Ant Design 组件
灵动桌面框架集成了 Ant Design 6(antd ^6.3.1),配合 @ant-design/cssinjs ^2.1.2 和 @ant-design/icons ^6.1.0,提供企业级 UI 组件。
全局配置
// src/App.tsx(节选)
import { ConfigProvider } from "antd";
import { StyleProvider } from "@ant-design/cssinjs";
import zhCN from "antd/locale/zh_CN";
import { getAntdTheme } from "@/theme/antdTheme";
<StyleProvider layer>
<ConfigProvider locale={zhCN} theme={getAntdTheme(resolved)}>
<ErrorBoundary>
<AppRouter />
</ErrorBoundary>
<GlobalNativeTooltip />
</ConfigProvider>
</StyleProvider>
locale={zhCN}:组件内置文案(分页、空状态、确认按钮等)使用简体中文theme={getAntdTheme(resolved)}:根据当前生效的主题返回lightTheme或darkTheme,两套配置定义在src/theme/antdTheme.ts,详见 主题切换<StyleProvider layer>:把 antd 运行时注入的样式放进 CSS 层@layer antd,让 Tailwind 工具类能覆盖 antd 组件样式,详见 TailwindCSS 样式
两套主题共享的 token(src/theme/antdTheme.ts):
const sharedToken: ThemeConfig["token"] = {
borderRadius: 6,
borderRadiusSM: 3,
borderRadiusLG: 8,
fontSize: 13,
controlHeight: 32,
controlHeightSM: 24,
controlHeightLG: 40,
};
组件级覆盖(sharedComponents)统一了 Button / Input / Select / Table 的圆角为 6、Modal 的 borderRadiusLG 为 12;Tooltip 的背景色和文字色按亮 / 暗主题分别配置。
常用布局
主布局(Sider + Header + Content)
// src/components/layout/AppLayout.tsx(节选)
import { Outlet, useNavigate } from "react-router-dom";
import { Layout, Button, theme as antdTheme } from "antd";
import { MenuFoldOutlined, MenuUnfoldOutlined, SettingOutlined } from "@ant-design/icons";
import { useAppStore } from "@/store";
import { Sidebar } from "./Sidebar";
import { WindowControls } from "./WindowControls";
import { ThemeToggle } from "@/components/ui/ThemeToggle";
const { Header, Sider, Content } = Layout;
export function AppLayout({ headerExtra }: AppLayoutProps) {
const { sidebarCollapsed, toggleSidebar } = useAppStore();
const { token } = antdTheme.useToken();
const navigate = useNavigate();
return (
<Layout style={{ height: "100vh" }}>
<Sider
collapsed={sidebarCollapsed}
collapsedWidth={60}
width={220}
style={{ background: token.colorBgContainer, borderRight: `1px solid var(--border)` }}
>
<Sidebar />
</Sider>
<Layout>
<Header style={{ padding: 0, height: "var(--header-height)", display: "flex", alignItems: "center" }}>
<Button
type="text"
icon={sidebarCollapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
onClick={toggleSidebar}
/>
<DragRegion />
<div style={{ display: "flex", alignItems: "center" }}>
{headerExtra}
<ThemeToggle />
<Button type="text" icon={<SettingOutlined />} onClick={() => navigate("/settings")} title="设置" />
<WindowControls />
</div>
</Header>
<Content style={{ padding: 24, overflow: "auto", background: token.colorBgLayout }}>
<Outlet />
</Content>
</Layout>
</Layout>
);
}
要点:
- 侧边栏折叠状态由 Zustand 的
sidebarCollapsed控制(不是Sider自带的collapsible触发器),折叠按钮在顶栏左侧 - 窗口是无边框的(
tauri.conf.json中"decorations": false),顶栏中间的DragRegion按下时调用startDragging()拖动窗口、双击调用toggleMaximize();右侧WindowControls自绘最小化 / 最大化 / 关闭按钮 headerExtra属性可以在主题切换按钮之前插入额外操作- 颜色取自
antdTheme.useToken()的 token 或var(--xxx)CSS 变量,不写死色值
表单
import { Form, Input, Button, message } from "antd";
import { configApi } from "@/lib/api";
function SettingsForm() {
const [form] = Form.useForm();
const onFinish = async (values: { key: string; value: string }) => {
try {
await configApi.set(values.key, values.value);
message.success("保存成功");
} catch (e) {
message.error(String(e));
}
};
return (
<Form form={form} layout="vertical" onFinish={onFinish}>
<Form.Item name="key" label="配置项" rules={[{ required: true }]}>
<Input placeholder="输入配置键名" />
</Form.Item>
<Form.Item name="value" label="值" rules={[{ required: true }]}>
<Input.TextArea rows={3} />
</Form.Item>
<Button type="primary" htmlType="submit">保存</Button>
</Form>
);
}
configApi 定义在 src/lib/api/config.ts,提供 getAll()、get(key)、set(key, value)、delete(key) 四个方法,分别对应 Rust Command get_all_config / get_config / set_config / delete_config。
表格
// src/pages/settings/index.tsx(节选)
import { Table, Tag } from "antd";
import type { AppConfig } from "@/types";
const columns = [
{
title: "配置键",
dataIndex: "key",
key: "key",
render: (text: string) => <Tag color="blue">{text}</Tag>,
},
{ title: "配置值", dataIndex: "value", key: "value" },
];
<Table
columns={columns}
dataSource={configs}
rowKey="key"
loading={loading}
pagination={false}
size="small"
/>
AppConfig 只有 key 和 value 两个字段(src/types/config.ts),因此用 key 作为 rowKey。
原生 title 提示统一
App.tsx 中挂载了 GlobalNativeTooltip(src/components/GlobalNativeTooltip.tsx):它在捕获阶段监听 mouseover,把任意 HTML 元素上的原生 title 属性「借走」存到 data-native-title,再用受控的 antd Tooltip 在该元素位置显示气泡,同时补上 aria-label。
因此写普通按钮时直接加 title="设置" 即可,悬停效果与 antd Tooltip 一致并跟随主题;antd 组件自己的 Tooltip / Modal 不受影响。
图标
框架同时使用 Lucide React(lucide-react ^0.577.0)和 Ant Design Icons:
import { Home, Info, Sun, Moon, Monitor } from "lucide-react";
import { MenuFoldOutlined, SettingOutlined, SyncOutlined } from "@ant-design/icons";
<Home size={18} />
<Moon size={16} />
<SettingOutlined />
<SyncOutlined spin={checking} />
现有代码中,侧边栏菜单、主题切换、窗口控制按钮用 Lucide;顶栏折叠 / 设置按钮、检查更新按钮用 Ant Design Icons。