feat: antd 主题改造 — 启用 cssVar、纯黑白 colorPrimary、统一 sidebar/滚动条/按钮样式
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -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 }} />
|
||||
|
||||
@@ -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}>
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user