refactor(desktop/ui): 组件库对齐 shadcn 画廊基调
按已定稿的组件画廊精修 ui/ 基础组件(均走主题令牌,亮/暗自适应): - Button:主按钮去掉霓虹 shadow-glow(玩具感残留)→ 扁平 + active 微缩; 次按钮落到 ink-850 表面。 - Input/Textarea/Select:底色对齐表面(ink-900) + 焦点环改 ring-2 ring-brand/25(更柔的聚焦)。 - 新增 Table/Tr/Td:细分隔线 + 弱化表头 + 行 hover,运维/数据场景标准呈现。 - EmptyState/Skeleton/Badge/Tabs/Card 已主题化,沿用。 页面经 ui/ 桶引入,组件升级即全页生效。tsc + 生产构建 + vitest 48 全过。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,8 +9,8 @@ const base =
|
||||
"inline-flex items-center justify-center gap-1.5 rounded-md font-medium transition select-none disabled:cursor-not-allowed disabled:opacity-40 focus:outline-none focus-visible:ring-2 focus-visible:ring-brand/50";
|
||||
|
||||
const variants: Record<Variant, string> = {
|
||||
primary: "bg-brand text-white hover:bg-brand-500 active:bg-brand-600 shadow-glow",
|
||||
secondary: "border border-line bg-ink-800 text-slate-200 hover:bg-ink-700 hover:border-ink-600",
|
||||
primary: "bg-brand text-white hover:bg-brand-500 active:scale-[0.98]",
|
||||
secondary: "border border-line bg-ink-850 text-slate-200 hover:bg-ink-800 hover:border-ink-600",
|
||||
ghost: "text-slate-400 hover:bg-ink-800 hover:text-slate-200",
|
||||
danger: "border border-danger/50 text-danger hover:bg-danger/10",
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ import { cn } from "./cn";
|
||||
// 注意:基类不含宽度。宽度由调用方决定(Field 内为 flex-col 自动撑满,
|
||||
// 或显式 w-full / flex-1 / w-16),避免 w-full 与 flex-1/w-16 冲突塌陷。
|
||||
const fieldBase =
|
||||
"rounded-md border border-line bg-ink-950 text-sm text-slate-200 placeholder:text-slate-600 transition focus:border-brand focus:outline-none focus:ring-1 focus:ring-brand/40 disabled:opacity-50";
|
||||
"rounded-md border border-line bg-ink-900 text-sm text-slate-200 placeholder:text-slate-600 transition focus:border-brand focus:outline-none focus:ring-2 focus:ring-brand/25 disabled:opacity-50";
|
||||
|
||||
export function Input({ className, ...rest }: InputHTMLAttributes<HTMLInputElement>) {
|
||||
return <input className={cn(fieldBase, "h-9 px-3", className)} {...rest} />;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { cn } from "./cn";
|
||||
|
||||
// 轻量数据表格:细分隔线、左对齐表头(弱化)、行 hover。运维/数据场景的标准呈现。
|
||||
// 用法:<Table cols={["任务","状态","耗时"]}><Tr>...<Td>...</Td></Tr></Table>
|
||||
|
||||
export function Table({ cols, children, className }: { cols: ReactNode[]; children: ReactNode; className?: string }) {
|
||||
return (
|
||||
<table className={cn("w-full border-collapse text-xs", className)}>
|
||||
<thead>
|
||||
<tr>
|
||||
{cols.map((c, i) => (
|
||||
<th key={i} className="border-b border-line px-2.5 py-2 text-left font-medium text-slate-500">
|
||||
{c}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>{children}</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
|
||||
export function Tr({ children, onClick, className }: { children: ReactNode; onClick?: () => void; className?: string }) {
|
||||
return (
|
||||
<tr onClick={onClick} className={cn("border-b border-line/70 transition hover:bg-ink-800", onClick && "cursor-pointer", className)}>
|
||||
{children}
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
export function Td({ children, className }: { children: ReactNode; className?: string }) {
|
||||
return <td className={cn("px-2.5 py-2 align-middle text-slate-300", className)}>{children}</td>;
|
||||
}
|
||||
@@ -4,6 +4,7 @@ export { Button } from "./Button";
|
||||
export { Input, Textarea, Select, Field } from "./Input";
|
||||
export { Card, Panel } from "./Card";
|
||||
export { Badge, Dot } from "./Badge";
|
||||
export { Table, Tr, Td } from "./Table";
|
||||
export { Tabs, type TabDef } from "./Tabs";
|
||||
export { Skeleton, EmptyState } from "./Feedback";
|
||||
export { Dialog, ConfirmFooter } from "./Dialog";
|
||||
|
||||
Reference in New Issue
Block a user