Admin portal mobile responsiveness: tables, grids, and nav

- Tab nav: scroll isolation, icon-only on mobile, accessible titles
- IAM table: hide 6 columns on mobile, responsive padding
- User detail: responsive grid (1→2→3 cols), role select sizing
- Dashboard: responsive stats grid, hide Actor/Target cols on mobile
- Audit log: responsive column hiding and padding
- Actions menu: role submenu repositions below trigger on mobile
- Config: narrower filter select on mobile

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Kyle 2026-03-11 02:54:23 +08:00
parent db16a07f68
commit 84b3083987
6 changed files with 68 additions and 67 deletions

View File

@ -25,7 +25,7 @@ export default function AdminDashboardPage() {
return ( return (
<div className="px-4 md:px-6 py-6 space-y-6 animate-fade-in"> <div className="px-4 md:px-6 py-6 space-y-6 animate-fade-in">
{/* Stats grid */} {/* Stats grid */}
<div className="grid gap-2.5 grid-cols-2 lg:grid-cols-5"> <div className="grid gap-2.5 grid-cols-2 md:grid-cols-3 lg:grid-cols-5">
{isLoading ? ( {isLoading ? (
Array.from({ length: 5 }).map((_, i) => ( Array.from({ length: 5 }).map((_, i) => (
<Card key={i}> <Card key={i}>
@ -94,10 +94,10 @@ export default function AdminDashboardPage() {
<table className="w-full text-sm"> <table className="w-full text-sm">
<thead> <thead>
<tr className="border-b border-border bg-card-elevated/50"> <tr className="border-b border-border bg-card-elevated/50">
<th className="px-5 py-2.5 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-2.5 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium">
Username Username
</th> </th>
<th className="px-5 py-2.5 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-2.5 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium">
When When
</th> </th>
</tr> </tr>
@ -111,8 +111,8 @@ export default function AdminDashboardPage() {
idx % 2 === 0 ? '' : 'bg-card-elevated/25' idx % 2 === 0 ? '' : 'bg-card-elevated/25'
)} )}
> >
<td className="px-5 py-2.5 font-medium">{entry.username}</td> <td className="px-3 lg:px-5 py-2.5 font-medium">{entry.username}</td>
<td className="px-5 py-2.5 text-xs text-muted-foreground"> <td className="px-3 lg:px-5 py-2.5 text-xs text-muted-foreground">
{getRelativeTime(entry.last_login_at)} {getRelativeTime(entry.last_login_at)}
</td> </td>
</tr> </tr>
@ -142,16 +142,16 @@ export default function AdminDashboardPage() {
<table className="w-full text-sm"> <table className="w-full text-sm">
<thead> <thead>
<tr className="border-b border-border bg-card-elevated/50"> <tr className="border-b border-border bg-card-elevated/50">
<th className="px-5 py-2.5 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-2.5 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium">
Action Action
</th> </th>
<th className="px-5 py-2.5 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-2.5 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium hidden sm:table-cell">
Actor Actor
</th> </th>
<th className="px-5 py-2.5 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-2.5 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium hidden sm:table-cell">
Target Target
</th> </th>
<th className="px-5 py-2.5 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-2.5 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium">
When When
</th> </th>
</tr> </tr>
@ -165,7 +165,7 @@ export default function AdminDashboardPage() {
idx % 2 === 0 ? '' : 'bg-card-elevated/25' idx % 2 === 0 ? '' : 'bg-card-elevated/25'
)} )}
> >
<td className="px-5 py-2.5"> <td className="px-3 lg:px-5 py-2.5">
<span <span
className={cn( className={cn(
'text-[9px] px-1.5 py-0.5 rounded font-medium uppercase tracking-wide whitespace-nowrap', 'text-[9px] px-1.5 py-0.5 rounded font-medium uppercase tracking-wide whitespace-nowrap',
@ -175,15 +175,15 @@ export default function AdminDashboardPage() {
{entry.action} {entry.action}
</span> </span>
</td> </td>
<td className="px-5 py-2.5 text-xs font-medium"> <td className="px-3 lg:px-5 py-2.5 text-xs font-medium hidden sm:table-cell">
{entry.actor_username ?? ( {entry.actor_username ?? (
<span className="text-muted-foreground italic">system</span> <span className="text-muted-foreground italic">system</span>
)} )}
</td> </td>
<td className="px-5 py-2.5 text-xs text-muted-foreground"> <td className="px-3 lg:px-5 py-2.5 text-xs text-muted-foreground hidden sm:table-cell">
{entry.target_username ?? '—'} {entry.target_username ?? '—'}
</td> </td>
<td className="px-5 py-2.5 text-xs text-muted-foreground whitespace-nowrap"> <td className="px-3 lg:px-5 py-2.5 text-xs text-muted-foreground whitespace-nowrap">
{getRelativeTime(entry.created_at)} {getRelativeTime(entry.created_at)}
</td> </td>
</tr> </tr>

View File

@ -17,32 +17,33 @@ export default function AdminPortal() {
return ( return (
<div className="flex flex-col h-full animate-fade-in"> <div className="flex flex-col h-full animate-fade-in">
{/* Portal header with tab navigation */} {/* Portal header with tab navigation */}
<div className="shrink-0 border-b bg-card"> <div className="shrink-0 border-b bg-card overflow-hidden">
<div className="px-4 md:px-6 h-16 flex items-center gap-4"> <div className="px-3 md:px-6 h-14 md:h-16 flex items-center gap-2 md:gap-4">
<div className="flex items-center gap-2 mr-6"> <div className="flex items-center gap-2 mr-2 md:mr-6 shrink-0">
<div className="p-1.5 rounded-md bg-red-500/10"> <div className="p-1.5 rounded-md bg-red-500/10">
<ShieldCheck className="h-5 w-5 text-red-400" /> <ShieldCheck className="h-5 w-5 text-red-400" />
</div> </div>
<h1 className="font-heading text-xl md:text-2xl font-bold tracking-tight">Admin Portal</h1> <h1 className="font-heading text-base md:text-2xl font-bold tracking-tight">Admin</h1>
</div> </div>
{/* Horizontal tab navigation */} {/* Horizontal tab navigation */}
<nav className="flex items-center gap-1 h-full"> <nav className="flex items-center gap-1 h-full min-w-0 overflow-x-auto">
{tabs.map(({ label, path, icon: Icon }) => { {tabs.map(({ label, path, icon: Icon }) => {
const isActive = location.pathname.startsWith(path); const isActive = location.pathname.startsWith(path);
return ( return (
<NavLink <NavLink
key={path} key={path}
to={path} to={path}
title={label}
className={cn( className={cn(
'flex items-center gap-2 px-4 h-full text-sm font-medium transition-colors duration-150 border-b-2 -mb-px', 'flex items-center gap-1.5 px-2.5 md:px-4 h-full text-sm font-medium transition-colors duration-150 border-b-2 -mb-px whitespace-nowrap',
isActive isActive
? 'text-accent border-accent' ? 'text-accent border-accent'
: 'text-muted-foreground hover:text-foreground border-transparent' : 'text-muted-foreground hover:text-foreground border-transparent'
)} )}
> >
<Icon className="h-4 w-4" /> <Icon className="h-4 w-4 shrink-0" />
{label} <span className="hidden sm:inline">{label}</span>
</NavLink> </NavLink>
); );
})} })}

View File

@ -75,7 +75,7 @@ export default function ConfigPage() {
<Filter className="h-3.5 w-3.5 text-muted-foreground" /> <Filter className="h-3.5 w-3.5 text-muted-foreground" />
<span className="text-xs text-muted-foreground">Filter:</span> <span className="text-xs text-muted-foreground">Filter:</span>
</div> </div>
<div className="w-52"> <div className="w-36 sm:w-52">
<Select <Select
value={filterAction} value={filterAction}
onChange={(e) => { onChange={(e) => {
@ -129,22 +129,22 @@ export default function ConfigPage() {
<table className="w-full text-sm"> <table className="w-full text-sm">
<thead> <thead>
<tr className="border-b border-border bg-card-elevated/50"> <tr className="border-b border-border bg-card-elevated/50">
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium">
Time Time
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium hidden sm:table-cell">
Actor Actor
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium">
Action Action
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium hidden sm:table-cell">
Target Target
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium hidden lg:table-cell">
IP IP
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium hidden lg:table-cell">
Detail Detail
</th> </th>
</tr> </tr>
@ -158,15 +158,15 @@ export default function ConfigPage() {
idx % 2 === 0 ? '' : 'bg-card-elevated/25' idx % 2 === 0 ? '' : 'bg-card-elevated/25'
)} )}
> >
<td className="px-5 py-3 text-xs text-muted-foreground whitespace-nowrap"> <td className="px-3 lg:px-5 py-3 text-xs text-muted-foreground whitespace-nowrap">
{getRelativeTime(entry.created_at)} {getRelativeTime(entry.created_at)}
</td> </td>
<td className="px-5 py-3 text-xs font-medium"> <td className="px-3 lg:px-5 py-3 text-xs font-medium hidden sm:table-cell">
{entry.actor_username ?? ( {entry.actor_username ?? (
<span className="text-muted-foreground italic">system</span> <span className="text-muted-foreground italic">system</span>
)} )}
</td> </td>
<td className="px-5 py-3"> <td className="px-3 lg:px-5 py-3">
<span <span
className={cn( className={cn(
'text-[9px] px-1.5 py-0.5 rounded font-medium uppercase tracking-wide whitespace-nowrap', 'text-[9px] px-1.5 py-0.5 rounded font-medium uppercase tracking-wide whitespace-nowrap',
@ -176,13 +176,13 @@ export default function ConfigPage() {
{entry.action} {entry.action}
</span> </span>
</td> </td>
<td className="px-5 py-3 text-xs text-muted-foreground"> <td className="px-3 lg:px-5 py-3 text-xs text-muted-foreground hidden sm:table-cell">
{entry.target_username ?? '—'} {entry.target_username ?? '—'}
</td> </td>
<td className="px-5 py-3 text-xs text-muted-foreground font-mono"> <td className="px-3 lg:px-5 py-3 text-xs text-muted-foreground font-mono hidden lg:table-cell">
{entry.ip_address ?? '—'} {entry.ip_address ?? '—'}
</td> </td>
<td className="px-5 py-3 text-xs text-muted-foreground max-w-xs truncate"> <td className="px-3 lg:px-5 py-3 text-xs text-muted-foreground max-w-xs truncate hidden lg:table-cell">
{entry.detail ?? '—'} {entry.detail ?? '—'}
</td> </td>
</tr> </tr>

View File

@ -125,7 +125,7 @@ export default function IAMPage() {
{/* User table */} {/* User table */}
<Card> <Card>
<CardHeader className="flex-row items-center justify-between gap-3"> <CardHeader className="flex-row items-center justify-between flex-wrap gap-2 md:gap-3">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<div className="p-1.5 rounded-md bg-accent/10"> <div className="p-1.5 rounded-md bg-accent/10">
<Users className="h-4 w-4 text-accent" /> <Users className="h-4 w-4 text-accent" />
@ -139,12 +139,12 @@ export default function IAMPage() {
value={searchQuery} value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)} onChange={(e) => setSearchQuery(e.target.value)}
placeholder="Search users..." placeholder="Search users..."
className="pl-8 h-8 w-48 text-xs" className="pl-8 h-8 w-32 sm:w-48 text-xs"
/> />
</div> </div>
<Button size="sm" onClick={() => setCreateOpen(true)}> <Button size="sm" onClick={() => setCreateOpen(true)}>
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />
Create User <span className="hidden sm:inline">Create User</span>
</Button> </Button>
</div> </div>
</CardHeader> </CardHeader>
@ -160,38 +160,38 @@ export default function IAMPage() {
{searchQuery ? 'No users match your search.' : 'No users found.'} {searchQuery ? 'No users match your search.' : 'No users found.'}
</p> </p>
) : ( ) : (
<div> <div className="overflow-x-auto">
<table className="w-full text-sm"> <table className="w-full text-sm">
<thead> <thead>
<tr className="border-b border-border bg-card-elevated/50"> <tr className="border-b border-border bg-card-elevated/50">
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium">
Username Username
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium hidden lg:table-cell">
Umbral Name Umbral Name
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium hidden lg:table-cell">
Email Email
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium">
Role Role
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium">
Status Status
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium hidden lg:table-cell">
Last Login Last Login
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium hidden lg:table-cell">
MFA MFA
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium hidden lg:table-cell">
Sessions Sessions
</th> </th>
<th className="px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium hidden lg:table-cell">
Created Created
</th> </th>
<th className="px-5 py-3 text-right text-[11px] uppercase tracking-wider text-muted-foreground font-medium"> <th className="px-3 lg:px-5 py-3 text-right text-[11px] uppercase tracking-wider text-muted-foreground font-medium">
Actions Actions
</th> </th>
</tr> </tr>
@ -211,17 +211,17 @@ export default function IAMPage() {
) )
)} )}
> >
<td className="px-5 py-3 font-medium">{user.username}</td> <td className="px-3 lg:px-5 py-3 font-medium">{user.username}</td>
<td className="px-5 py-3 text-muted-foreground text-xs"> <td className="px-3 lg:px-5 py-3 text-muted-foreground text-xs hidden lg:table-cell">
{user.umbral_name || user.username} {user.umbral_name || user.username}
</td> </td>
<td className="px-5 py-3 text-muted-foreground text-xs"> <td className="px-3 lg:px-5 py-3 text-muted-foreground text-xs hidden lg:table-cell">
{user.email || '—'} {user.email || '—'}
</td> </td>
<td className="px-5 py-3"> <td className="px-3 lg:px-5 py-3">
<RoleBadge role={user.role} /> <RoleBadge role={user.role} />
</td> </td>
<td className="px-5 py-3"> <td className="px-3 lg:px-5 py-3">
<span <span
className={cn( className={cn(
'text-[9px] px-1.5 py-0.5 rounded font-medium uppercase tracking-wide', 'text-[9px] px-1.5 py-0.5 rounded font-medium uppercase tracking-wide',
@ -233,10 +233,10 @@ export default function IAMPage() {
{user.is_active ? 'Active' : 'Disabled'} {user.is_active ? 'Active' : 'Disabled'}
</span> </span>
</td> </td>
<td className="px-5 py-3 text-muted-foreground text-xs"> <td className="px-3 lg:px-5 py-3 text-muted-foreground text-xs hidden lg:table-cell">
{user.last_login_at ? getRelativeTime(user.last_login_at) : '—'} {user.last_login_at ? getRelativeTime(user.last_login_at) : '—'}
</td> </td>
<td className="px-5 py-3"> <td className="px-3 lg:px-5 py-3 hidden lg:table-cell">
{user.totp_enabled ? ( {user.totp_enabled ? (
<span className="text-[9px] px-1.5 py-0.5 rounded font-medium uppercase tracking-wide bg-green-500/15 text-green-400"> <span className="text-[9px] px-1.5 py-0.5 rounded font-medium uppercase tracking-wide bg-green-500/15 text-green-400">
On On
@ -249,13 +249,13 @@ export default function IAMPage() {
<span className="text-muted-foreground text-xs"></span> <span className="text-muted-foreground text-xs"></span>
)} )}
</td> </td>
<td className="px-5 py-3 text-muted-foreground text-xs tabular-nums"> <td className="px-3 lg:px-5 py-3 text-muted-foreground text-xs tabular-nums hidden lg:table-cell">
{user.active_sessions} {user.active_sessions}
</td> </td>
<td className="px-5 py-3 text-muted-foreground text-xs"> <td className="px-3 lg:px-5 py-3 text-muted-foreground text-xs hidden lg:table-cell">
{getRelativeTime(user.created_at)} {getRelativeTime(user.created_at)}
</td> </td>
<td className="px-5 py-3 text-right" onClick={(e) => e.stopPropagation()}> <td className="px-3 lg:px-5 py-3 text-right" onClick={(e) => e.stopPropagation()}>
<UserActionsMenu user={user} currentUsername={authStatus?.username ?? null} /> <UserActionsMenu user={user} currentUsername={authStatus?.username ?? null} />
</td> </td>
</tr> </tr>

View File

@ -147,7 +147,7 @@ export default function UserActionsMenu({ user, currentUsername }: UserActionsMe
{roleSubmenuOpen && ( {roleSubmenuOpen && (
<div <div
className="absolute right-full top-0 z-50 min-w-[180px] rounded-lg border bg-card shadow-lg py-1" className="absolute left-0 top-full sm:left-auto sm:right-full sm:top-0 z-50 min-w-[180px] rounded-lg border bg-card shadow-lg py-1"
onMouseEnter={() => setRoleSubmenuOpen(true)} onMouseEnter={() => setRoleSubmenuOpen(true)}
onMouseLeave={() => setRoleSubmenuOpen(false)} onMouseLeave={() => setRoleSubmenuOpen(false)}
> >

View File

@ -71,15 +71,15 @@ export default function UserDetailSection({ userId, onClose }: UserDetailSection
if (isLoading) { if (isLoading) {
return ( return (
<div className="grid grid-cols-4 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 md:gap-4">
<Card className="col-span-1"> <Card>
<CardContent className="p-5 space-y-3"> <CardContent className="p-5 space-y-3">
{Array.from({ length: 5 }).map((_, i) => ( {Array.from({ length: 5 }).map((_, i) => (
<Skeleton key={i} className="h-5 w-full" /> <Skeleton key={i} className="h-5 w-full" />
))} ))}
</CardContent> </CardContent>
</Card> </Card>
<Card className="col-span-1"> <Card>
<CardContent className="p-5 space-y-3"> <CardContent className="p-5 space-y-3">
{Array.from({ length: 7 }).map((_, i) => ( {Array.from({ length: 7 }).map((_, i) => (
<Skeleton key={i} className="h-5 w-full" /> <Skeleton key={i} className="h-5 w-full" />
@ -109,9 +109,9 @@ export default function UserDetailSection({ userId, onClose }: UserDetailSection
if (!user) return null; if (!user) return null;
return ( return (
<div className="grid grid-cols-4 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 md:gap-4">
{/* User Information (read-only) */} {/* User Information (read-only) */}
<Card className="col-span-1"> <Card>
<CardHeader className="flex-row items-center justify-between pb-3"> <CardHeader className="flex-row items-center justify-between pb-3">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<div className="p-1.5 rounded-md bg-accent/10"> <div className="p-1.5 rounded-md bg-accent/10">
@ -152,7 +152,7 @@ export default function UserDetailSection({ userId, onClose }: UserDetailSection
</Card> </Card>
{/* Security & Permissions */} {/* Security & Permissions */}
<Card className="col-span-1"> <Card>
<CardHeader className="pb-3"> <CardHeader className="pb-3">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<div className="p-1.5 rounded-md bg-accent/10"> <div className="p-1.5 rounded-md bg-accent/10">
@ -168,7 +168,7 @@ export default function UserDetailSection({ userId, onClose }: UserDetailSection
<Select <Select
value={user.role} value={user.role}
onChange={(e) => handleRoleChange(e.target.value as UserRole)} onChange={(e) => handleRoleChange(e.target.value as UserRole)}
className="h-6 text-xs py-0 px-1.5 w-auto min-w-[120px]" className="h-6 text-xs py-0 px-1.5 w-auto min-w-[100px] sm:min-w-[120px]"
disabled={updateRole.isPending} disabled={updateRole.isPending}
> >
<option value="admin">Admin</option> <option value="admin">Admin</option>
@ -221,7 +221,7 @@ export default function UserDetailSection({ userId, onClose }: UserDetailSection
</Card> </Card>
{/* Sharing Stats */} {/* Sharing Stats */}
<Card className="col-span-1"> <Card>
<CardHeader className="pb-3"> <CardHeader className="pb-3">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<div className="p-1.5 rounded-md bg-accent/10"> <div className="p-1.5 rounded-md bg-accent/10">