feat: antd 主题改造 — 启用 cssVar、纯黑白 colorPrimary、统一 sidebar/滚动条/按钮样式

This commit is contained in:
2026-06-05 16:01:54 +08:00
parent db40d04dc5
commit 85abc2a515
10 changed files with 88 additions and 70 deletions

View File

@@ -6,7 +6,6 @@ import "overlayscrollbars/styles/overlayscrollbars.css";
import { OverlayScrollbarsComponent, type OverlayScrollbarsComponentRef } from "overlayscrollbars-react";
import { useCallback, useRef, useState } from "react";
import { useIsDark } from "../../shared/hooks/use-is-dark";
import { useChatScroll } from "./use-chat-scroll";
interface ChatScrollAreaProps {
@@ -19,7 +18,6 @@ export function ChatScrollArea({ children, messages, status }: ChatScrollAreaPro
const scrollRef = useRef<HTMLDivElement>(null);
const osRef = useRef<OverlayScrollbarsComponentRef>(null);
const [viewportElement, setViewportElement] = useState<HTMLDivElement | null>(null);
const isDark = useIsDark();
const handleOsInitialized = useCallback(() => {
const os = osRef.current;
@@ -42,7 +40,7 @@ export function ChatScrollArea({ children, messages, status }: ChatScrollAreaPro
overflow: { x: "hidden", y: "scroll" },
scrollbars: {
autoHide: "move",
theme: isDark ? "os-theme-custom-dark" : "os-theme-custom",
theme: "os-theme-custom",
},
}}
ref={osRef}

View File

@@ -7,7 +7,6 @@ import { useMemo, useState } from "react";
import type { Conversation } from "../../../../shared/api";
import { SidebarGroup } from "../../../shared/components/SidebarGroup";
import { useIsDark } from "../../../shared/hooks/use-is-dark";
import { GROUP_LABELS, groupByDate } from "../../../shared/utils/date-group";
import { ConversationCard } from "./ConversationCard";
@@ -30,7 +29,6 @@ export function ConversationList({
}: ConversationListProps) {
const [inputText, setInputText] = useState("");
const [appliedSearch, setAppliedSearch] = useState("");
const isDark = useIsDark();
const filteredConversations = useMemo(() => {
if (!appliedSearch) return conversations;
@@ -60,7 +58,7 @@ export function ConversationList({
overflow: { x: "hidden", y: "scroll" },
scrollbars: {
autoHide: "move",
theme: isDark ? "os-theme-custom-dark" : "os-theme-custom",
theme: "os-theme-custom",
},
}}
>

View File

@@ -1,7 +1,7 @@
import type { ReactNode } from "react";
import { CopyOutlined } from "@ant-design/icons";
import { Button, message } from "antd";
import { App, Button } from "antd";
import { useCallback, useEffect, useState } from "react";
import { codeToHtml } from "shiki";
@@ -14,6 +14,7 @@ interface CodeBlockProps {
}
export function CodeBlock({ children, className: _className, isStreaming }: CodeBlockProps) {
const { message } = App.useApp();
const isDark = useIsDark();
const [highlighted, setHighlighted] = useState<null | string>(null);
const { codeText, lang } = extractCode(children);
@@ -23,7 +24,7 @@ export function CodeBlock({ children, className: _className, isStreaming }: Code
() => message.success("已复制"),
() => message.error("复制失败"),
);
}, [codeText]);
}, [codeText, message]);
useEffect(() => {
if (isStreaming || !codeText) return;
@@ -57,7 +58,7 @@ export function CodeBlock({ children, className: _className, isStreaming }: Code
<div className="code-block">
<div className="code-block-header">
<span className="code-block-lang">{lang}</span>
<Button icon={<CopyOutlined />} onClick={handleCopy} size="small" type="text" />
<Button className="btn-dimmed" icon={<CopyOutlined />} onClick={handleCopy} size="small" type="text" />
</div>
{highlighted ? (
<div className="code-block-body" dangerouslySetInnerHTML={{ __html: highlighted }} />

View File

@@ -18,7 +18,7 @@ const STATUS_MAP: Record<MaterialStatus, { color: string; label: string }> = {
export function MaterialCard({ material, onDelete, onSelect, selected }: MaterialCardProps) {
const statusInfo = STATUS_MAP[material.status];
const className = selected ? "material-list-item material-list-item--selected" : "material-list-item";
const className = selected ? "app-sidebar-list-item app-sidebar-list-item--selected" : "app-sidebar-list-item";
return (
<Flex align="center" className={className} gap="small" justify="space-between" onClick={onSelect}>

View File

@@ -13,7 +13,6 @@ import { useMemo, useState } from "react";
import type { Material } from "../types";
import { SidebarGroup } from "../../../shared/components/SidebarGroup";
import { useIsDark } from "../../../shared/hooks/use-is-dark";
import { GROUP_LABELS, groupByDate } from "../../../shared/utils/date-group";
import { MaterialCard } from "./MaterialCard";
@@ -37,7 +36,6 @@ 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;
@@ -74,7 +72,7 @@ export function MaterialList({ loading, materials, onAddClick, onDelete, onSelec
overflow: { x: "hidden", y: "scroll" },
scrollbars: {
autoHide: "move",
theme: isDark ? "os-theme-custom-dark" : "os-theme-custom",
theme: "os-theme-custom",
},
}}
>

View File

@@ -1,7 +1,7 @@
import type { TableColumnsType, TableProps } from "antd";
import { DeleteOutlined, EditOutlined, InboxOutlined, LoginOutlined, RedoOutlined } from "@ant-design/icons";
import { Button, Popconfirm, Space, Table, Tag } from "antd";
import { Button, Popconfirm, Space, Table, Tag, theme } from "antd";
import { useMemo } from "react";
import { useNavigate } from "react-router";
@@ -40,6 +40,7 @@ export function ProjectTable({
sortOrder,
}: ProjectTableProps) {
const navigate = useNavigate();
const { token: themeToken } = theme.useToken();
const columns = useMemo<TableColumnsType<Project>>(
() => [
@@ -60,7 +61,7 @@ export function ProjectTable({
if (record.status === "archived") {
return <Tag></Tag>;
}
return <Tag color="blue"></Tag>;
return <Tag color={themeToken.colorPrimary}></Tag>;
},
title: "状态",
width: 90,
@@ -137,7 +138,7 @@ export function ProjectTable({
width: 260,
},
],
[navigate, onEdit, onArchive, onRestore, onDelete, sortBy, sortOrder],
[navigate, onEdit, onArchive, onRestore, onDelete, sortBy, sortOrder, themeToken.colorPrimary],
);
const handleTableChange: TableProps<Project>["onChange"] = (pagination, _filters, sorter) => {