返回 AiToEarn
design.json
1 {
2 "schemaVersion": 2,
3 "generatedAt": "2026-06-08T00:00:00.000Z",
4 "title": "Design System: AiToEarn Web",
5 "extensions": {
6 "colorMeta": {
7 "brand-cyan": {
8 "role": "primary",
9 "displayName": "Brand Cyan-Violet",
10 "canonical": "oklch(0.71 0.17 294)",
11 "tonalRamp": [
12 "oklch(0.22 0.08 294)",
13 "oklch(0.33 0.11 294)",
14 "oklch(0.44 0.14 294)",
15 "oklch(0.55 0.16 294)",
16 "oklch(0.66 0.17 294)",
17 "oklch(0.71 0.17 294)",
18 "oklch(0.82 0.12 294)",
19 "oklch(0.93 0.05 294)"
20 ]
21 },
22 "brand-purple": {
23 "role": "primary",
24 "displayName": "Brand Magenta-Rose",
25 "canonical": "oklch(0.74 0.17 3)",
26 "tonalRamp": [
27 "oklch(0.24 0.09 3)",
28 "oklch(0.35 0.12 3)",
29 "oklch(0.46 0.15 3)",
30 "oklch(0.57 0.17 3)",
31 "oklch(0.68 0.17 3)",
32 "oklch(0.74 0.17 3)",
33 "oklch(0.84 0.12 3)",
34 "oklch(0.94 0.05 3)"
35 ]
36 },
37 "foreground": {
38 "role": "neutral",
39 "displayName": "Ink",
40 "canonical": "oklch(0.145 0 0)",
41 "tonalRamp": [
42 "oklch(0.145 0 0)",
43 "oklch(0.205 0 0)",
44 "oklch(0.269 0 0)",
45 "oklch(0.439 0 0)",
46 "oklch(0.556 0 0)",
47 "oklch(0.708 0 0)",
48 "oklch(0.85 0 0)",
49 "oklch(0.97 0 0)"
50 ]
51 },
52 "border": {
53 "role": "neutral",
54 "displayName": "Hairline",
55 "canonical": "oklch(0.922 0 0)",
56 "tonalRamp": [
57 "oklch(0.3 0 0)",
58 "oklch(0.45 0 0)",
59 "oklch(0.6 0 0)",
60 "oklch(0.75 0 0)",
61 "oklch(0.85 0 0)",
62 "oklch(0.922 0 0)",
63 "oklch(0.96 0 0)",
64 "oklch(0.99 0 0)"
65 ]
66 }
67 },
68 "typographyMeta": {
69 "display": {
70 "displayName": "Display",
71 "purpose": "Card titles, section and modal headings. The in-app heading ceiling."
72 },
73 "body": {
74 "displayName": "Body",
75 "purpose": "Base 14px text for all running copy and controls."
76 },
77 "label": {
78 "displayName": "Label",
79 "purpose": "Form labels, badges, table headers, meta text."
80 },
81 "numeric": {
82 "displayName": "Numeric",
83 "purpose": "DIN-set counts, durations, dates, metrics."
84 }
85 },
86 "shadows": [
87 {
88 "name": "resting",
89 "value": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
90 "purpose": "Cards, inputs, buttons at rest (Tailwind shadow-sm)."
91 },
92 {
93 "name": "hover-lift",
94 "value": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
95 "purpose": "Primary button and interactive cards on hover only."
96 },
97 {
98 "name": "brand-glow",
99 "value": "0 1px 2px 0 oklch(0.71 0.17 294 / 0.2)",
100 "purpose": "Exclusive to the primary gradient button; ties elevation to brand intent."
101 }
102 ],
103 "motion": [
104 {
105 "name": "transition-all",
106 "value": "150ms cubic-bezier(0.4, 0, 0.2, 1)",
107 "purpose": "Default state transition for interactive controls."
108 },
109 { "name": "accordion", "value": "200ms ease-out", "purpose": "Accordion open/close." }
110 ],
111 "breakpoints": [
112 { "name": "sm", "value": "640px" },
113 { "name": "md", "value": "768px" },
114 { "name": "lg", "value": "1024px" },
115 { "name": "xl", "value": "1280px" },
116 { "name": "3xl", "value": "1400px" }
117 ]
118 },
119 "components": [
120 {
121 "name": "Primary Button",
122 "kind": "button",
123 "refersTo": "button-primary",
124 "description": "The Action role of the Signature Gradient; gradient fill for primary intent.",
125 "html": "<button class=\"ds-btn-primary\">发布内容</button>",
126 "css": ".ds-btn-primary { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 36px; padding: 8px 16px; font-size: 14px; font-weight: 500; color: oklch(0.985 0 0); background: linear-gradient(to right in oklch, oklch(0.74 0.17 3), oklch(0.71 0.17 294)); border: none; border-radius: 8px; box-shadow: 0 1px 2px 0 oklch(0.71 0.17 294 / 0.2); cursor: pointer; transition: box-shadow 150ms cubic-bezier(0.4,0,0.2,1), transform 150ms cubic-bezier(0.4,0,0.2,1); } .ds-btn-primary:hover { box-shadow: 0 4px 6px -1px oklch(0.71 0.17 294 / 0.25); } .ds-btn-primary:active { transform: scale(0.98); } .ds-btn-primary:focus-visible { outline: 2px solid oklch(0.71 0.17 294); outline-offset: 2px; }"
127 },
128 {
129 "name": "Outline Button",
130 "kind": "button",
131 "refersTo": "button-outline",
132 "description": "Neutral secondary action with hairline border.",
133 "html": "<button class=\"ds-btn-outline\">取消</button>",
134 "css": ".ds-btn-outline { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 36px; padding: 8px 16px; font-size: 14px; font-weight: 500; color: oklch(0.145 0 0); background: oklch(1 0 0); border: 1px solid oklch(0.922 0 0); border-radius: 8px; box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); cursor: pointer; transition: background 150ms cubic-bezier(0.4,0,0.2,1); } .ds-btn-outline:hover { background: oklch(0.97 0 0); } .ds-btn-outline:focus-visible { outline: 2px solid oklch(0.71 0.17 294); outline-offset: 2px; }"
135 },
136 {
137 "name": "Secondary Button",
138 "kind": "button",
139 "refersTo": "button-secondary",
140 "description": "Low-emphasis filled action.",
141 "html": "<button class=\"ds-btn-secondary\">保存草稿</button>",
142 "css": ".ds-btn-secondary { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 36px; padding: 8px 16px; font-size: 14px; font-weight: 500; color: oklch(0.205 0 0); background: oklch(0.97 0 0); border: none; border-radius: 8px; box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); cursor: pointer; transition: background 150ms cubic-bezier(0.4,0,0.2,1); } .ds-btn-secondary:hover { background: oklch(0.97 0 0 / 0.8); } .ds-btn-secondary:focus-visible { outline: 2px solid oklch(0.71 0.17 294); outline-offset: 2px; }"
143 },
144 {
145 "name": "Text Input",
146 "kind": "input",
147 "refersTo": "input-default",
148 "description": "Standard 36px field with 1px focus ring, no glow.",
149 "html": "<input class=\"ds-input\" type=\"text\" placeholder=\"输入标题\" />",
150 "css": ".ds-input { display: flex; width: 100%; height: 36px; padding: 4px 12px; font-size: 14px; color: oklch(0.145 0 0); background: transparent; border: 1px solid oklch(0.922 0 0); border-radius: 8px; box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); transition: border-color 150ms cubic-bezier(0.4,0,0.2,1); } .ds-input::placeholder { color: oklch(0.556 0 0); } .ds-input:focus-visible { outline: none; border-color: oklch(0.71 0.17 294); box-shadow: 0 0 0 1px oklch(0.71 0.17 294); } .ds-input:disabled { cursor: not-allowed; opacity: 0.5; }"
151 },
152 {
153 "name": "Card",
154 "kind": "card",
155 "refersTo": "card-default",
156 "description": "Flat surface with hairline border and soft resting shadow.",
157 "html": "<div class=\"ds-card\"><h3 class=\"ds-card-title\">发布记录</h3><p class=\"ds-card-desc\">查看跨平台发布状态</p></div>",
158 "css": ".ds-card { background: oklch(1 0 0); color: oklch(0.145 0 0); border: 1px solid oklch(0.922 0 0); border-radius: 10px; box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); padding: 24px; } .ds-card-title { margin: 0 0 6px; font-size: 24px; font-weight: 600; letter-spacing: -0.01em; line-height: 1; } .ds-card-desc { margin: 0; font-size: 14px; color: oklch(0.556 0 0); }"
159 },
160 {
161 "name": "Topic Mention",
162 "kind": "custom",
163 "refersTo": "topic-mention",
164 "description": "Publish-editor inline @topic / #tag chip with thin brand-gradient underline.",
165 "html": "<span class=\"ds-topic\"><span class=\"ds-topic-trigger\">#</span><span class=\"ds-topic-value\">AI增长</span></span>",
166 "css": ".ds-topic { display: inline; margin-inline: 1px; padding: 0 1px 1px; vertical-align: baseline; color: color-mix(in oklch, oklch(0.71 0.17 294) 76%, oklch(0.145 0 0)); border-radius: 7px; background: linear-gradient(90deg, oklch(0.71 0.17 294), oklch(0.74 0.17 3)) 0 100% / 100% 0.08em no-repeat; transition: background 180ms ease, color 180ms ease; } .ds-topic-trigger { color: color-mix(in oklch, oklch(0.74 0.17 3) 62%, oklch(0.71 0.17 294)); font-weight: 700; } .ds-topic-value { font-weight: 600; }"
167 }
168 ],
169 "narrative": {
170 "northStar": "The Calm Growth Studio",
171 "overview": "AiToEarn is a professional workspace where creators and operators drive AI agents through high-volume, multi-account publishing. The interface should feel like a calm growth studio: capable and efficient, never cold or sterile. Surfaces stay quiet and neutral so dense publishing flows read clearly; the purple→cyan brand gradient appears deliberately across a small set of explicit roles to mark action, state, progress, identity, and page structure. The tool disappears into the task. This system rejects decorative interfaces that distract from publishing, inconsistent form and modal patterns, and low-contrast controls. Depth is achieved through near-flat tonal layering, not heavy shadows. Light and dark themes are both first-class via semantic tokens.",
172 "keyCharacteristics": [
173 "Neutral grayscale surfaces; the brand gradient is the signature, deployed across action, state, progress, brand identity/frame, and seam roles while work surfaces stay neutral.",
174 "High information density, with calm spacing rhythm to keep it legible.",
175 "One sans family (Suisseintl) carries the whole UI; DIN for numerics, HYHanHeiJ for Chinese.",
176 "Near-flat elevation via shadow-sm and tonal color-mix layering.",
177 "Full light/dark parity through semantic tokens."
178 ],
179 "rules": [
180 {
181 "name": "The Signature Gradient Rule",
182 "body": "The purple→cyan brand gradient is the system signature, deployed across five defined roles and nowhere else: Action (primary button, key CTAs); State (active-nav indicator bar + label tint, unread/count badge, active tab underline, switch on-state); Progress (progress-bar fills, one emphasized metric/series); Brand identity/frame (brand mark, 1px gradient border on a focused field or one featured card, avatar ring, empty-state icon stroke); Brand-seam (a single thin page-header hairline). Ceiling: work surfaces stay neutral — cards, tables, forms, list rows, and panel backgrounds are never filled or backed with the gradient. Hard bans, always: no gradient text (background-clip:text), no gradient side-stripe wider than 1px, no full-bleed gradient on a work surface.",
183 "section": "colors"
184 },
185 {
186 "name": "The Semantic-Token Rule",
187 "body": "Never hardcode a color (no text-gray-900, no #000, no bg-[var(...)]). Always use the semantic variable so light/dark both resolve correctly.",
188 "section": "colors"
189 },
190 {
191 "name": "The One-Family Rule",
192 "body": "Suisseintl carries headings, buttons, labels, body, and data. DIN and HYHanHeiJ are scoped tools, not a second display voice. Display fonts in UI labels, buttons, or data are forbidden.",
193 "section": "typography"
194 },
195 {
196 "name": "The Fixed-Scale Rule",
197 "body": "Use the fixed rem scale, not fluid clamp() headings. Users view at consistent DPI; a heading that shrinks inside a sidebar looks worse.",
198 "section": "typography"
199 },
200 {
201 "name": "The Flat-By-Default Rule",
202 "body": "Surfaces are flat at rest. Shadows appear as a response to state (hover, focus, the primary action), never as ambient decoration. Prefer a hairline border or tonal color-mix layer before a shadow.",
203 "section": "elevation"
204 }
205 ],
206 "dos": [
207 "Do deploy the brand gradient across its five roles — Action (primary button/CTA), State (active-nav indicator + tint, unread/count badge, active tab underline, switch on), Progress (progress fill, one emphasized metric/series), Brand identity/frame (brand mark, avatar ring, one featured card/focused-field border, empty-state icon stroke), Brand-seam (a single page-header hairline).",
208 "Do keep work surfaces neutral: cards, tables, forms, list rows, and panel backgrounds are never filled or backed with the gradient.",
209 "Do use semantic tokens (bg-background, text-muted-foreground, border-border) so every surface resolves in both light and dark.",
210 "Do keep elevation near-flat: shadow-sm at rest, shadows only as a state response.",
211 "Do carry the whole UI in Suisseintl; scope DIN to numerics and HYHanHeiJ to Chinese.",
212 "Do use the NumberInput component for all numeric entry.",
213 "Do verify body text and placeholders clear 4.5:1 contrast against tinted near-white surfaces."
214 ],
215 "donts": [
216 "Don't use the brand gradient as a work-surface background, ambient decoration, or a flourish beyond its five roles.",
217 "Don't render gradient text (background-clip:text), a gradient side-stripe wider than 1px on a card/list/alert, or any full-bleed gradient on a work surface — permanent bans regardless of role.",
218 "Don't hardcode colors (text-gray-900, #000, black, bg-[var(--primary-color)]); always semantic variables and Tailwind v4 bg-(--token) syntax.",
219 "Don't put display fonts in UI labels, buttons, or data.",
220 "Don't use fluid clamp() headings in product UI; use the fixed rem scale.",
221 "Don't reach for a modal as the first thought; exhaust inline and progressive alternatives first.",
222 "Don't ship inconsistent component vocabulary across platform flows.",
223 "Don't use native input type=number; use the NumberInput component.",
224 "Don't add gratuitous motion; transitions are 150-250ms and convey state, never choreography."
225 ]
226 }
227 }
228
228 lines JSON