feat: 收集箱侧边栏UI美化 — 自定义滚动条、隐藏空分组、优化列表项间距

This commit is contained in:
2026-06-03 22:31:49 +08:00
parent 525278870f
commit dc7d9e83b8
3 changed files with 22 additions and 32 deletions

View File

@@ -5,11 +5,10 @@ import { type ReactNode, useState } from "react";
interface MaterialGroupProps {
children: ReactNode;
count: number;
emptyText?: string;
label: string;
}
export function MaterialGroup({ children, count, emptyText, label }: MaterialGroupProps) {
export function MaterialGroup({ children, count, label }: MaterialGroupProps) {
const [collapsed, setCollapsed] = useState(false);
return (
@@ -23,17 +22,7 @@ export function MaterialGroup({ children, count, emptyText, label }: MaterialGro
({count})
</Typography.Text>
</div>
{!collapsed && (
<div className="app-inbox-group-content">
{count === 0 && emptyText ? (
<Typography.Text className="app-inbox-group-empty" type="secondary">
{emptyText}
</Typography.Text>
) : (
children
)}
</div>
)}
{!collapsed && <div className="app-inbox-group-content">{children}</div>}
</div>
);
}

View File

@@ -6,10 +6,13 @@ import {
PlusOutlined,
} from "@ant-design/icons";
import { Button, Empty, Segmented, Skeleton } from "antd";
import "overlayscrollbars/styles/overlayscrollbars.css";
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
import { useMemo, useState } from "react";
import type { Material } from "../types";
import { useIsDark } from "../../../shared/hooks/use-is-dark";
import { MaterialCard } from "./MaterialCard";
import { MaterialGroup } from "./MaterialGroup";
@@ -84,6 +87,7 @@ type FilterValue = (typeof STATUS_FILTER_OPTIONS)[number]["value"];
export function MaterialList({ loading, materials, onAddClick, onDelete, onSelect, selectedId }: MaterialListProps) {
const [filterStatus, setFilterStatus] = useState<FilterValue>("all");
const isDark = useIsDark();
const filteredMaterials = useMemo(() => {
if (filterStatus === "all") return materials;
@@ -106,8 +110,6 @@ export function MaterialList({ loading, materials, onAddClick, onDelete, onSelec
[materials],
);
const showAllGroups = filterStatus === "all";
return (
<div className="app-inbox-sidebar">
<div className="app-inbox-sidebar-header">
@@ -116,7 +118,16 @@ export function MaterialList({ loading, materials, onAddClick, onDelete, onSelec
</Button>
<Segmented block onChange={(value) => setFilterStatus(value)} options={segmentedOptions} value={filterStatus} />
</div>
<div className="app-inbox-list">
<OverlayScrollbarsComponent
className="app-inbox-list"
options={{
overflow: { x: "hidden", y: "scroll" },
scrollbars: {
autoHide: "move",
theme: isDark ? "os-theme-custom-dark" : "os-theme-custom",
},
}}
>
{loading ? (
<Skeleton active paragraph={{ rows: 6 }} title={false} />
) : materials.length === 0 ? (
@@ -125,14 +136,9 @@ export function MaterialList({ loading, materials, onAddClick, onDelete, onSelec
<Empty description="当前筛选条件下无素材" image={Empty.PRESENTED_IMAGE_SIMPLE} />
) : (
groupedMaterials.map((group) => {
if (!showAllGroups && group.items.length === 0) return null;
if (group.items.length === 0) return null;
return (
<MaterialGroup
count={group.items.length}
emptyText="暂无"
key={group.key}
label={GROUP_LABELS[group.key]}
>
<MaterialGroup count={group.items.length} key={group.key} label={GROUP_LABELS[group.key]}>
{group.items.map((material) => (
<MaterialCard
key={material.id}
@@ -146,7 +152,7 @@ export function MaterialList({ loading, materials, onAddClick, onDelete, onSelec
);
})
)}
</div>
</OverlayScrollbarsComponent>
</div>
);
}