feat(gui): add Design Token system and theme configuration (U1)

- Create tokens.css with CSS custom properties for colors, spacing,
  radius, fonts, shadows, transitions, and code theme
- Create theme.ts mapping tokens to Ant Design Vue ConfigProvider
- Create styles/index.ts as unified entry point
- Inject theme into App.vue ConfigProvider
- Import styles in main.ts

Primary color unified to #7c3aed (purple gradient brand color).
This commit is contained in:
chiguyong 2026-06-13 02:32:29 +08:00
parent 09698d7a06
commit 2988d3768e
5 changed files with 228 additions and 1 deletions

View File

@ -1,5 +1,5 @@
<template>
<a-config-provider :locale="zhCN">
<a-config-provider :locale="zhCN" :theme="themeConfig">
<AppLayout />
</a-config-provider>
</template>
@ -8,6 +8,7 @@
import { ConfigProvider as AConfigProvider } from 'ant-design-vue'
import zhCN from 'ant-design-vue/es/locale/zh_CN'
import AppLayout from './components/layout/AppLayout.vue'
import { themeConfig } from './styles'
</script>
<style>

View File

@ -1,6 +1,7 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import 'ant-design-vue/dist/reset.css'
import './styles'
import App from './App.vue'
import router from './router'

View File

@ -0,0 +1,8 @@
/**
* Fischer AgentKit Styles Entry
*
* Import this module to load all design tokens and theme configuration.
*/
import './tokens.css'
export { themeConfig } from './theme'

View File

@ -0,0 +1,81 @@
/**
* Ant Design Vue Theme Token Mapping
*
* Maps CSS custom properties to Ant Design Vue ConfigProvider theme tokens.
* This ensures antd components use the same design tokens as custom components.
*/
import type { ThemeConfig } from 'ant-design-vue/es/config-provider/context'
export const themeConfig: ThemeConfig = {
token: {
// Brand
colorPrimary: '#7c3aed',
colorInfo: '#7c3aed',
// Semantic
colorSuccess: '#10b981',
colorWarning: '#f59e0b',
colorError: '#ef4444',
// Text
colorText: '#171717',
colorTextSecondary: '#525252',
colorTextTertiary: '#737373',
colorTextQuaternary: '#a3a3a3',
// Background
colorBgContainer: '#ffffff',
colorBgLayout: '#fafafa',
colorBgElevated: '#ffffff',
// Border
colorBorder: '#e5e5e5',
colorBorderSecondary: '#f0f0f0',
// Font
fontSize: 14,
fontSizeSM: 12,
fontSizeLG: 16,
fontSizeXL: 20,
// Radius
borderRadius: 8,
borderRadiusSM: 6,
borderRadiusLG: 12,
// Spacing
marginXS: 4,
marginSM: 8,
margin: 16,
marginMD: 16,
marginLG: 24,
marginXL: 32,
// Shadow
boxShadow: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
boxShadowSecondary: '0 4px 6px -1px rgba(0, 0, 0, 0.07), 0 2px 4px -2px rgba(0, 0, 0, 0.05)',
// Control
controlHeight: 32,
controlHeightSM: 24,
controlHeightLG: 40,
},
components: {
Menu: {
itemSelectedBg: '#ede9fe',
itemSelectedColor: '#7c3aed',
itemHoverBg: '#f5f3ff',
itemHoverColor: '#7c3aed',
itemColor: '#525252',
} as Record<string, unknown>,
Tabs: {
itemSelectedColor: '#7c3aed',
itemHoverColor: '#6d28d9',
} as Record<string, unknown>,
Select: {
colorPrimary: '#7c3aed',
colorPrimaryHover: '#6d28d9',
} as Record<string, unknown>,
},
}

View File

@ -0,0 +1,136 @@
/**
* Fischer AgentKit Design Tokens
*
* CSS Custom Properties as the single source of truth.
* Ant Design Vue theme tokens are mapped from these values in theme.ts.
*/
:root {
/* ── Brand Colors ── */
--color-primary: #7c3aed;
--color-primary-hover: #6d28d9;
--color-primary-active: #5b21b6;
--color-primary-light: #ede9fe;
--color-primary-bg: #f5f3ff;
/* ── Gradient ── */
--gradient-brand: linear-gradient(135deg, #7c3aed 0%, #1e1b4b 100%);
/* ── Semantic Colors ── */
--color-success: #10b981;
--color-success-light: #d1fae5;
--color-warning: #f59e0b;
--color-warning-light: #fef3c7;
--color-error: #ef4444;
--color-error-light: #fee2e2;
--color-info: #3b82f6;
--color-info-light: #dbeafe;
/* ── Neutral / Gray Scale ── */
--color-gray-50: #fafafa;
--color-gray-100: #f5f5f5;
--color-gray-200: #e5e5e5;
--color-gray-300: #d4d4d4;
--color-gray-400: #a3a3a3;
--color-gray-500: #737373;
--color-gray-600: #525252;
--color-gray-700: #404040;
--color-gray-800: #262626;
--color-gray-900: #171717;
/* ── Background ── */
--bg-primary: #ffffff;
--bg-secondary: #fafafa;
--bg-tertiary: #f5f5f5;
--bg-elevated: #ffffff;
--bg-code: #282c34;
/* ── Foreground / Text ── */
--text-primary: #171717;
--text-secondary: #525252;
--text-tertiary: #737373;
--text-placeholder: #a3a3a3;
--text-inverse: #ffffff;
--text-code: #abb2bf;
/* ── Border ── */
--border-color: #e5e5e5;
--border-color-hover: #d4d4d4;
--border-color-active: var(--color-primary);
--border-color-split: #f0f0f0;
/* ── Spacing ── */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
/* ── Border Radius ── */
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 8px;
--radius-xl: 12px;
--radius-full: 9999px;
/* ── Font Size ── */
--font-xs: 12px;
--font-sm: 13px;
--font-base: 14px;
--font-md: 16px;
--font-lg: 20px;
--font-xl: 24px;
/* ── Font Weight ── */
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
/* ── Line Height ── */
--leading-tight: 1.25;
--leading-normal: 1.5;
--leading-relaxed: 1.75;
/* ── Shadow ── */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.07), 0 2px 4px -2px rgba(0, 0, 0, 0.05);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.04);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 8px 10px -6px rgba(0, 0, 0, 0.04);
/* ── Transition ── */
--transition-fast: 150ms ease;
--transition-normal: 200ms ease;
--transition-slow: 300ms ease;
/* ── Z-Index ── */
--z-dropdown: 1000;
--z-sticky: 1020;
--z-fixed: 1030;
--z-modal-backdrop: 1040;
--z-modal: 1050;
--z-popover: 1060;
--z-tooltip: 1070;
/* ── Layout ── */
--topnav-height: 48px;
--sidebar-width: 280px;
--quadrant-min-size: 320px;
/* ── Code Theme (One Dark Pro) ── */
--code-bg: #282c34;
--code-fg: #abb2bf;
--code-keyword: #c678dd;
--code-string: #98c379;
--code-number: #d19a66;
--code-comment: #5c6370;
--code-function: #61afef;
--code-variable: #e06c75;
--code-type: #e5c07b;
--code-added-bg: rgba(16, 185, 129, 0.15);
--code-removed-bg: rgba(239, 68, 68, 0.15);
}