fix(web): 控制台界面细节与 uhd_web 控件规范对齐
- 顶栏搜索移进右侧玻璃胶囊;输入框改淡玻璃(边线 0.46 → 0.16,悬停加深,聚焦 / 出错保留光晕) - 新增 SegmentedControl(滑动 seg-thumb),替换站点、下载、订阅、文件、智能体列表及对话框里的实心选中块;Tabs 改为同一枚滑块 - 开关型按钮统一 outline + aria-pressed 选中外观;页头 / 工具栏次操作描边、图标钮描边圆;文件排序改 Select;下载总速度加标签 - 分页一页放得下时只留总数、空列表不渲染、按容器宽度收起按钮 - 运行状态存储区重排;智能体列表页与会话页共用外壳路由,标题与左栏不再重挂载 - 站点卡片「⋯」不再单独换行;设置导航、状态计数、多选条件改玻璃选中态 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
8ff1817845
commit
c9b4ceb301
32 files changed
+753
-639
No files matched your search
@@ -32,6 +32,7 @@ import { SubscriptionCard, SubscriptionRow } from "~/components/subscriptions/ov
|
||||
import { SubscriptionFormDialog } from "~/components/subscriptions/subscription-form.tsx";
|
||||
import { Button } from "~/components/ui/button.tsx";
|
||||
import { Pagination } from "~/components/ui/pagination.tsx";
|
||||
import { SegmentedControl } from "~/components/ui/segmented.tsx";
|
||||
import { cn } from "~/lib/utils.ts";
|
||||
import { legacyRedirectLoader } from "./redirects.ts";
|
||||
|
||||
@@ -74,27 +75,13 @@ function Pills<T extends string>({
|
||||
items: { value: T | ""; label: string; count?: number }[];
|
||||
}) {
|
||||
return (
|
||||
<div role="tablist" aria-label={label} className="flex min-w-0 gap-1 overflow-x-auto scroll-bleed">
|
||||
{items.map((it) => (
|
||||
<button
|
||||
key={it.value || "all"}
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={value === it.value}
|
||||
onClick={() => onChange(it.value)}
|
||||
className={cn(
|
||||
"inline-flex h-8 shrink-0 cursor-pointer items-center gap-1.5 rounded-full border px-3 text-sm font-medium whitespace-nowrap transition-colors duration-micro",
|
||||
value === it.value
|
||||
? "pill-selected text-foreground"
|
||||
: "border-transparent text-muted-foreground hover:bg-foreground/[0.06] hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
{it.label}
|
||||
{it.count !== undefined ? (
|
||||
<span className="text-meta text-muted-foreground tabular-nums">{it.count}</span>
|
||||
) : null}
|
||||
</button>
|
||||
))}
|
||||
<div className="min-w-0 overflow-x-auto scroll-bleed">
|
||||
<SegmentedControl<T | "all">
|
||||
label={label}
|
||||
value={value || "all"}
|
||||
onChange={(v) => onChange(v === "all" ? "" : v)}
|
||||
options={items.map((it) => ({ value: it.value || "all", label: it.label, count: it.count }))}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -207,7 +194,7 @@ export default function SubscriptionsPage() {
|
||||
title="订阅"
|
||||
actions={
|
||||
<>
|
||||
<Button asChild variant="ghost" size="sm">
|
||||
<Button asChild variant="outline" size="sm">
|
||||
<Link to={consolePath("rules")}>
|
||||
<ListChecks />
|
||||
规则
|
||||
@@ -235,46 +222,25 @@ export default function SubscriptionsPage() {
|
||||
<div className="flex items-center gap-1">
|
||||
{calendar ? null : (
|
||||
<Button
|
||||
variant={selecting ? "secondary" : "ghost"}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
aria-pressed={selecting}
|
||||
onClick={() => (selecting ? exitSelect() : setSelecting(true))}
|
||||
>
|
||||
{selecting ? <X /> : null}
|
||||
{selecting ? "退出批量" : "批量"}
|
||||
</Button>
|
||||
)}
|
||||
<fieldset className="m-0 flex rounded-full border border-border p-0.5" aria-label="视图">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
aria-label="卡片视图"
|
||||
aria-pressed={!calendar && view === "card"}
|
||||
className={cn("rounded-full", !calendar && view === "card" && "bg-foreground/[0.08]")}
|
||||
onClick={() => setView("card")}
|
||||
>
|
||||
<LayoutGrid />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
aria-label="列表视图"
|
||||
aria-pressed={!calendar && view === "list"}
|
||||
className={cn("rounded-full", !calendar && view === "list" && "bg-foreground/[0.08]")}
|
||||
onClick={() => setView("list")}
|
||||
>
|
||||
<List />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
aria-label="日历"
|
||||
aria-pressed={calendar}
|
||||
className={cn("rounded-full", calendar && "bg-foreground/[0.08]")}
|
||||
onClick={() => f.set("view", "calendar")}
|
||||
>
|
||||
<CalendarDays />
|
||||
</Button>
|
||||
</fieldset>
|
||||
<SegmentedControl
|
||||
label="视图"
|
||||
value={calendar ? "calendar" : view}
|
||||
onChange={(x) => (x === "calendar" ? f.set("view", "calendar") : setView(x))}
|
||||
options={[
|
||||
{ value: "card", label: "", title: "卡片视图", icon: <LayoutGrid /> },
|
||||
{ value: "list", label: "", title: "列表视图", icon: <List /> },
|
||||
{ value: "calendar", label: "", title: "日历", icon: <CalendarDays /> },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{calendar ? (
|
||||
@@ -459,7 +425,7 @@ export default function SubscriptionsPage() {
|
||||
) : (
|
||||
renderItems(visible)
|
||||
)}
|
||||
{items.length > 0 || query.hasNextPage ? <Pagination {...paged.pagination} /> : null}
|
||||
{items.length > 0 || query.hasNextPage ? <Pagination {...paged.pagination} hideSingle /> : null}
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
Reference in new issue
Block a user