refactor: tighten shadcn admin ui polish

This commit is contained in:
hailin
2026-07-02 11:02:59 +08:00
parent 399a5bdb73
commit dbb1ceb0e0
17 changed files with 62 additions and 76 deletions

View File

@@ -35,43 +35,41 @@ export function AppDataTable<Row>({
onRowClick
}: AppDataTableProps<Row>) {
return (
<div className="overflow-hidden rounded-lg border border-border bg-surface">
{toolbar ? <div className="border-b border-border p-3">{toolbar}</div> : null}
<div className="overflow-hidden rounded-lg border border-border bg-card shadow-sm">
{toolbar ? <div className="border-b border-border bg-muted/20 p-3">{toolbar}</div> : null}
{rows.length === 0 ? (
<div className="p-4">
<AppEmptyState title={emptyTitle} description={emptyDescription} />
</div>
) : (
<div className="overflow-x-auto">
<Table className={tableClassName}>
<TableHeader>
<TableRow>
<Table className={tableClassName}>
<TableHeader className="bg-muted/30">
<TableRow>
{columns.map((column) => (
<TableHead key={column.key} className={column.className}>
{column.header}
</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{rows.map((row) => (
<TableRow
key={getRowKey(row)}
className={cn(onRowClick ? 'cursor-pointer' : undefined)}
onClick={() => onRowClick?.(row)}
>
{columns.map((column) => (
<TableHead key={column.key} className={column.className}>
{column.header}
</TableHead>
<TableCell key={column.key} className={column.className}>
{column.cell(row)}
</TableCell>
))}
</TableRow>
</TableHeader>
<TableBody>
{rows.map((row) => (
<TableRow
key={getRowKey(row)}
className={cn(onRowClick ? 'cursor-pointer' : undefined)}
onClick={() => onRowClick?.(row)}
>
{columns.map((column) => (
<TableCell key={column.key} className={column.className}>
{column.cell(row)}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</div>
))}
</TableBody>
</Table>
)}
{footer ? <div className="border-t border-border px-3 py-2">{footer}</div> : null}
{footer ? <div className="border-t border-border bg-muted/20 px-3 py-2">{footer}</div> : null}
</div>
)
}

View File

@@ -8,7 +8,7 @@ type AppEmptyStateProps = {
export function AppEmptyState({ title, description, action }: AppEmptyStateProps) {
return (
<div className="rounded-lg border border-dashed border-border bg-surface px-4 py-8 text-center">
<div className="rounded-lg border border-dashed border-border bg-background px-4 py-8 text-center">
<p className="text-sm font-medium text-foreground">{title}</p>
{description ? <p className="mt-1 text-sm text-muted-foreground">{description}</p> : null}
{action ? <div className="mt-4 flex justify-center">{action}</div> : null}

View File

@@ -1,6 +1,6 @@
import type * as React from 'react'
import { Card, CardContent, CardHeader } from '@/components/ui/card'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
type AppSectionProps = {
title: string
@@ -14,8 +14,8 @@ export function AppSection({ title, description, action, children }: AppSectionP
<Card>
<CardHeader className="flex flex-row items-start justify-between gap-3">
<div>
<h2 className="text-sm font-semibold text-foreground">{title}</h2>
{description ? <p className="mt-1 text-sm text-muted-foreground">{description}</p> : null}
<CardTitle className="text-sm">{title}</CardTitle>
{description ? <CardDescription>{description}</CardDescription> : null}
</div>
{action}
</CardHeader>

View File

@@ -19,14 +19,14 @@ export function AppTopbar() {
<Badge variant="info">本地环境</Badge>
<Separator orientation="vertical" className="h-5" />
<Button variant="ghost" size="icon" aria-label="通知">
<Bell className="size-4" />
<Bell data-icon="inline-start" />
</Button>
<Button variant="ghost" className="gap-2">
<UserRound className="size-4" />
<UserRound data-icon="inline-start" />
<span>{user?.display_name || user?.username || '当前用户'}</span>
</Button>
<Button variant="outline" className="gap-2" onClick={() => void logout()}>
<LogOut className="size-4" />
<LogOut data-icon="inline-start" />
<span>退出</span>
</Button>
</div>