Files
gt-agent-company/.claude/DESIGN-SYSTEM.md
sexygoat 91d7d4c21f
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 1m27s
fix: 优化界面以及更新接口
2026-04-15 11:54:43 +08:00

22 KiB

GT Agent Company - UI/UX Design System

Project Type: Mobile-First SaaS Application (UniApp Vue3) Tech Stack: Vue 3 + UnoCSS + uView Plus Platforms: H5 / WeChat Mini Program / Native App Last Updated: 2026-03-18


🎨 Design Philosophy

Style Direction: Modern Professional SaaS with Xiaomi-Inspired Branding Primary Pattern: Glassmorphism + Flat Design + Vibrant & Block-based Target Audience: B2B/B2C professionals seeking agent management solutions

Core Design Principles

  1. Mobile-First: Design for 375px viewport first, enhance for larger screens
  2. Performance-Focused: Minimize animations, optimize images, lazy load
  3. Accessibility-Driven: WCAG 2.1 AA minimum, touch-friendly targets
  4. Consistent Branding: Xiaomi-inspired orange (#ff6700) as primary identity
  5. Cross-Platform: Unified experience across H5, WeChat, and native apps

🎯 Product Type Recommendations

Based on analysis: SaaS (General) + B2B Service

Recommended Landing Pattern: Hero + Features + CTA Dashboard Style: Data-Dense + Real-Time Monitoring Key Considerations:

  • Balance modern feel with clarity
  • Focus on strong CTAs (Call-to-Actions)
  • Credibility essential - show clear ROI messaging
  • Social proof and trust elements mandatory

🌈 Color Palette

Brand Colors (Blue Theme)

// Primary Brand Colors
--brand-primary: #1677ff;        // Primary CTA, hover states
--brand-primary-light: #4096ff;  // Lighter variant
--brand-primary-dark: #0958d9;   // Pressed states
--brand-secondary: #1e293b;       // Dark Gray (headings)
--brand-accent: #ffffff;         // White (emphasis)

Semantic Colors (Light Mode)

// Primary Theme Colors
--theme-primary: #1677ff;        // Blue (Trust + Energy)
--theme-secondary: #1e293b;      // Dark Gray
--theme-accent: #ffffff;         // White

// Status Colors
--theme-success: #52c41a;        // Green (Success states)
--theme-warning: #faad14;        // Amber (Warnings)
--theme-error: #ff4d4f;          // Red (Errors)
--theme-info: #1677ff;          // Info (same as primary)

// Text Hierarchy
--theme-main-color: #212121;    // Primary text
--theme-content-color: #666666;  // Body text
--theme-tips-color: #999999;    // Secondary text
--theme-light-color: #cccccc;   // Muted text
--theme-disabled-color: #f5f5f5; // Disabled states

// Backgrounds
--theme-bg-color: #fafafa;      // Main background
--theme-bg-color-secondary: #ffffff; // Card backgrounds
--theme-bg-gradient-start: #1677ff;
--theme-bg-gradient-end: #4096ff;

// Borders
--theme-border-color: #e8e8e8;  // Borders, dividers

Dark Mode Colors

.theme-dark {
  --brand-primary: #4b9cff;     // Blue (lighter for dark mode)
  --brand-primary-light: #69b1ff;
  --brand-primary-dark: #1668dc;
  --theme-success: #73d13d;
  --theme-warning: #ffc53d;
  --theme-error: #f56c6c;

  // Text (High Contrast Required)
  --theme-main-color: #ffffff;
  --theme-content-color: #b0b8c1;
  --theme-tips-color: #8a8f95;
  --theme-light-color: #6c757d;
  --theme-disabled-color: #495057;

  // Backgrounds
  --theme-bg-color: #1a1a1a;
  --theme-bg-color-secondary: #2d2d2d;
}

UnoCSS Theme Integration

// uno.config.ts already configured:
theme: {
  colors: {
    'primary': 'var(--theme-primary)',
    'success': 'var(--theme-success)',
    'warning': 'var(--theme-warning)',
    'error': 'var(--theme-error)',
    'text-main': 'var(--theme-main-color)',
    'text-content': 'var(--theme-content-color)',
    'text-tips': 'var(--theme-tips-color)',
  }
}

// Usage in templates:
<div class="bg-primary text-white">
<p class="text-content">Body text</p>

Color Contrast Requirements

CRITICAL: Maintain minimum 4.5:1 contrast ratio for normal text

Good Combinations:

  • #4c484f (text-main) on #ffffff → 7.2:1
  • #ffffff on #ff6700 (primary) → 4.1:1
  • #333333 on #ffffff → 12.6:1

Bad Combinations:

  • #bd9e84 (light) on #ffffff → 2.4:1 (TOO LOW)
  • Use text-light only for decorative text, not critical content

📝 Typography

Font Pairing: Modern Professional

Stack: Plus Jakarta Sans (Sans + Sans) Character: Friendly, modern, SaaS, clean, approachable, professional

/* Import Google Fonts */
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700&display=swap');

/* Fallback for platforms without custom fonts */
font-family: 'Plus Jakarta Sans', 'PingFang SC', 'Microsoft YaHei', sans-serif;

Font Scale (Mobile-First)

// Base: 16px (rem baseline)

// Headings
--font-h1: 32px;      // Hero headings
--font-h2: 28px;      // Section titles
--font-h3: 24px;      // Card headers
--font-h4: 20px;      // Subsection titles
--font-h5: 18px;      // Small headings
--font-h6: 16px;      // Labels

// Body
--font-body: 16px;    // MINIMUM for mobile readability
--font-body-small: 14px;
--font-caption: 12px; // Fine print only

// Line Heights
--line-height-tight: 1.2;   // Headings
--line-height-normal: 1.5;  // Body text (MANDATORY)
--line-height-relaxed: 1.75; // Long-form content

Typography Hierarchy

<!-- UnoCSS Classes -->
<h1 class="text-32px font-700 leading-tight text-main">
  Hero Heading
</h1>

<h2 class="text-28px font-600 leading-tight text-main">
  Section Title
</h2>

<p class="text-16px font-400 leading-normal text-content">
  Body text content. Minimum 16px on mobile.
</p>

<span class="text-14px text-tips">
  Secondary information
</span>

<small class="text-12px text-light">
  Fine print only - not for critical content
</small>

Font Weight Usage

  • 300 Light: Decorative text only
  • 400 Regular: Body text, descriptions
  • 500 Medium: Emphasized body text
  • 600 SemiBold: Headings, buttons
  • 700 Bold: Hero titles, important CTAs

⚠️ RULE: Never use font weight < 400 for critical content


📐 Layout & Spacing

Container Widths

// Mobile-first breakpoints (UnoCSS)
--container-xs: 100%;       // < 640px
--container-sm: 640px;      // sm:
--container-md: 768px;      // md:
--container-lg: 1024px;     // lg:
--container-xl: 1280px;     // xl:

// Recommended max-width for content
--max-width-content: 1200px;

Spacing Scale (UnoCSS rem-based)

// Base: 1rem = 16px (4px increments)

--space-1: 0.25rem;   // 4px
--space-2: 0.5rem;    // 8px  (Minimum touch spacing)
--space-3: 0.75rem;   // 12px
--space-4: 1rem;      // 16px (Base unit)
--space-6: 1.5rem;    // 24px (Section spacing)
--space-8: 2rem;      // 32px (Component gaps)
--space-12: 3rem;     // 48px (Large sections)
--space-16: 4rem;     // 64px (Hero sections)

// UnoCSS Usage:
<div class="p-4">        <!-- 16px padding -->
<div class="gap-2">      <!-- 8px gap -->
<div class="mt-8 mb-6">  <!-- 32px top, 24px bottom -->

Grid System

<!-- 12-column responsive grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  <div class="col-span-1">Card 1</div>
  <div class="col-span-1">Card 2</div>
  <div class="col-span-1">Card 3</div>
</div>

<!-- Common layouts -->
<div class="flex flex-col md:flex-row gap-4">
  <aside class="w-full md:w-64">Sidebar</aside>
  <main class="flex-1">Content</main>
</div>

Safe Area Handling

// Custom UnoCSS rule already configured:
.pb-safe {
  padding-bottom: env(safe-area-inset-bottom);
}

// Use for bottom navigation:
<view class="fixed bottom-0 pb-safe">
  Bottom Navigation
</view>

🎯 Components & Patterns

Touch Targets (CRITICAL)

MANDATORY: Minimum 44x44px for all interactive elements

<!-- ✅ GOOD: Proper touch target -->
<button class="min-h-44px min-w-44px center">
  <i class="i-mdi-home w-24px h-24px"></i>
</button>

<!-- ❌ BAD: Too small -->
<button class="w-32px h-32px">
  <i class="i-mdi-home"></i>
</button>

<!-- Touch spacing between adjacent buttons -->
<div class="flex gap-2">  <!-- Minimum 8px gap -->
  <button class="min-h-44px">Button 1</button>
  <button class="min-h-44px">Button 2</button>
</div>

Button Styles

<!-- Primary CTA (Orange) -->
<button class="
  bg-primary text-white
  px-6 py-3 rounded-8px
  min-h-44px
  font-600 text-16px
  transition-colors duration-200
  hover:bg-[#e65a00]
  active:bg-[#e65a00]
  cursor-pointer
">
  确认提交
</button>

<!-- Secondary Button -->
<button class="
  bg-transparent border-2 border-primary text-primary
  px-6 py-3 rounded-8px
  min-h-44px
  font-600
  transition-all duration-200
  hover:bg-primary hover:text-white
  cursor-pointer
">
  取消
</button>

<!-- Disabled State -->
<button class="
  bg-text-disabled text-white
  px-6 py-3 rounded-8px
  cursor-not-allowed
  opacity-60
" disabled>
  Loading...
</button>

Card Components (Glassmorphism)

<!-- Light Mode Glass Card -->
<view class="
  bg-white/80
  backdrop-blur-md
  border border-gray-200
  rounded-16px
  p-6
  shadow-lg
">
  <text class="text-20px font-600 text-main">Card Title</text>
  <text class="text-14px text-content mt-2">Card content</text>
</view>

<!-- Dark Mode Glass Card -->
<view class="
  dark:bg-white/10
  dark:backdrop-blur-md
  dark:border-white/20
  rounded-16px
  p-6
">
  Content
</view>

Icon Usage (CRITICAL)

NEVER use emoji as UI icons (🎨 🚀 ⚙️) ALWAYS use SVG icons from UnoCSS preset-icons

<!-- ✅ GOOD: SVG icons -->
<i class="i-mdi-home w-24px h-24px text-primary"></i>
<i class="i-mdi-settings w-24px h-24px"></i>

<!-- Custom local icons -->
<i class="i-my-icons-preview-open w-24px h-24px"></i>

<!-- ❌ BAD: Emoji icons -->
<span>🏠 首页</span>  <!-- DON'T DO THIS -->

Navigation Bar (Floating)

<!-- ✅ GOOD: Floating navbar with proper spacing -->
<view class="
  fixed top-4 left-4 right-4
  bg-white/90 backdrop-blur-md
  rounded-full
  px-6 py-3
  shadow-lg
  z-50
">
  <view class="flex justify-between items-center">
    <text class="font-600 text-18px">Logo</text>
    <i class="i-mdi-menu w-24px h-24px cursor-pointer"></i>
  </view>
</view>

<!-- Account for navbar height in content -->
<view class="pt-72px">  <!-- top-4 + navbar-height + gap -->
  Main content starts here
</view>

Form Inputs

<!-- Accessible form input -->
<view class="mb-4">
  <label for="email" class="block text-14px font-500 text-main mb-2">
    邮箱地址
  </label>
  <input
    id="email"
    type="email"
    inputmode="email"
    class="
      w-full px-4 py-3 min-h-44px
      bg-white border-2 border-gray-200
      rounded-8px
      text-16px
      focus:border-primary focus:outline-none
      transition-colors duration-200
    "
    placeholder="输入您的邮箱"
  />
  <!-- Error state -->
  <text class="text-12px text-error mt-1" role="alert">
    请输入有效的邮箱地址
  </text>
</view>

🎭 Animation & Transitions

Duration Guidelines

// Speed mapping (prefer faster)
--duration-instant: 0ms;        // No animation
--duration-fast: 150ms;         // Micro-interactions (hover, focus)
--duration-normal: 200ms;       // Standard transitions
--duration-medium: 300ms;       // Maximum for UI (sliding panels)
--duration-slow: 500ms;         // AVOID - too sluggish
<!-- ✅ GOOD: Fast color transition -->
<button class="
  bg-primary
  transition-colors duration-200
  hover:bg-[#e65a00]
">
  Hover me
</button>

<!-- ✅ GOOD: Transform (GPU-accelerated) -->
<view class="
  transition-transform duration-200
  hover:scale-105
">
  Card
</view>

<!-- ❌ BAD: Slow transition -->
<view class="transition-all duration-1000">
  Too slow!
</view>

<!-- ❌ BAD: Animating width/height (causes reflow) -->
<view class="transition-width duration-300">
  Use transform instead
</view>

Reduced Motion (CRITICAL)

/* MANDATORY: Respect user preferences */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Loading States

<!-- Skeleton loader (preferred) -->
<view class="animate-pulse">
  <view class="h-20px bg-gray-200 rounded mb-4"></view>
  <view class="h-16px bg-gray-200 rounded w-3/4"></view>
</view>

<!-- Spinner (for buttons) -->
<button class="bg-primary text-white px-6 py-3" disabled>
  <i class="i-mdi-loading animate-spin w-20px h-20px"></i>
  Loading...
</button>

Hover States (CRITICAL)

RULE: Never use scale transforms that shift layout

<!-- ✅ GOOD: Stable hover (color change) -->
<view class="
  bg-white
  transition-colors duration-200
  hover:bg-gray-50
  cursor-pointer
">
  Stable hover
</view>

<!-- ❌ BAD: Layout shift -->
<view class="hover:scale-110">
  This shifts adjacent elements!
</view>

Accessibility Requirements

WCAG 2.1 AA Compliance (MANDATORY)

Color Contrast

  • Normal text (16px+): Minimum 4.5:1 ratio
  • Large text (24px+ or 18.5px bold): Minimum 3:1 ratio
  • UI components: Minimum 3:1 ratio
// ✅ Pre-validated combinations:
color: #4c484f; background: #ffffff; // 7.2:1
color: #ffffff; background: #ff6700; // 4.1:1
color: #333333; background: #ffffff; // 12.6:1

// ❌ Avoid:
color: #bd9e84; background: #ffffff; // 2.4:1 - TOO LOW

Keyboard Navigation

<!-- ✅ GOOD: Proper tab order and focus states -->
<button class="
  focus:outline-none
  focus:ring-2 focus:ring-primary focus:ring-offset-2
  transition-all duration-200
">
  Keyboard accessible
</button>

<!-- Custom interactive element -->
<view
  tabindex="0"
  role="button"
  @keydown.enter="handleAction"
  @keydown.space="handleAction"
  class="
    cursor-pointer
    focus:ring-2 focus:ring-primary
  "
>
  Keyboard accessible custom element
</view>

ARIA Labels

<!-- Icon-only buttons (MANDATORY) -->
<button aria-label="关闭菜单" class="p-2">
  <i class="i-mdi-close w-24px h-24px"></i>
</button>

<!-- Loading states -->
<view role="status" aria-live="polite">
  <i class="i-mdi-loading animate-spin"></i>
  <span class="sr-only">加载中...</span>
</view>

<!-- Error messages -->
<text role="alert" class="text-error">
  请填写必填项
</text>

Form Accessibility

<!-- ✅ GOOD: Proper label association -->
<view>
  <label for="username" class="block mb-2">
    用户名
  </label>
  <input
    id="username"
    type="text"
    aria-required="true"
    aria-invalid="false"
  />
</view>

<!-- ❌ BAD: Placeholder-only (no label) -->
<input placeholder="用户名" />

📱 Responsive Design

Mobile-First Breakpoints

// UnoCSS default breakpoints
xs:  0px      // Default (mobile)
sm:  640px    // Large mobile
md:  768px    // Tablet
lg:  1024px   // Desktop
xl:  1280px   // Large desktop
2xl: 1536px   // Extra large

// Common patterns:
<view class="
  grid
  grid-cols-1       /* Mobile: 1 column */
  sm:grid-cols-2    /* Tablet: 2 columns */
  lg:grid-cols-3    /* Desktop: 3 columns */
  gap-4
">

Viewport Meta (CRITICAL for H5)

<!-- index.html -->
<meta
  name="viewport"
  content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>

Responsive Typography

<!-- Responsive font sizes -->
<h1 class="
  text-24px sm:text-28px md:text-32px
  leading-tight
">
  Responsive Heading
</h1>

<!-- Responsive spacing -->
<view class="
  px-4 sm:px-6 md:px-8
  py-6 sm:py-8 md:py-12
">
  Responsive padding
</view>

Touch vs Hover

<!-- ✅ GOOD: Click/tap for primary interactions -->
<view @click="handleAction" class="cursor-pointer">
  Works on touch and mouse
</view>

<!-- ❌ BAD: Hover-only interactions -->
<view @mouseenter="showTooltip">
  Doesn't work on touch devices!
</view>

🚀 Performance Optimization

Image Optimization

<!-- ✅ GOOD: Lazy loading with placeholder -->
<image
  :src="imageUrl"
  mode="aspectFill"
  lazy-load
  class="w-full h-auto"
/>

<!-- Responsive images for H5 -->
<img
  :src="imageUrl"
  srcset="
    image-320w.webp 320w,
    image-640w.webp 640w,
    image-1280w.webp 1280w
  "
  sizes="(max-width: 640px) 100vw, 640px"
  loading="lazy"
  alt="描述性文本"
/>

Animation Performance

<!-- ✅ GOOD: GPU-accelerated properties only -->
<view class="transition-transform transition-opacity duration-200">
  Use transform and opacity
</view>

<!-- ❌ BAD: Triggers layout reflow -->
<view class="transition-width transition-height">
  Causes performance issues
</view>

Content Jumping Prevention

<!-- ✅ GOOD: Reserve space for async content -->
<view class="min-h-200px">
  <template v-if="loading">
    <view class="animate-pulse h-200px bg-gray-200"></view>
  </template>
  <template v-else>
    <AsyncContent />
  </template>
</view>

🎨 Style Variations

Glassmorphism (Primary Style)

<view class="
  bg-white/80
  backdrop-blur-md
  border border-white/20
  rounded-16px
  shadow-lg
">
  Glass card content
</view>

Flat Design (Secondary Style)

<view class="
  bg-white
  border border-gray-200
  rounded-8px
  shadow-sm
">
  Flat card content
</view>

Vibrant Block-based (Accent)

<view class="
  bg-primary
  text-white
  p-6
  rounded-12px
  shadow-xl
">
  <h3 class="text-24px font-700">Feature Title</h3>
  <p class="text-16px mt-2">High-contrast content block</p>
</view>

🔧 Vue 3 + UnoCSS Best Practices

Component Structure

<script setup lang="ts">
import { ref, computed } from 'vue'

// ✅ GOOD: Use ref for primitives
const count = ref(0)

// ✅ GOOD: Use reactive for objects
const state = reactive({ user: null })

// ✅ GOOD: Computed for derived state
const doubled = computed(() => count.value * 2)

// ✅ GOOD: Define props with types
const props = defineProps<{
  title: string
  isActive?: boolean
}>()

// ✅ GOOD: Define emits
const emit = defineEmits<{
  change: [id: number]
}>()
</script>

<template>
  <!--  GOOD: Use UnoCSS utility classes -->
  <view class="flex flex-col gap-4 p-4">
    <text class="text-20px font-600 text-main">
      {{ props.title }}
    </text>

    <button
      class="
        bg-primary text-white
        px-6 py-3 rounded-8px
        min-h-44px
        transition-colors duration-200
        hover:bg-[#e65a00]
        cursor-pointer
      "
      @click="emit('change', count)"
    >
      Click me: {{ count }}
    </button>
  </view>
</template>

UnoCSS Shortcuts (Custom)

// uno.config.ts shortcuts already configured:
shortcuts: {
  'border-base': 'border border-gray-500/10',
  'center': 'flex justify-center items-center',
}

// Usage:
<view class="center">Centered content</view>

Pre-Delivery Checklist

Before committing any UI code, verify:

Visual Quality

  • No emojis used as icons (use i-mdi-* instead)
  • All icons from consistent icon set (MDI via UnoCSS)
  • Hover states don't cause layout shift
  • Use theme colors directly (bg-primary, not bg-[#ff6700])

Interaction

  • All clickable elements have cursor-pointer
  • Hover states provide clear visual feedback
  • Transitions are 150-300ms (not slower)
  • Focus states visible for keyboard navigation

Light/Dark Mode

  • Light mode text contrast ≥ 4.5:1
  • Glass elements visible in light mode (bg-white/80 minimum)
  • Borders visible in both modes
  • Test both modes before delivery

Layout

  • Floating elements have spacing from edges (top-4 left-4 right-4)
  • No content hidden behind fixed navbars
  • Responsive at 375px, 768px, 1024px
  • No horizontal scroll on mobile

Accessibility

  • All images have alt text
  • Form inputs have <label> elements
  • Color is not the only indicator
  • prefers-reduced-motion respected

Performance

  • Images use lazy-load attribute
  • No animations > 300ms
  • Only transform/opacity animations
  • Reserve space for async content

Touch Targets

  • All interactive elements ≥ 44x44px
  • Minimum 8px gap between buttons
  • Input fields use correct inputmode

Internal Resources

Design Resources

Color Tools


🎯 Common Anti-Patterns to Avoid

DON'T

  1. Don't use emoji as icons

    <!-- ❌ BAD -->
    <span>🏠 首页</span>
    
    <!-- ✅ GOOD -->
    <i class="i-mdi-home"></i> 首页
    
  2. Don't use bg-white/10 in light mode

    <!-- ❌ BAD: Invisible in light mode -->
    <view class="bg-white/10">
    
    <!-- ✅ GOOD -->
    <view class="bg-white/80 dark:bg-white/10">
    
  3. Don't use text < 16px for body content on mobile

    <!-- ❌ BAD -->
    <text class="text-12px">Important content</text>
    
    <!-- ✅ GOOD -->
    <text class="text-16px">Important content</text>
    
  4. Don't forget touch targets

    <!-- ❌ BAD: Only 32px -->
    <button class="w-32px h-32px">X</button>
    
    <!-- ✅ GOOD: 44px minimum -->
    <button class="min-w-44px min-h-44px center">
      <i class="i-mdi-close w-20px h-20px"></i>
    </button>
    
  5. Don't use hover-only interactions

    <!-- ❌ BAD: Doesn't work on touch -->
    <view @mouseenter="showMenu">
    
    <!-- ✅ GOOD: Works everywhere -->
    <view @click="toggleMenu">
    

📝 Version History

  • v1.0 (2026-03-18): Initial design system based on UI/UX Pro Max analysis
  • Added comprehensive mobile-first guidelines
  • Integrated existing Xiaomi-inspired brand colors
  • Documented UnoCSS + Vue 3 patterns

Last Updated: 2026-03-18 Maintained By: Claude Code (UI/UX Pro Max)