/** @type {import('tailwindcss').Config} */ /** * 主题设计理念说明 * * 1. 设计系统基本原则 * - 一致性(Consistency): 确保UI元素在整个应用中保持一致 * - 可访问性(Accessibility): 支持所有用户的使用需求 * - 响应式(Responsive): 适应不同设备尺寸的界面 * - 直观性(Intuitive): 用户能够轻松理解和使用界面 * * 2. 组件变体设计 * - 主要变体(Primary): 用于主要操作和强调重要性的元素 * - 次要变体(Secondary): 用于辅助操作和次要强调的元素 * - 幽灵变体(Ghost): 低视觉权重的交互元素,通常无背景 * - 危险变体(Danger): 表示危险操作或警告信息 * * 3. 组件尺寸规范 (统一尺寸系统) * - 特小(xs): 用于空间紧凑或次要位置的元素 * - 小型(sm): 用于辅助操作或较小区域 * - 中型(md): 默认标准尺寸,适用于大多数场景 * - 大型(lg): 强调重要性或需要更高可点击区域 * - 特大(xl): 用于主要焦点区域或特殊强调 * * 所有组件使用统一的尺寸类: * - btn-xs, btn-sm, btn-md, btn-lg, btn-xl * * 用法示例: * * * * * 4. 状态设计 * - 正常(Normal): 组件的默认状态 * - 悬停(Hover): 鼠标指针悬停在元素上时的状态 * - 激活(Active): 元素被点击或当前活跃的状态 * - 禁用(Disabled): 元素不可交互的状态 * - 聚焦(Focus): 元素获得键盘焦点的状态 * * 5. 主题模式 * - 亮色模式(Light): 默认浅色背景深色文字的模式 * - 暗色模式(Dark): 深色背景浅色文字的模式,减少夜间使用时的视觉疲劳 */ module.exports = { darkMode: 'class', content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], theme: { extend: { screens: { '3xl': '1750px', '4xl': '1870px', }, keyframes: { spin: { from: { transform: 'rotate(0deg)' }, to: { transform: 'rotate(360deg)' }, }, blink: { '0%, 100%': { 'background-color': 'currentColor' }, '50%': { 'background-color': 'transparent' }, }, dotBounce: { '0%, 80%, 100%': { transform: 'translateY(-50%) scale(0.6)', opacity: 0.6, }, '40%': { transform: 'translateY(-50%) scale(1)', opacity: 1, }, }, rotate: { from: { transform: 'rotate(0deg)' }, to: { transform: 'rotate(360deg)' }, }, shimmer: { '0%': { 'background-position': '-200% 0' }, '100%': { 'background-position': '200% 0' }, }, glowBand: { '0%': { transform: 'translateX(-100%)' }, '100%': { transform: 'translateX(100%)' }, }, }, animation: { 'spin-slow': 'spin 2s linear infinite', blink: 'blink 1.2s infinite steps(1, start)', rotate: 'rotate 1s linear infinite', 'loading-dot': 'dotBounce 1.4s infinite ease-in-out', shimmer: 'shimmer 2s infinite linear', 'glow-band': 'glowBand 1.5s infinite linear', }, width: { sider: '60px', }, minHeight: { 28: '28px', }, backgroundColor: { lightBg: 'linear-gradient(145deg, #F7F9FA 0%, #D9E9F0 50%, #F7F9FA 100%)', }, backgroundImage: { 'custom-gradient': '#f4f4f4', 'primary-gradient': 'white', }, colors: { 'custom-gradient': '#f4f4f4', 'primary-gradient': 'white', opacity: '#f4f4f4', gray: { 50: '#f9f9f9', 100: '#ececec', 200: '#e3e3e3', 300: '#cdcdcd', 400: '#b4b4b4', 500: '#9b9b9b', 600: '#676767', 700: '#424242', 750: '#2f2f2f', 800: '#212121', 900: '#171717', 950: '#0d0d0d', }, primary: { 50: '#eef2ff', 100: '#e0e7ff', 200: '#c7d2fe', 300: '#a5b4fc', 400: '#818cf8', 500: '#6366f1', 600: '#4f46e5', 700: '#4338ca', 800: '#3730a3', 900: '#312e81', 950: '#1e1b4b', }, /* ===== 按钮主题化系统 ===== */ /* 1. 按钮背景色 */ 'btn-primary': 'var(--btn-bg-primary)', 'btn-primary-hover': 'var(--btn-bg-primary-hover)', 'btn-primary-active': 'var(--btn-bg-primary-active)', 'btn-secondary': 'var(--btn-bg-secondary)', 'btn-secondary-hover': 'var(--btn-bg-secondary-hover)', 'btn-secondary-active': 'var(--btn-bg-secondary-active)', 'btn-ghost': 'var(--btn-bg-ghost)', 'btn-ghost-hover': 'var(--btn-bg-ghost-hover)', 'btn-ghost-active': 'var(--btn-bg-ghost-active)', 'btn-danger': '#ef4444', 'btn-danger-hover': '#dc2626', 'btn-danger-active': '#b91c1c', 'btn-success': '#10b981', 'btn-success-hover': 'var(--btn-bg-success-hover)', 'btn-success-active': 'var(--btn-bg-success-active)', 'btn-warning': '#f59e0b', 'btn-warning-hover': 'var(--btn-bg-warning-hover)', 'btn-warning-active': 'var(--btn-bg-warning-active)', 'btn-info': '#3b82f6', 'btn-info-hover': 'var(--btn-bg-info-hover)', 'btn-info-active': 'var(--btn-bg-info-active)', /* 2. 按钮文字颜色 */ 'btn-text-primary': 'var(--btn-text-primary)', 'btn-text-secondary': 'var(--btn-text-secondary)', 'btn-text-ghost': 'var(--btn-text-ghost)', 'btn-text-danger': 'var(--btn-text-danger)', 'btn-text-success': 'var(--btn-text-success)' /* 新增 */, 'btn-text-warning': 'var(--btn-text-warning)' /* 新增 */, 'btn-text-info': 'var(--btn-text-info)' /* 新增 */, /* 3. 按钮边框 */ 'btn-primary-border': 'var(--btn-border-primary)', 'btn-primary-border-hover': 'var(--btn-border-primary-hover)', 'btn-primary-border-active': 'var(--btn-border-primary-active)', 'btn-secondary-border': 'var(--btn-border-secondary)', 'btn-secondary-border-hover': 'var(--btn-border-secondary-hover)', 'btn-secondary-border-active': 'var(--btn-border-secondary-active)', 'btn-success-border': 'var(--btn-border-success)' /* 新增 */, 'btn-warning-border': 'var(--btn-border-warning)' /* 新增 */, 'btn-info-border': 'var(--btn-border-info)' /* 新增 */, 'btn-danger-border': 'var(--btn-border-danger)' /* 新增 */, /* 4. 输入框主题 */ input: { outline: 'none', transition: 'all 0.2s', backgroundColor: '#ffffff', color: '#424242', borderWidth: '1px', borderColor: '#e3e3e3', borderStyle: 'solid', '::placeholder': { color: '#9b9b9b' }, '&:hover:not(:disabled)': { borderColor: '#cdcdcd' }, '&:focus:not(:disabled)': { borderColor: '#4f46e5', boxShadow: '0 0 0 2px #4f46e522', }, '&.is-error': { borderColor: '#ef4444', '&:focus': { boxShadow: '0 0 0 2px #ef444433' }, }, '&:disabled': { opacity: '.6', cursor: 'not-allowed' }, '.dark &': { backgroundColor: '#2f2f2f', color: '#cdcdcd', borderColor: '#424242', '::placeholder': { color: '#9b9b9b' }, '&:hover:not(:disabled)': { borderColor: '#676767' }, '&:focus:not(:disabled)': { borderColor: '#818cf8', boxShadow: '0 0 0 2px #818cf822', }, '&.is-error': { borderColor: '#f87171', '&:focus': { boxShadow: '0 0 0 2px #f8717133' }, }, }, }, /* 5. 按钮尺寸配置 */ buttonSize: { xs: { padding: '0.125rem 0.5rem', // 2px 8px fontSize: '0.6875rem', // 11px lineHeight: '0.875rem', // 14px borderRadius: '0.375rem', // 6px }, sm: { padding: '0.25rem 0.75rem', // 4px 12px fontSize: '0.75rem', // 12px lineHeight: '1rem', // 16px borderRadius: '0.5rem', // 8px }, md: { padding: '0.5rem 1rem', // 8px 16px fontSize: '0.875rem', // 14px lineHeight: '1.25rem', // 20px borderRadius: '0.625rem', // 10px }, lg: { padding: '0.75rem 1.25rem', // 12px 20px fontSize: '1rem', // 16px lineHeight: '1.5rem', // 24px borderRadius: '0.75rem', // 12px }, xl: { padding: '1rem 1.5rem', // 16px 24px fontSize: '1.125rem', // 18px lineHeight: '1.75rem', // 28px borderRadius: '0.875rem', // 14px }, }, /* 6. 图标按钮尺寸配置 */ iconButtonSize: { xs: { padding: '0.125rem', // 2px height: '1.25rem', // 20px width: '1.25rem', // 20px borderRadius: '0.375rem', // 6px }, sm: { padding: '0.25rem', // 4px height: '1.5rem', // 24px width: '1.5rem', // 24px borderRadius: '0.5rem', // 8px }, md: { padding: '0.375rem', // 6px height: '2rem', // 32px width: '2rem', // 32px borderRadius: '0.625rem', // 10px }, lg: { padding: '0.5rem', // 8px height: '2.5rem', // 40px width: '2.5rem', // 40px borderRadius: '0.75rem', // 12px }, xl: { padding: '0.625rem', // 10px height: '3rem', // 48px width: '3rem', // 48px borderRadius: '0.875rem', // 14px }, }, /* 7. 输入框尺寸配置 */ inputSize: { sm: { padding: '0.25rem 0.5rem', // 4px 8px fontSize: '0.75rem', // 12px lineHeight: '1rem', // 16px borderRadius: '0.5rem', // 8px }, md: { padding: '0.5rem 0.75rem', // 8px 12px fontSize: '0.875rem', // 14px lineHeight: '1.25rem', // 20px borderRadius: '0.625rem', // 10px }, lg: { padding: '0.75rem 1rem', // 12px 16px fontSize: '1rem', // 16px lineHeight: '1.5rem', // 24px borderRadius: '0.75rem', // 12px }, }, }, /* 5. 按钮尺寸配置 */ buttonSize: { xs: { padding: '0.125rem 0.5rem', // 2px 8px fontSize: '0.6875rem', // 11px lineHeight: '0.875rem', // 14px borderRadius: '0.375rem', // 6px }, sm: { padding: '0.25rem 0.75rem', // 4px 12px fontSize: '0.75rem', // 12px lineHeight: '1rem', // 16px borderRadius: '0.5rem', // 8px }, md: { padding: '0.5rem 1rem', // 8px 16px fontSize: '0.875rem', // 14px lineHeight: '1.25rem', // 20px borderRadius: '0.625rem', // 10px }, lg: { padding: '0.75rem 1.25rem', // 12px 20px fontSize: '1rem', // 16px lineHeight: '1.5rem', // 24px borderRadius: '0.75rem', // 12px }, xl: { padding: '1rem 1.5rem', // 16px 24px fontSize: '1.125rem', // 18px lineHeight: '1.75rem', // 28px borderRadius: '0.875rem', // 14px }, }, /* 6. 图标按钮尺寸配置 */ iconButtonSize: { xs: { padding: '0.125rem', // 2px height: '1.25rem', // 20px width: '1.25rem', // 20px borderRadius: '0.375rem', // 6px }, sm: { padding: '0.25rem', // 4px height: '1.5rem', // 24px width: '1.5rem', // 24px borderRadius: '0.5rem', // 8px }, md: { padding: '0.375rem', // 6px height: '2rem', // 32px width: '2rem', // 32px borderRadius: '0.625rem', // 10px }, lg: { padding: '0.5rem', // 8px height: '2.5rem', // 40px width: '2.5rem', // 40px borderRadius: '0.75rem', // 12px }, xl: { padding: '0.625rem', // 10px height: '3rem', // 48px width: '3rem', // 48px borderRadius: '0.875rem', // 14px }, }, /* 7. 输入框尺寸配置 */ inputSize: { sm: { padding: '0.25rem 0.5rem', // 4px 8px fontSize: '0.75rem', // 12px lineHeight: '1rem', // 16px borderRadius: '0.5rem', // 8px }, md: { padding: '0.5rem 0.75rem', // 8px 12px fontSize: '0.875rem', // 14px lineHeight: '1.25rem', // 20px borderRadius: '0.625rem', // 10px }, lg: { padding: '0.75rem 1rem', // 12px 16px fontSize: '1rem', // 16px lineHeight: '1.5rem', // 24px borderRadius: '0.75rem', // 12px }, }, }, }, plugins: [ require('@tailwindcss/typography'), require('tailwind-scrollbar'), /** * 统一的按钮组件系统 * * 设计理念: * - 变体(Variant): 定义按钮的外观类型(primary, secondary, ghost, danger等) * - 尺寸(Size): 使用统一的尺寸类(xs, sm, md, lg, xl)适用于所有按钮类型 * - 状态(State): 定义按钮的不同状态样式(normal, hover, active, disabled) * * 使用方式: * - 基础按钮: * - 图标按钮: * - 关闭按钮: * - 药丸按钮: * - 禁用状态: */ function ({ addComponents, theme }) { addComponents({ /* ===== 1. 基础按钮系统 ===== */ /** * 按钮基础类 (.btn) * 所有按钮的通用基础样式 */ '.btn': { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontWeight: '500', transition: 'all 0.2s', whiteSpace: 'nowrap', cursor: 'pointer', boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)', '&:disabled': { opacity: '.6', cursor: 'not-allowed', pointerEvents: 'none', }, }, /* 按钮尺寸变体 */ '.btn-xs': { padding: theme('buttonSize.xs.padding'), fontSize: theme('buttonSize.xs.fontSize'), lineHeight: theme('buttonSize.xs.lineHeight'), borderRadius: theme('buttonSize.xs.borderRadius'), }, '.btn-sm': { padding: theme('buttonSize.sm.padding'), fontSize: theme('buttonSize.sm.fontSize'), lineHeight: theme('buttonSize.sm.lineHeight'), borderRadius: theme('buttonSize.sm.borderRadius'), }, '.btn-md': { padding: theme('buttonSize.md.padding'), fontSize: theme('buttonSize.md.fontSize'), lineHeight: theme('buttonSize.md.lineHeight'), borderRadius: theme('buttonSize.md.borderRadius'), }, '.btn-lg': { padding: theme('buttonSize.lg.padding'), fontSize: theme('buttonSize.lg.fontSize'), lineHeight: theme('buttonSize.lg.lineHeight'), borderRadius: theme('buttonSize.lg.borderRadius'), }, '.btn-xl': { padding: theme('buttonSize.xl.padding'), fontSize: theme('buttonSize.xl.fontSize'), lineHeight: theme('buttonSize.xl.lineHeight'), borderRadius: theme('buttonSize.xl.borderRadius'), }, /* 按钮变体类型 */ /** * 主要按钮 (.btn-primary) * 用于表单提交、确认操作等主要操作 */ '.btn-primary': { backgroundColor: '#4f46e5' /* 主题色 */, color: '#ffffff', borderWidth: '0', borderColor: 'transparent', '&:hover:not(:disabled)': { backgroundColor: '#6366f1' /* 更浅色调 */, borderColor: 'transparent', }, '&:active:not(:disabled)': { backgroundColor: '#4338ca' /* 更深色调 */, borderColor: 'transparent', }, '.dark &': { backgroundColor: '#818cf8', color: '#ffffff', borderColor: 'transparent', '&:hover:not(:disabled)': { backgroundColor: '#6366f1', borderColor: 'transparent', }, '&:active:not(:disabled)': { backgroundColor: '#4f46e5', borderColor: 'transparent', }, }, }, /** * 次要按钮 (.btn-secondary) * 用于辅助操作、次级确认等 */ '.btn-secondary': { backgroundColor: '#ffffff', color: '#424242', borderWidth: '1px', borderColor: '#e3e3e3', '&:hover:not(:disabled)': { backgroundColor: '#f9f9f9', borderColor: '#cdcdcd', }, '&:active:not(:disabled)': { backgroundColor: '#ececec', borderColor: '#b4b4b4', }, '.dark &': { backgroundColor: '#2f2f2f', color: '#cdcdcd', borderColor: '#424242', '&:hover:not(:disabled)': { backgroundColor: '#424242', borderColor: '#676767', }, '&:active:not(:disabled)': { backgroundColor: '#676767', borderColor: '#9b9b9b', }, }, }, /** * 幽灵按钮 (.btn-ghost) * 用于低强调操作,通常是透明背景 */ '.btn-ghost': { backgroundColor: 'transparent', color: '#424242', borderWidth: '0', '&:hover:not(:disabled)': { backgroundColor: 'rgba(0, 0, 0, 0.04)', }, '&:active:not(:disabled)': { backgroundColor: 'rgba(0, 0, 0, 0.08)', }, '.dark &': { backgroundColor: 'transparent', color: '#cdcdcd', '&:hover:not(:disabled)': { backgroundColor: 'rgba(255, 255, 255, 0.08)', }, '&:active:not(:disabled)': { backgroundColor: 'rgba(255, 255, 255, 0.12)', }, }, }, /** * 危险按钮 (.btn-danger) * 用于删除、危险操作等需要警示的场景 */ '.btn-danger': { backgroundColor: '#ef4444', color: '#ffffff', borderWidth: '0', '&:hover:not(:disabled)': { backgroundColor: '#dc2626', }, '&:active:not(:disabled)': { backgroundColor: '#b91c1c', }, '.dark &': { backgroundColor: '#f87171', color: '#ffffff', '&:hover:not(:disabled)': { backgroundColor: '#ef4444', }, '&:active:not(:disabled)': { backgroundColor: '#dc2626', }, }, }, /** * 成功按钮 (.btn-success) * 用于表示成功、完成等积极操作 */ '.btn-success': { backgroundColor: '#10b981', color: '#ffffff', borderWidth: '0', borderColor: 'transparent', '&:hover:not(:disabled)': { backgroundColor: '#059669', }, '&:active:not(:disabled)': { backgroundColor: '#047857', }, '.dark &': { backgroundColor: '#10b981', color: '#ffffff', '&:hover:not(:disabled)': { backgroundColor: '#059669', }, '&:active:not(:disabled)': { backgroundColor: '#047857', }, }, }, /** * 警告按钮 (.btn-warning) * 用于需要注意但不危险的操作 */ '.btn-warning': { backgroundColor: '#f59e0b', color: '#ffffff', borderWidth: '0', borderColor: 'transparent', '&:hover:not(:disabled)': { backgroundColor: '#d97706', }, '&:active:not(:disabled)': { backgroundColor: '#b45309', }, '.dark &': { backgroundColor: '#f59e0b', color: '#ffffff', '&:hover:not(:disabled)': { backgroundColor: '#d97706', }, '&:active:not(:disabled)': { backgroundColor: '#b45309', }, }, }, /** * 信息按钮 (.btn-info) * 用于提示、信息性操作 */ '.btn-info': { backgroundColor: '#3b82f6', color: '#ffffff', borderWidth: '0', borderColor: 'transparent', '&:hover:not(:disabled)': { backgroundColor: '#2563eb', }, '&:active:not(:disabled)': { backgroundColor: '#1d4ed8', }, '.dark &': { backgroundColor: '#3b82f6', color: '#ffffff', '&:hover:not(:disabled)': { backgroundColor: '#2563eb', }, '&:active:not(:disabled)': { backgroundColor: '#1d4ed8', }, }, }, /** * 发送按钮 (.btn-send) * 专用于聊天、评论等发送消息场景 */ '.btn-send': { display: 'flex', alignItems: 'center', justifyContent: 'center', borderRadius: '9999px' /* rounded-full */, padding: '0.5rem' /* p-2 */, height: '2rem' /* h-8 */, width: '2rem' /* w-8 */, fontSize: '1rem' /* text-base */, fontWeight: '600' /* font-semibold */, boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)' /* shadow-sm */, backgroundColor: '#4f46e5' /* primary-600 */, color: '#ffffff' /* text-white */, transition: 'all 0.2s', '&:hover:not(:disabled)': { backgroundColor: '#4338ca' /* primary-700 */, }, '&:disabled': { backgroundColor: '#a5b4fc' /* primary-300 */, opacity: '0.6', cursor: 'not-allowed', }, '.dark &': { backgroundColor: '#424242' /* gray-750 - 参考btn-pill暗色默认背景 */, color: '#cdcdcd' /* gray-400 */, '&:hover:not(:disabled)': { backgroundColor: '#424242' /* 保持背景不变 */, color: '#ececec' /* gray-100 */, }, '&:disabled': { backgroundColor: '#2f2f2f' /* gray-800 */, }, }, }, /** * 停止按钮 (.btn-stop) * 用于停止生成内容的场景 */ '.btn-stop': { display: 'flex', alignItems: 'center', justifyContent: 'center', borderRadius: '9999px' /* rounded-full */, padding: '0.5rem' /* p-2 */, height: '2rem' /* h-8 */, width: '2rem' /* w-8 */, fontSize: '1rem' /* text-base */, fontWeight: '600' /* font-semibold */, boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)' /* shadow-sm */, backgroundColor: '#4f46e5' /* primary-600 */, color: '#ffffff' /* text-white */, transition: 'all 0.2s', '&:hover:not(:disabled)': { backgroundColor: '#4338ca' /* primary-700 */, }, '.dark &': { backgroundColor: '#676767' /* gray-600 - 参考btn-pill激活状态背景 */, color: '#ececec' /* gray-100 - 参考btn-pill激活状态文字 */, '&:hover': { backgroundColor: '#676767' /* 保持与非悬停状态相同 */, color: '#ececec' /* 保持与非悬停状态相同 */, }, }, }, /* ===== 2. 图标按钮系统 ===== */ /** * 图标按钮基础类 (.btn-icon) * 专为图标设计的按钮,可与尺寸类(btn-xs, btn-sm, btn-md, btn-lg, btn-xl)结合使用 * 例如: */ '.btn-icon': { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', transition: 'all 0.2s', cursor: 'pointer', backgroundColor: 'transparent' /* 透明背景 */, color: '#000' /* 黑色图标 */, overflow: 'hidden', position: 'relative', border: '0 solid transparent', fontWeight: '600', borderRadius: '10px' /* 使用s-radius-xs的值 */, aspectRatio: '1 / 1' /* 保持正方形 */, '&:hover:not(:disabled)': { backgroundColor: 'rgba(0, 0, 0, 0.06)' /* 对应--s-color-bg-trans-primary */, }, '&:active:not(:disabled)': { backgroundColor: 'rgba(0, 0, 0, 0.1)' /* 对应--s-color-bg-trans-secondary */, }, '&:disabled': { opacity: '.5', cursor: 'not-allowed', pointerEvents: 'none', }, '.dark &': { color: '#cdcdcd' /* 暗色模式下的颜色 */, '&:hover:not(:disabled)': { backgroundColor: 'rgba(255, 255, 255, 0.08)' /* 暗色模式下的悬停颜色 */, }, '&:active:not(:disabled)': { backgroundColor: 'rgba(255, 255, 255, 0.12)' /* 暗色模式下的激活颜色 */, }, }, }, /** * 侧栏折叠图标按钮 (.btn-icon-collapse) * 用于侧栏折叠/展开的按钮,具有特定的悬停效果 */ '.btn-icon-collapse': { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', transition: 'all 0.2s', cursor: 'pointer', backgroundColor: 'transparent', color: '#9b9b9b' /* gray-500 */, border: '0 solid transparent', fontWeight: '600', position: 'relative', overflow: 'hidden', '&:hover:not(:disabled)': { backgroundColor: '#ffffff' /* white */, color: '#6366f1' /* primary-500 */, }, '&:active:not(:disabled)': { backgroundColor: '#ffffff', color: '#4f46e5' /* primary-600 */, }, '&:disabled': { opacity: '.5', cursor: 'not-allowed', pointerEvents: 'none', }, '.dark &': { color: '#9b9b9b' /* gray-500 */, '&:hover:not(:disabled)': { backgroundColor: '#2f2f2f' /* gray-750 */, color: '#cdcdcd' /* gray-400 */, }, '&:active:not(:disabled)': { backgroundColor: '#2f2f2f', color: '#ececec' /* gray-100 */, }, }, }, /* 按钮尺寸变体 - 同时适用于普通按钮和图标按钮 */ '.btn-xs': { padding: theme('buttonSize.xs.padding'), fontSize: theme('buttonSize.xs.fontSize'), lineHeight: theme('buttonSize.xs.lineHeight'), borderRadius: theme('buttonSize.xs.borderRadius'), '.btn-icon&': { height: '24px', width: '24px', padding: '4px', fontSize: '14px', }, }, '.btn-sm': { padding: theme('buttonSize.sm.padding'), fontSize: theme('buttonSize.sm.fontSize'), lineHeight: theme('buttonSize.sm.lineHeight'), borderRadius: theme('buttonSize.sm.borderRadius'), '.btn-icon&': { height: '28px', width: '28px', padding: '6px', fontSize: '15px', }, }, '.btn-md': { padding: theme('buttonSize.md.padding'), fontSize: theme('buttonSize.md.fontSize'), lineHeight: theme('buttonSize.md.lineHeight'), borderRadius: theme('buttonSize.md.borderRadius'), '.btn-icon&': { height: '35px', width: '35px', padding: '7px', fontSize: '16px', }, }, '.btn-lg': { padding: theme('buttonSize.lg.padding'), fontSize: theme('buttonSize.lg.fontSize'), lineHeight: theme('buttonSize.lg.lineHeight'), borderRadius: theme('buttonSize.lg.borderRadius'), '.btn-icon&': { height: '40px', width: '40px', padding: '10px', fontSize: '18px', }, }, '.btn-xl': { padding: theme('buttonSize.xl.padding'), fontSize: theme('buttonSize.xl.fontSize'), lineHeight: theme('buttonSize.xl.lineHeight'), borderRadius: theme('buttonSize.xl.borderRadius'), '.btn-icon&': { height: '48px', width: '48px', padding: '12px', fontSize: '20px', }, }, /* ===== 3. 特殊按钮类型 ===== */ /** * 关闭按钮 (.btn-close) * 专用于模态框、提示框等的关闭按钮 */ '.btn-close': { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', borderRadius: '0.375rem', transition: 'all 0.2s', backgroundColor: 'transparent', color: 'var(--btn-text-ghost)', cursor: 'pointer', '&:hover:not(:disabled)': { backgroundColor: 'var(--btn-bg-ghost-hover)', }, '&:active:not(:disabled)': { backgroundColor: 'var(--btn-bg-ghost-active)', }, '&:disabled': { opacity: '.6', cursor: 'not-allowed', }, }, /** * 验证码按钮 (.btn-captcha) * 用于短信/邮箱验证码输入框 */ '.btn-captcha': { position: 'absolute', right: '0', top: '0', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', borderTopRightRadius: '0.75rem', borderBottomRightRadius: '0.75rem', paddingLeft: '0.5rem', paddingRight: '0.5rem', fontSize: '1rem', lineHeight: '1rem', fontWeight: '600', backgroundColor: '#4f46e5', color: '#ffffff', transition: 'all 0.2s', '&:hover:not(:disabled)': { backgroundColor: '#6366f1', }, '&:focus-visible': { outline: '2px solid transparent', outlineOffset: '2px', }, '&:disabled': { opacity: '.6', cursor: 'not-allowed', }, '.dark &': { backgroundColor: '#818cf8', color: '#ffffff', '&:hover:not(:disabled)': { backgroundColor: '#6366f1', }, }, }, /** * 药丸按钮 (.btn-pill) * 全圆角、带文字的可交互按钮,有激活和非激活两种状态 * 用于功能开关、选项切换等需要状态反馈的场景 * * 特点: * - 全圆角设计,类似药丸形状 * - 激活状态使用主题色突出显示 * - 非激活状态使用白色背景,灰色文字 * - 自动适配移动端和桌面端 * - 完善的深色模式支持 * * 用法: * */ '.btn-pill': { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', borderRadius: '9999px' /* rounded-full */, padding: '0.5rem', height: '2rem' /* h-8 */, fontSize: '0.875rem' /* text-sm */, fontWeight: '500', transition: 'all 0.15s ease', cursor: 'pointer', userSelect: 'none', whiteSpace: 'nowrap', border: '1px solid #cdcdcd' /* border-gray-100 */, backgroundColor: '#ffffff', color: '#6b7280' /* gray-500 */, boxShadow: '0 1px 1px rgba(0, 0, 0, 0.01)', /* 悬停效果 */ '&:hover:not(:disabled)': { backgroundColor: '#f9f9f9' /* gray-50 */, color: '#4b5563' /* gray-600 */, }, /* 暗色模式 */ '.dark &': { backgroundColor: '#2f2f2f' /* gray-750 */, borderColor: '#2f2f2f' /* gray-750 */, color: '#9b9b9b' /* gray-500 */, '&:hover:not(:disabled)': { backgroundColor: '#424242' /* gray-700 */, color: '#cdcdcd' /* gray-300 */, }, }, /* 禁用状态 */ '&:disabled': { opacity: '.6', cursor: 'not-allowed', pointerEvents: 'none', }, }, /** * 激活状态的药丸按钮 (.btn-pill-active) */ '.btn-pill-active': { backgroundColor: '#e0e7ff' /* primary-100 */, borderColor: '#e0e7ff', color: '#4f46e5' /* primary-600 */, border: '1px solid #e0e7ff', // boxShadow: '0 1px 2px rgba(0, 0, 0, 0.03)', /* 悬停效果 */ '&:hover:not(:disabled)': { backgroundColor: '#e0e7ff' /* primary-100 */, borderColor: '#e0e7ff', color: '#4f46e5' /* primary-600 */, }, '.dark &': { backgroundColor: '#676767' /* gray-600 */, borderColor: '#2f2f2f' /* gray-750 */, color: '#ececec' /* gray-100 */, '&:hover:not(:disabled)': { backgroundColor: '#676767' /* 保持背景不变 */, borderColor: '#2f2f2f' /* 保持边框不变 */, color: '#ececec' /* 保持文字颜色不变 */, }, }, }, /* ===== 4. 输入框系统 ===== */ /** * 输入框基础类 (.input) * 用于所有输入框元素 */ '.input': { outline: 'none', transition: 'all 0.2s', backgroundColor: '#ffffff', color: '#424242', borderWidth: '1px', borderColor: '#e3e3e3', borderStyle: 'solid', '::placeholder': { color: '#9b9b9b' }, '&:hover:not(:disabled)': { borderColor: '#cdcdcd' }, '&:focus:not(:disabled)': { borderColor: '#4f46e5', boxShadow: '0 0 0 2px #4f46e522', }, '&.is-error': { borderColor: '#ef4444', '&:focus': { boxShadow: '0 0 0 2px #ef444433' }, }, '&:disabled': { opacity: '.6', cursor: 'not-allowed' }, '.dark &': { backgroundColor: '#2f2f2f', color: '#cdcdcd', borderColor: '#424242', '::placeholder': { color: '#9b9b9b' }, '&:hover:not(:disabled)': { borderColor: '#676767' }, '&:focus:not(:disabled)': { borderColor: '#818cf8', boxShadow: '0 0 0 2px #818cf822', }, '&.is-error': { borderColor: '#f87171', '&:focus': { boxShadow: '0 0 0 2px #f8717133' }, }, }, }, /* 输入框尺寸 */ '.input-sm': { padding: theme('inputSize.sm.padding'), fontSize: theme('inputSize.sm.fontSize'), lineHeight: theme('inputSize.sm.lineHeight'), borderRadius: theme('inputSize.sm.borderRadius'), }, '.input-md': { padding: theme('inputSize.md.padding'), fontSize: theme('inputSize.md.fontSize'), lineHeight: theme('inputSize.md.lineHeight'), borderRadius: theme('inputSize.md.borderRadius'), }, '.input-lg': { padding: theme('inputSize.lg.padding'), fontSize: theme('inputSize.lg.fontSize'), lineHeight: theme('inputSize.lg.lineHeight'), borderRadius: theme('inputSize.lg.borderRadius'), }, /* ===== 5. 标签切换组件 ===== */ /** * 标签组容器 (.tab-group) */ '.tab-group': { display: 'flex', width: '100%', justifyContent: 'center', borderRadius: '10px', padding: '2.5px', transition: 'all 0.2s', backgroundColor: '#ececec', '.dark &': { backgroundColor: '#212121', }, }, /* 标签组变体 */ '.tab-group-default': { /* 默认样式已在基础类中定义 */ }, '.tab-group-filled': { backgroundColor: '#e2e8f0', '.dark &': { backgroundColor: '#334155', }, }, /** * 单个标签按钮 (.tab) */ '.tab': { display: 'block', width: '100%', borderRadius: '10px', transition: 'all 0.15s ease', fontWeight: '500', fontSize: '0.875rem', lineHeight: '1.25rem', textAlign: 'center', cursor: 'pointer', color: '#424242', '&:focus': { outline: 'none', }, '.dark &': { color: '#9ca3af', }, }, /* 标签尺寸 */ '.tab-sm': { padding: '0.25rem 0.5rem', fontSize: '0.75rem', lineHeight: '1rem', }, '.tab-md': { padding: '0.375rem 0.75rem', fontSize: '0.875rem', lineHeight: '1.25rem', }, '.tab-lg': { padding: '0.5rem 1rem', fontSize: '1rem', lineHeight: '1.5rem', }, /* 标签活动状态 */ '.tab-active': { backgroundColor: '#ffffff', color: '#4f46e5', boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)', '.dark &': { backgroundColor: '#374151', color: '#f3f4f6', }, }, /* ===== 6. 悬停提示组件 ===== */ /** * 悬停提示基础类 (.tooltip) * 为任何元素添加悬停提示,支持四个方向 * * 用法: * 1. 将需要显示提示的元素包裹在具有group类的容器中 * 2. 添加tooltip类及方向类(tooltip-top/right/bottom/left) * * 示例: *