swiss-style-guide
npx skills add https://github.com/sweetretry/skills --skill swiss-style-guide
Agent 安装分布
Skill 文档
å¿«éåè
| è¦ç´ | è§è |
|---|---|
| ç½æ ¼ç³»ç» | 8-Point Grid (8px åååä½)ï¼Desktop 12 Cols |
| åè§ | rounded-none å
¨å±ï¼ä»
交äºçåº rounded-sm (2px) |
| èæ¯è² | bg-background (CSS Variable å±å®ä¹çº¯ç½/è¿é») |
| åæ¯è² | text-foreground (CSS Variable å±å®ä¹è¿é»/è¿ç½) |
| 强è°è² | International Blue (--primary) + Swiss Red (--destructive) |
| 卿弿 | Framer Motion, Expo Out æ²çº¿ï¼<300ms |
| è§è§æ¨¡å¼ | ä¾§è¾¹æ Shell / ææ å¡çç½æ ¼ / æ°æ®è¡¨æ ¼ / å¾è¡¨å®¹å¨ / ç½æ ¼å å (å¯ç»å) |
| 对æ¯åº¦ | WCAG AA (â¥4.5:1)ï¼æè²æ¨¡å¼å è°±åç§» |
| 硬ç¼ç Hex | ç¦æ¢ â ç»ä»¶å±ä¸¥æ ¼ä½¿ç¨è¯ä¹ Token |
æ ¸å¿æä»¤ (Core Mandate)
æ¬è§èæ¨å¨æå»º “æ°ç士飿 ¼ (Neo-Swiss)” æ “ç³»ç»æç®ä¸»ä¹ (Systemic Minimalism)” çæ°åçé¢ãæ ¸å¿å¨äºå©ç¨æ°å¦ç§©åºå¯¹æä¿¡æ¯çµï¼ä¸º AI æ¶ä»£çè¿åº¦ä¿¡æ¯æä¾æ¸ æ°ç认ç¥ç»æã
å¼ºå¶ææ¯æ (Hard Constraints):
- UI åº:
shadcn/ui(å¿ é¡»éè¿cn()åå¹¶æ ·å¼ï¼ä¸¥ç¦ç¡¬ç¼ç æ ·å¼è¦çç³»ç» Token)ã - æ ·å¼å¼æ:
Tailwind CSS(å¼ºå¶æ§è¡ 8-Point Grid Systemï¼ä¸¥æ ¼ä½¿ç¨è¯ä¹å Token ç±»)ã - 卿åº:
Framer Motion(ä» éç¨äº <300ms çåè½æ§å¾®äº¤äº)ã
ä¸ã 设计å²å¦ï¼ç³»ç»æç®ä¸»ä¹ (Systemic Minimalism)
- å ¨é¢ç§©åº (Comprehensive Order): å©ç¨ CSS Grid (Subgrid) å Container Queries å®ç°è·¨å±çº§çç»å¯¹å¯¹é½ã
- å®¢è§æç (Objective Typography): å使¯ç»æèéè£ é¥°ãä½¿ç¨æµä½æç (Fluid Typography) éåºå¤è®¾å¤ã
- å½¢å¼è¿½éå 容 (Form Follows Content): ç½æ ¼éåºå 容ï¼èé强迫å 容éåºç½æ ¼ã妿ä¸ä¸ªåç´ ä¸æ¿è½½ä¿¡æ¯ï¼å é¤å®ã
- éå¯¹ç§°å¨æ (Asymmetrical Dynamic): æç»æ»æ¿çå± ä¸ï¼éè¿å·¦å¯¹é½ (Flush-left) åå³ä¾§çç½åé è§è§å¼ ååé 读æµã
äºã åºç¡ç³»ç» (System Foundations)
1. Token åè²å½©ç³»ç» (Neo-Swiss Color Tokens)
ååï¼ ææè²å½©å¨ CSS Variables å±å®ä¹ï¼ç»ä»¶å±ä¸¥æ ¼ä½¿ç¨ Tailwind è¯ä¹ç±»ãç¦æ¢å¨ç»ä»¶ä»£ç ä¸åºç°ä»»ä½ç¡¬ç¼ç Hex å¼ã
CSS Variables å®ä¹ï¼ç士åè½è²è°ï¼oklch è²å½©ç©ºé´ï¼ï¼
:root {
/* Neo-Swiss Light â 纯ç½åº + è¿é»åæ¯ + åè½åè² */
--background: oklch(1 0 0); /* 纯ç½ç»å¸ */
--foreground: oklch(0.145 0 0); /* è¿é»åæ¯ */
--card: oklch(0.985 0 0); /* å¡çå¾®ç° */
--card-foreground: oklch(0.145 0 0);
--primary: oklch(0.45 0.25 260); /* International Blue */
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--border: oklch(0.922 0 0);
--ring: oklch(0.45 0.25 260); /* ä¸ Primary ä¸è´ */
--destructive: oklch(0.6 0.25 25); /* Swiss Red */
}
.dark {
/* Neo-Swiss Dark â OLED å®å
¨è¿é» + å
è°±å移强è°è² */
--background: oklch(0.145 0 0); /* â #1A1A1A, OLED å®å
¨ */
--foreground: oklch(0.985 0 0); /* è¿ç½åæ¯ */
--card: oklch(0.205 0 0); /* å¡çå¾®æäº® */
--card-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0); /* å
è°±åç§»åç Primary */
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--border: oklch(0.269 0 0);
--ring: oklch(0.556 0 0);
--destructive: oklch(0.704 0.191 22.216); /* å
è°±åç§» Swiss Red */
}
åè½æ§å¤å·´èºååï¼ è²å½©ä» ç¨äº å ³é®äº¤äº (Action) æ ç¶ææç¤º (Status)ãç¦æ¢è£ 饰æ§è²åãInternational Blue ç¨äº Primary Actionï¼Swiss Red ä» ç¨äº Error/Destructiveã
å è°±åç§» (Spectral Shifting)ï¼ æè²æ¨¡å¼ä¸ç强è°è²å¿ é¡»è¿è¡äº®åº¦æå以满足 WCAG AA 4.5:1 对æ¯åº¦ã
ç»ä»¶å±ç¨æ³ç¤ºä¾ï¼
// â
æ£ç¡® â 使ç¨è¯ä¹ Token
<div className="bg-background text-foreground">
<div className="bg-card border border-border">
<Button className="bg-primary text-primary-foreground">Action</Button>
<span className="text-destructive">Error</span>
// â ç¦æ¢ â 硬ç¼ç Hex
<div className="bg-[#FFFFFF] text-[#111111]">
<button style={{ background: '#0055FF' }}>Action</button>
<span style={{ color: '#FF3B30' }}>Error</span>
2. ç½æ ¼ä¸é´è· (The 8-Point Grid)
- åååä½: 8px (0.5rem)ãææé´è· (
margin,padding,gap,height) å¿ é¡»æ¯ 8 çåæ°ã- Scale: 8, 16, 24, 32, 40, 48, 64, 80pxã
- Implementation: 严ç¦ä½¿ç¨å¥æ°æé 8 åæ°å¼ (å¦
p-[11px])ã
- ç½æ ¼ç³»ç»:
- Desktop: 12 Cols, Gap 24px (3rem), Margin 80px (10rem).
- Tablet: 8 Cols, Gap 16px.
- Mobile: 4 Cols, Gap 16px, Margin 16px.
- Technique: 使ç¨
grid-cols-12é åcol-span-xè¿è¡ååå¼åå²ã
3. å ä½ä¸æé (Strict Geometry)
- åè§ (Radius): 0px (Zero Radius)ãå
¨ç³»ç»é»è®¤å¼ºå¶ç´è§ï¼ä¼ éå·¥ä¸ç²¾å¯æã
- Exception: ä»
å¨ é«é¢äººæºäº¤äºç¹ (å¦
Button,Badge,Input Focus Ring) å 许微åè§ (2px /rounded-sm) 以符å人ä½å·¥å¦ï¼é²æ¢è§è§åºçã - Prohibited: Card, Dialog, Image, Container å¿ é¡»ä¿æç´è§ã
- Exception: ä»
å¨ é«é¢äººæºäº¤äºç¹ (å¦
- è¾¹æ¡ (Borders): æç»éå©ãé»è®¤
1pxï¼Modal/Popover å¯ä½¿ç¨2px强è°å±çº§ã - ç士弿·±åº¦ (Swiss Depth): ç¦ç¨æå½± (Shadow)ï¼éè¿å±çº§å å åè¾¹æ¡è¡¨è¾¾æ·±åº¦ï¼
- Level 0 (Base): Canvas (
bg-background)ã - Level 1 (Group): Bordered Area (
border border-border)ã - Level 2 (Overlay): Dialog/Popover ä½¿ç¨ Thick Border (
border-2 border-border) æé«å¯¹æ¯åº¦èæ¯è²ã
- Level 0 (Base): Canvas (
4. æçä½ç³» (Fluid Typography)
- åä½:
- UI:
Inter,Geist,Roboto Flex(é¦éå¯ååä½)ã - Data:
JetBrains Mono,Geist Mono(æææ°åãIDã代ç å¿ é¡»ä½¿ç¨ç宽åä½)ã
- UI:
- æµä½ç¼©æ¾ (Modular Scale): æ¾å¼åºå®åç´ ï¼ä½¿ç¨
clamp()ååºè§å£ã- éµå¾ª Major Third (1.250) æ Perfect Fourth (1.333) æ°å¦æ¯ä¾ã
- Display (H1):
clamp(2.5rem, 5vw, 3.8rem)(Letter-spacing: tight)ã - Body:
1rem(16px) (Line-height: 1.5)ã - Label:
0.75rem(12px) Uppercase, Tracking Widest (0.05em+)ã
- 徿 (Geometric Icons):
- SVG æ ¼å¼ï¼çº¯æè¾¹ (Stroke) æçº¯å¡«å (Fill)ï¼æ æ¸åï¼æ 3Dã
- è¯ä¹åï¼å¾æ æ¨å¨å é认ç¥ï¼èéè£ é¥°ã
ä¸ãè§è§æ¨¡å¼èå (Data-Dense Visual Modes)
以䏿¨¡å¼éå¯¹æ°æ®å¯éåçé¢ä¼åï¼å¯ç¬ç«ä½¿ç¨æç»åå å ãDashboard 项ç®é常ç»å Sidebar Shell + Metric Grid + Data Tableã
1. ä¾§è¾¹æ Shell (Sidebar Shell)
åºå®å®½åº¦ä¾§è¾¹æ + æµå¨ä¸»åºåï¼ç»å ¸ SaaS å¸å±éª¨æ¶ã
- ä¾§è¾¹æ
w-64 border-r border-border bg-cardï¼ä¸»åºåflex-1 bg-backgroundã - 导èªé¡¹ä½¿ç¨
text-muted-foreground hover:text-foreground hover:bg-accentç¶æåæ¢ã - æ´»è·é¡¹ä½¿ç¨
bg-accent text-foreground font-mediumæ è®°ï¼é åborder-l-2 border-primaryæç¤ºã - Mobile ä¸ä¾§è¾¹æ æ¶èµ·ä¸ºæ½å± (
w-0âw-64+backdrop-blur-sm)ã - éç¨ï¼ SaaS 产åä¸»æ¡æ¶ã管çåå°ãè®¾ç½®é¢æ¿ã
2. ææ å¡çç½æ ¼ (Metric Card Grid)
4 å KPI å¡çç½æ ¼ï¼Mono æ°å + delta çè²ã
- ç½æ ¼
grid grid-cols-2 md:grid-cols-4 gap-4 md:gap-6ã - æ¯å¼ å¡ç
border border-border rounded-none p-6ã - ææ æ°å使ç¨
font-mono text-3xl font-bold text-foregroundã - Delta æ£å
text-primaryï¼èè² = å¢é¿ï¼ï¼è´åtext-destructiveï¼çº¢è² = ä¸éï¼ã - Label 使ç¨
text-xs uppercase tracking-widest text-muted-foregroundã - éç¨ï¼ Dashboard 顶鍿¦è§ãè´¢å¡æè¦ãè¿è¥ææ ã
3. æ°æ®è¡¨æ ¼ (Data Table)
ç士å¼ç²¾ç¡®æççæ°æ®è¡¨æ ¼ï¼é«å¯åº¦ä¿¡æ¯å±ç¤ºã
- 表头
text-xs uppercase tracking-widest text-muted-foreground font-medium border-b-2 border-borderã - æ°æ®è¡ä½¿ç¨
border-b border-border/50 hover:bg-accent交æ¿é«äº®ã - æ°å¼å强å¶
font-mono text-rightï¼ææ¬åtext-leftã - è¡å æä½æé®ä½¿ç¨ Ghost variantï¼ä» å¨ hover æ¶æ¾ç¤ºã
- æåºæç¤ºå¨ä½¿ç¨å ä½å¾æ (ä¸è§å½¢)ï¼å½åæåºå
font-semiboldã - éç¨ï¼ 交æè®°å½ãç¨æ·åè¡¨ãæ¥å¿æ°æ®ã
4. å¾è¡¨å®¹å¨ (Chart Container)
è¾¹æ¡æ¡å® + Mono 表头 + æ¶é´éæ©å¨çæ åå¾è¡¨æ¡æ¶ã
- 容å¨
border border-border rounded-none p-6ã - æ é¢åº
flex items-center justify-between mb-6ã - å¾è¡¨æ é¢
font-mono text-sm uppercase tracking-widest text-muted-foregroundã - æ¶é´éæ©å¨ä½¿ç¨
rounded-smæé®ç»ï¼Active ç¶æbg-primary text-primary-foregroundã - å¾è¡¨åºåä¿æ
aspect-[16/9]æh-[300px]åºå®é«åº¦ã - éç¨ï¼ è¶å¿å¾ãæ±ç¶å¾ãé¢ç§¯å¾å®¹å¨ã
5. ç½æ ¼å å (Grid Overlay)
å¼åæ¶ç 12 å坹齿 ¡éªå·¥å ·ã
- éè¿
fixed inset-0 pointer-events-none z-[9999]å å å ¨å±ã - 12 å使ç¨
grid grid-cols-12 gap-6 h-fullï¼æ¯åbg-primary/5ã - éè¿é®çå¿«æ·é® (å¦
Ctrl+G) 忢æ¾ç¤º/éèã - ä»
å¨
process.env.NODE_ENV === 'development'æ¶æ¸²æã - éç¨ï¼ å¼åé¶æ®µå¯¹é½æ ¡éªã设计è¿åæ£æ¥ã
åã ç»ä»¶å®ç° (Implementation Specs)
shadcn/ui ç士忹é (Neo-Swiss Overrides)
æææ¹é éè¿ cn() åå¹¶æ ·å¼ï¼ä½¿ç¨è¯ä¹ Tokenï¼ç¦æ¢ç¡¬ç¼ç é¢è²å¼ã
Button
// Primary â åè½æ§èè²å¨ä½æé®
<Button className={cn(
"bg-primary text-primary-foreground",
"rounded-sm font-medium tracking-wide",
"shadow-none transition-none" // ç± Framer Motion æ¥ç®¡
)}>
<motion.span whileTap={{ scale: 0.98 }} transition={neoSwiss}>
Action
</motion.span>
</Button>
// Ghost â å·¥å
·æ /è¾
婿ä½
<Button variant="ghost" className={cn(
"text-muted-foreground hover:text-foreground",
"rounded-sm hover:bg-accent"
)}>
Secondary
</Button>
// Destructive â Swiss Red ç ´åæ§æä½
<Button variant="destructive" className={cn(
"bg-destructive text-primary-foreground",
"rounded-sm font-medium"
)}>
Delete
</Button>
Card / Container
// æ ååºåå®¹å¨ â è¾¹æ¡åå²ï¼æ é´å½±ï¼ç´è§
<div className={cn(
"border border-border rounded-none bg-card",
"shadow-none"
)}>
{/* ååºå¤´é¨ â Mono uppercase */}
<div className="border-b border-border px-6 py-4">
<h3 className="font-mono text-xs uppercase tracking-widest text-muted-foreground">
{sectionTitle}
</h3>
</div>
{/* å
容åºå */}
<div className="p-6">
{children}
</div>
</div>
Input
// ç´è§è¾å
¥ â Label å¨ä¸æ¹ï¼å ç²
<div className="space-y-2">
<Label className="text-sm font-semibold text-foreground">
{label}
</Label>
<Input className={cn(
"rounded-none border-input bg-background",
"focus:ring-2 focus:ring-primary focus:ring-offset-0",
"placeholder:text-muted-foreground"
)} />
</div>
Dialog
<Dialog>
<DialogOverlay className={cn(
"bg-background/80 backdrop-blur-sm"
)} />
<DialogContent className={cn(
"bg-card border-2 border-border rounded-none",
"shadow-none"
)}>
<AnimatePresence mode="wait">
<motion.div
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -4 }}
transition={neoSwiss}
>
{/* Mono æ é¢ */}
<DialogTitle className="font-mono text-sm uppercase tracking-widest text-muted-foreground mb-4">
{title}
</DialogTitle>
{children}
</motion.div>
</AnimatePresence>
</DialogContent>
</Dialog>
Navigation
<nav className={cn(
"fixed top-0 w-full z-50",
"bg-background border-b border-border"
)}>
<div className="flex items-center justify-between px-8 h-16">
{/* å 使 è¯ */}
<div className="flex items-center gap-3">
<div className="w-6 h-6 bg-primary rounded-none" />
<span className="font-mono text-sm uppercase tracking-widest text-foreground">
{brand}
</span>
</div>
{/* Mono uppercase 龿¥ */}
<div className="flex gap-8">
{links.map(link => (
<motion.a
key={link.href}
className={cn(
"font-mono text-xs uppercase tracking-widest",
"text-muted-foreground hover:text-foreground"
)}
whileHover={{ x: 2 }}
transition={neoSwiss}
>
{link.label}
</motion.a>
))}
</div>
</div>
</nav>
卿忰 (Polite Motion)
ååï¼ äº¤äºå¿ é¡»æ¯ ç¤¼è²ç (Polite)ãç¬æ¶ç (<300ms) ä¸ æ åå¼¹ (No Bounce)ã
// å¾®äº¤äº â Expo Outï¼é»è®¤ææäº¤äº
const neoSwiss = {
duration: 0.2,
ease: [0.16, 1, 0.3, 1] // Expo Out
};
// è¡¨æ ¼è¡å
¥åº â æ´å¿«ï¼æ°æ®å¯éåºæ¯
const tableRow = {
duration: 0.15,
ease: [0.16, 1, 0.3, 1]
};
// æ°æ®å è½½æç¤º â éª¨æ¶ â å
å®¹è¿æ¸¡
const dataReveal = {
duration: 0.3,
ease: [0.16, 1, 0.3, 1]
};
// åºåè¿æ¸¡ â 页é¢çº§å¸å±åæ¢
const sectionTransition = {
duration: 0.4,
ease: [0.16, 1, 0.3, 1]
};
å ¥åºç¼æ (Stagger Orchestration)
// è¡¨æ ¼/å表 â å¿«é级èå
¥åº
const tableContainer = {
animate: { transition: { staggerChildren: 0.03 } }
};
const tableItem = {
initial: { opacity: 0, y: 4 },
animate: {
opacity: 1,
y: 0,
transition: tableRow
}
};
// å¡çç½æ ¼ â ç¨æ
¢çº§è
const gridContainer = {
animate: { transition: { staggerChildren: 0.06 } }
};
const gridItem = {
initial: { opacity: 0, y: 8 },
animate: {
opacity: 1,
y: 0,
transition: dataReveal
}
};
骨æ¶èå²å¨ç»
// æ°æ®å è½½æ¶ç骨æ¶å ä½
const skeletonPulse = {
animate: {
opacity: [0.4, 0.7, 0.4],
transition: {
duration: 1.5,
repeat: Infinity,
ease: "easeInOut"
}
}
};
// éª¨æ¶ â çå®å
容ç忢
<AnimatePresence mode="wait">
{isLoading ? (
<motion.div
key="skeleton"
className="bg-muted rounded-none h-8"
{...skeletonPulse}
exit={{ opacity: 0, transition: tableRow }}
/>
) : (
<motion.div
key="content"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={dataReveal}
>
{content}
</motion.div>
)}
</AnimatePresence>
äºã 代ç å®¡æ¥æ¸ å (The Neo-Swiss Audit)
Token åè§
- Token Check â ç»ä»¶ä»£ç 䏿¯å¦åå¨ç¡¬ç¼ç Hex (å¦
#0055FF,#FF3B30)ï¼ææé¢è²æ¯å¦ä½¿ç¨bg-background/text-foreground/border-borderçè¯ä¹ç±»ï¼ - CSS Variable Check â ç士è²è°æ¯å¦å¨
:root/.darkç CSS Variables ä¸ä½¿ç¨ oklch() æ£ç¡®å®ä¹ï¼
ç½æ ¼ä¸å ä½
- 8-Point Compliance â ææç margin/padding/gap æ¯å¦é½æ¯ 8 çåæ°ï¼æç»
10px,15pxã - Zero Radius Default â é»è®¤æ¯å¦ä¸ºç´è§ï¼åè§æ¯å¦ä»
éäº Button/Input ç交äºçåº (
rounded-sm)ï¼ - Border Depth â æ·±åº¦æ¯å¦éè¿è¾¹æ¡è¡¨è¾¾ (Level 0/1/2)ï¼æ¯å¦åå¨ä¸å¿ è¦ç shadowï¼
æç
- Mono Data â æ°åãIDãä»£ç æ¯å¦ä½¿ç¨äº Mono åä½ï¼
- Fluid Scale â æ 颿¯å¦ä½¿ç¨äº
clamp()æµä½ç¼©æ¾ææ£ç¡®ç Modular Scale æ¯ä¾ï¼ - Label Convention â Label æ¯å¦ä½¿ç¨
text-xs uppercase tracking-widestï¼
è²å½©åè½
- Functional Only â å½©è²æ¯å¦ä» ç¨äº Action (Primary) æ Status (Destructive)ï¼æ¯å¦åå¨è£ 饰æ§çèæ¯è²åï¼
- Spectral Shifting â Dark Mode ä¸ç Primary/Destructive æ¯å¦è¿è¡äºå è°±å移以满足 WCAG AAï¼
å¨æè´¨é
- Duration Check â ææå¨ææ¶é¿æ¯å¦ <300msï¼æ¯å¦åå¨ç¼æ ¢æææ½æçå¨ç»ï¼
- Stagger Check â è¡¨æ ¼/å表æ¯å¦ä½¿ç¨
staggerChildren级èå ¥åºï¼ - Loading State â æ°æ®å è½½æ¯å¦æéª¨æ¶èå²ï¼éª¨æ¶ â å å®¹è¿æ¸¡æ¯å¦æµç ï¼
å¯è®¿é®æ§
- Contrast Safety â ææææ¬ (å°¤å
¶æ¯
text-muted-foreground) 对æ¯åº¦æ¯å¦ ⥠4.5:1ï¼ - Motion Safety â æ¯å¦å°é
prefers-reduced-motionï¼å¼å¯åæ¯å¦ç¦ç¨ stagger åå ¥åºå¨ç»ï¼ - Focus Ring â ææäº¤äºå
ç´ æ¯å¦æé«å¯¹æ¯åº¦ Focus Ring (
ring-2 ring-primary ring-offset-2)ï¼
ååºå¼
- Grid Adaptive â ç½æ ¼æ¯å¦ååºå¼éå (12 â 8 â 4 cols)ï¼
- OLED Safety â Dark Mode èæ¯æ¯å¦ä½¿ç¨
oklch(0.145 0 0)(â#1A1A1A)ï¼é¿å 纯é»ï¼ - Touch Target â ç§»å¨ç«¯äº¤äºçåºæ¯å¦ â¥44pxï¼
åèèµæº
- 设计ç论深度æ¥å: å¦éäºè§£æ°ç士飿 ¼çå岿¸æºãçè®ºæ¡æ¶å宿´è®¾è®¡ååï¼è¯·åé reference.md
- 示ä¾é¡¹ç®:
example/ç®å½å å«ä¸ä¸ªå®æ´ç Neo-Swiss 飿 ¼ç¤ºä¾åºç¨ï¼å±ç¤ºäºè§èçå®é å®ç°ï¼å æ¬å¸å±ç»ä»¶ã页颿¨¡æ¿å卿é ç½®
åæç¬è®° (Composition Notes)
æ¬èä¾
design-directoræè½å¨å¤é£æ ¼èååºæ¯ä¸ä½¿ç¨ãå®ä¹æ¬é£æ ¼æåä¸åªäºå±æ§æ¯ç¡¬çº¦æï¼å³ä½¿å¨æ··å模å¼ä¸ä¹ä¸å¯è¦çï¼ï¼åªäºæ¯è½¯çº¦æï¼å¯ç± Director æ ¹æ®é¡¹ç®éæ±è°æ´ï¼ã
硬约æ (Hard Constraints â ä¸å¯è¦ç)
| ID | 屿§ | è§èå¼ | çç± |
|---|---|---|---|
| S.H1 | 8-Point Grid | ææé´è·ï¼margin / padding / gapï¼ä¸º 8px åæ° | æ°å¦ç§©åºæ¯ç士飿 ¼çæ ¸å¿èº«ä»½ï¼ç ´åç½æ ¼çäºç ´å飿 ¼æ¬è´¨ |
| S.H2 | Token å | ç¦æ¢ç¡¬ç¼ç Hexï¼ç»ä»¶å±ä½¿ç¨è¯ä¹ Token | è·¨é£æ ¼èåçåºç¡è®¾æ½ï¼ææé£æ ¼å ±äº«æ¤çº¦æ |
| S.H3 | è²å½©ç©ºé´ | oklch | æç¥ååè²å½©ç©ºé´ï¼æ··å项ç®çæ å |
| S.H4 | ç¦ç¨æå½± | shadow-none å
¨å±ï¼æ·±åº¦éè¿è¾¹æ¡å±çº§è¡¨è¾¾ (Level 0/1/2) |
æå½±å¨ç´è§ç³»ç»ä¸å¶é è§è§çç¾ï¼ç士弿·±åº¦æ¨¡åçæ ¸å¿åå |
| S.H5 | 卿æ¶é¿ | <300msï¼Expo Out ç¼å¨ | åè½æ§äº¤äºçæ ¸å¿èå¥ââè¶ è¿ 300ms 卿°æ®æä½ä¸äº§ç”ææ½æ” |
| S.H6 | 对æ¯åº¦ | WCAG AA (â¥4.5:1) | æ éç¢å¼ºå¶è¦æ± |
| S.H7 | åè½æ§è²å½© | 彩è²ä»
ç¨äº Action (--primary) å Status (--destructive)ï¼ç¦æ¢è£
饰æ§è²å |
ä¿¡æ¯ç¼ç çæ ¸å¿ååââè²å½©å¿ é¡»æºå¸¦è¯ä¹ |
软约æ (Soft Constraints â å¯ç± Director è¦ç)
| ID | 屿§ | é»è®¤å¼ | Director å¯è°æ´èå´ | è§¦åæ¡ä»¶ |
|---|---|---|---|---|
| S.S1 | åè§ | rounded-none (0px) å
¨å±é»è®¤ï¼äº¤äºçåº rounded-sm (2px) |
é Dashboard åºå坿¾å®½è³ rounded-md (6px) / rounded-lg (8px) |
å½ Minimal ä¸ºè¾ å©é£æ ¼ï¼å 容é 读åºåéè¦æ´æåçè§è§æåæ¶ |
| S.S2 | æçï¼å¤§åæ ç¾ | text-xs uppercase tracking-widest ç¨äºææ Label |
å 容åºå坿¾å¼ uppercaseï¼ä½¿ç¨ Sentence case | å½ Minimal ä¸ºè¾ å©é£æ ¼ï¼æç« /å客åºåä¸éåå ¨å¤§åæ ç¾æ¶ |
| S.S3 | ç½æ ¼åæ° | Desktop 12 å | å 容åºåå¯ç®å为 8 æ 6 å | å½éæ°æ®å¯éåºåä¸éè¦å®æ´ 12 åç²¾åº¦æ¶ |
| S.S4 | OLED æè²èæ¯ | oklch(0.145 0 0) â #1A1A1A |
Expressive åºå坿åè³ oklch(0.08 0 0) |
å½ Expressive ä¸ºè¾ å©é£æ ¼ï¼éè¦æ´æ·±çå½±é¢ç»å¸æ¶ |
| S.S5 | ä¿¡æ¯å¯åº¦ | é«å¯åº¦ï¼æ°æ®è¡¨æ ¼ãKPI å¡çï¼ | é Dashboard åºåå¯éä½å¯åº¦ | å½åºåçåè½æ¯é è¯»ææµè§èéæä½æ°æ®æ¶ |
| S.S6 | è¾¹æ¡å度 | 1px é»è®¤ï¼2px ç¨äºå å å± (Modal/Drawer) | å¯ç»ä¸ä¸º 1px | å½ Minimal ä¸ºä¸»é£æ ¼ï¼æ´ä½è§è§éè¦æ´è½»çè§¦ææ¶ |