style(web): 文件管理目录树改成与主面板同款卡片(FIX-7)
目录树放进同背景、边框、圆角的卡片,两卡间距与上下边缘对齐;头部「目录」+ 折叠钮与工具栏第一行等高, 折叠钮从主面板工具栏挪到这里;拖宽与折叠记忆保留,手机抽屉不变。 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
3c17fa3356
commit
faf1552607
2 files changed
+39
-46
No files matched your search
@@ -61,7 +61,7 @@ export function DirTree({
|
|||||||
<nav aria-label="登记目录" className={cn("space-y-4", className)}>
|
<nav aria-label="登记目录" className={cn("space-y-4", className)}>
|
||||||
{groups.map((g) => (
|
{groups.map((g) => (
|
||||||
<section key={g.title} aria-label={g.title}>
|
<section key={g.title} aria-label={g.title}>
|
||||||
<p className="mb-1 px-2 text-micro font-semibold tracking-[0.15em] text-muted-foreground uppercase">
|
<p className="mb-1 px-2 text-micro font-semibold tracking-[0.15em] text-muted-foreground/75 uppercase">
|
||||||
{g.title}
|
{g.title}
|
||||||
</p>
|
</p>
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ function readLastLoc(): Loc | null {
|
|||||||
const hnrPathsOf = (list: FileEntry[]) =>
|
const hnrPathsOf = (list: FileEntry[]) =>
|
||||||
list.filter((e) => e.download && (e.download.hnr !== "satisfied" || e.status === "downloading")).map((e) => e.path);
|
list.filter((e) => e.download && (e.download.hnr !== "satisfied" || e.status === "downloading")).map((e) => e.path);
|
||||||
|
|
||||||
/** 折叠后的左栏:44px 图标条(登记目录 + 回收站) */
|
/** 折叠后的左栏:52px 圆角卡片里的图标条(登记目录 + 回收站),展开钮与主面板工具栏第一行对齐 */
|
||||||
function TreeRail({
|
function TreeRail({
|
||||||
roots,
|
roots,
|
||||||
current,
|
current,
|
||||||
@@ -207,7 +207,7 @@ function TreeRail({
|
|||||||
trashCount: string;
|
trashCount: string;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<nav aria-label="登记目录" className="flex flex-col items-center gap-1 py-2">
|
<nav aria-label="登记目录" className="flex flex-col items-center gap-1 py-2.5">
|
||||||
<Button variant="ghost" size="icon-sm" aria-label="展开目录树" title="展开目录树" onClick={onExpand}>
|
<Button variant="ghost" size="icon-sm" aria-label="展开目录树" title="展开目录树" onClick={onExpand}>
|
||||||
<PanelLeftOpen />
|
<PanelLeftOpen />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -883,29 +883,45 @@ export default function FilesPage() {
|
|||||||
<>
|
<>
|
||||||
{/* 顶栏已显示页面名,这里只给读屏留标题,把高度让给列表 */}
|
{/* 顶栏已显示页面名,这里只给读屏留标题,把高度让给列表 */}
|
||||||
<h1 className="sr-only">文件管理</h1>
|
<h1 className="sr-only">文件管理</h1>
|
||||||
<div className={cn("flex h-[calc(100dvh-3.5rem)] min-w-0", mobile && "flex-col p-3")}>
|
<div className={cn("flex h-[calc(100dvh-3.5rem)] min-w-0 gap-3 p-3", mobile && "flex-col")}>
|
||||||
{/* 桌面左栏:贴着侧边栏的整高目录树(可折叠、可拖宽,宽度记在本机) */}
|
{/* 桌面左栏:与主面板同款的圆角卡片(同背景、边框、圆角),上下与主面板对齐;可折叠、可拖宽,宽度记在本机 */}
|
||||||
{!mobile ? (
|
{!mobile ? (
|
||||||
<aside
|
<aside
|
||||||
className="pg-chrome pg-chrome-side relative flex shrink-0 flex-col border-r"
|
className="relative flex shrink-0"
|
||||||
style={{ width: treeOpen ? treeW : 44 }}
|
style={{ width: treeOpen ? treeW : 52 }}
|
||||||
aria-label="登记目录与目录树"
|
aria-label="登记目录与目录树"
|
||||||
>
|
>
|
||||||
|
<div className="pg-slab flex min-h-0 w-full flex-col overflow-hidden rounded-2xl">
|
||||||
{treeOpen ? (
|
{treeOpen ? (
|
||||||
<>
|
<>
|
||||||
{/* 左侧留出全站侧栏折叠钮的位置 */}
|
{/* 头部一行与主面板工具栏第一行等高(同 px-3 py-2.5 + 按钮高度) */}
|
||||||
<div className="flex h-11 shrink-0 items-center border-b border-[var(--shell-border)] pr-2 pl-6">
|
<div className="flex shrink-0 items-center gap-1.5 px-3 py-2.5">
|
||||||
<span className="text-label font-semibold tracking-[0.18em] text-muted-foreground uppercase">
|
<Button
|
||||||
登记目录
|
variant="ghost"
|
||||||
</span>
|
size="icon-sm"
|
||||||
{filesMockEnabled() ? (
|
aria-label="折叠目录树"
|
||||||
<StatusBadge tone="warning" className="ml-auto">
|
title="折叠目录树"
|
||||||
演示数据
|
onClick={() => setTreeOpenStored(false)}
|
||||||
</StatusBadge>
|
>
|
||||||
) : null}
|
<PanelLeftClose />
|
||||||
|
</Button>
|
||||||
|
<span className="min-w-0 flex-1 truncate text-sm font-medium text-foreground">目录</span>
|
||||||
|
{filesMockEnabled() ? <StatusBadge tone="warning">演示数据</StatusBadge> : null}
|
||||||
</div>
|
</div>
|
||||||
<div className="min-h-0 flex-1 overflow-y-auto p-2">{tree}</div>
|
<div className="min-h-0 flex-1 overflow-y-auto px-2 pb-2">{tree}</div>
|
||||||
{/* biome-ignore lint/a11y/useSemanticElements: 可拖动、可键盘调整的分隔条,hr 不能获焦 */}
|
</>
|
||||||
|
) : (
|
||||||
|
<TreeRail
|
||||||
|
roots={rootList}
|
||||||
|
current={rootId}
|
||||||
|
onSelect={go}
|
||||||
|
onExpand={() => setTreeOpenStored(true)}
|
||||||
|
trashCount={trashCount}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{treeOpen ? (
|
||||||
|
// biome-ignore lint/a11y/useSemanticElements: 可拖动、可键盘调整的分隔条,hr 不能获焦
|
||||||
<div
|
<div
|
||||||
role="separator"
|
role="separator"
|
||||||
aria-orientation="vertical"
|
aria-orientation="vertical"
|
||||||
@@ -932,29 +948,15 @@ export default function FilesPage() {
|
|||||||
window.addEventListener("pointermove", move);
|
window.addEventListener("pointermove", move);
|
||||||
window.addEventListener("pointerup", upH);
|
window.addEventListener("pointerup", upH);
|
||||||
}}
|
}}
|
||||||
className="absolute inset-y-0 -right-1 z-10 w-2 cursor-col-resize hover:bg-foreground/[0.08] focus-visible:bg-foreground/[0.12] focus-visible:outline-none"
|
// 放在两张卡片之间的缝里
|
||||||
|
className="absolute inset-y-3 -right-2.5 z-10 w-2 cursor-col-resize rounded-full hover:bg-foreground/[0.08] focus-visible:bg-foreground/[0.12] focus-visible:outline-none"
|
||||||
/>
|
/>
|
||||||
</>
|
) : null}
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<div aria-hidden className="h-11 shrink-0 border-b border-[var(--shell-border)]" />
|
|
||||||
<TreeRail
|
|
||||||
roots={rootList}
|
|
||||||
current={rootId}
|
|
||||||
onSelect={go}
|
|
||||||
onExpand={() => setTreeOpenStored(true)}
|
|
||||||
trashCount={trashCount}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</aside>
|
</aside>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<section
|
<section
|
||||||
className={cn(
|
className="pg-slab relative flex min-h-[24rem] min-w-0 flex-1 flex-col overflow-hidden rounded-2xl"
|
||||||
"pg-slab relative flex min-h-[24rem] min-w-0 flex-1 flex-col overflow-hidden rounded-2xl",
|
|
||||||
!mobile && "m-3",
|
|
||||||
)}
|
|
||||||
aria-label="目录内容"
|
aria-label="目录内容"
|
||||||
>
|
>
|
||||||
{/* 工具栏 */}
|
{/* 工具栏 */}
|
||||||
@@ -1001,15 +1003,6 @@ export default function FilesPage() {
|
|||||||
) : (
|
) : (
|
||||||
<div className="space-y-2 border-b border-border px-3 py-2.5">
|
<div className="space-y-2 border-b border-border px-3 py-2.5">
|
||||||
<div className="flex min-w-0 items-center gap-1.5">
|
<div className="flex min-w-0 items-center gap-1.5">
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="icon-sm"
|
|
||||||
aria-label={treeOpen ? "折叠目录树" : "展开目录树"}
|
|
||||||
title={treeOpen ? "折叠目录树" : "展开目录树"}
|
|
||||||
onClick={() => setTreeOpenStored(!treeOpen)}
|
|
||||||
>
|
|
||||||
{treeOpen ? <PanelLeftClose /> : <PanelLeftOpen />}
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon-sm"
|
size="icon-sm"
|
||||||
|
|||||||
Reference in new issue
Block a user