@sarunyu/system-one 4.5.1 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -32,14 +32,35 @@ in this package.** This file is the short version: the rules you must follow.
32
32
  `bg-background`, `bg-card`, `bg-muted`, `bg-primary-action`,
33
33
  `border-border`, `border-divider`, etc. See `llms.txt` for the full table.
34
34
 
35
- 3. **Do not add text/font utility classes to `<h1>`–`<h4>`.** They are pre-styled.
35
+ 3. **No arbitrary bracket values for spacing/sizing/typography.** Use scale utilities only.
36
+ - **Forbidden**: `max-w-[1100px]`, `h-[317px]`, `min-h-[calc(100vh-64px)]`,
37
+ `w-[272px]`, `gap-[14px]`, `p-[10px]`, `text-[13px]`, `leading-[22px]`,
38
+ `rounded-[10px]`, `top-[7px]`.
39
+ - **Allowed**: scale values — `max-w-5xl` / `max-w-2xl`, `h-80` (=320px),
40
+ `w-64` (=256px), `gap-4`, `p-6`, `text-sm`, `leading-6`, `rounded-lg`,
41
+ `top-2`. The spacing scale is 4px-based: `0.5` (2px), `1` (4px), `2` (8px),
42
+ `3` (12px), `4` (16px), `5` (20px), `6` (24px), `8` (32px), `10` (40px),
43
+ `12` (48px), `16` (64px), `20` (80px), `24` (96px).
44
+ - **Exception — container widths only**: these specific arbitrary widths are
45
+ safelisted and may be used: `max-w-[480px]`, `max-w-[640px]`, `max-w-[720px]`,
46
+ `max-w-[800px]`, `max-w-[960px]`, `max-w-[1024px]`, `max-w-[1200px]`,
47
+ `max-w-[1280px]`, `max-w-[1440px]`. For other widths, pick the nearest
48
+ `max-w-{xs,sm,md,lg,xl,2xl,3xl,4xl,5xl,6xl,7xl}`.
49
+ - **Why**: the library's shipped `styles.css` only contains scale utilities
50
+ + the safelisted arbitrary container widths. Any other `[...]` value needs
51
+ host-side Tailwind to compile — in a plain host (e.g. Claude Code / Cursor
52
+ vibe-coded Vite project without Tailwind setup) the class is a no-op and
53
+ layout collapses. If a design truly requires an odd value, snap to the
54
+ nearest scale step.
55
+
56
+ 4. **Do not add text/font utility classes to `<h1>`–`<h4>`.** They are pre-styled.
36
57
  Use them as-is.
37
58
 
38
- 4. **Layout is your job, with plain Tailwind.** The library has NO layout primitives.
59
+ 5. **Layout is your job, with plain Tailwind.** The library has NO layout primitives.
39
60
  Do not import `Page`, `Section`, `Stack`, `CardGrid`, `Toolbar` — they do not exist.
40
61
  Build structure with `<div>` + `flex` / `grid` / `max-w-*` / `gap-*` / `p-*`.
41
62
 
42
- 5. **Component props are documented in `llms.txt` and in the `.d.ts` files.**
63
+ 6. **Component props are documented in `llms.txt` and in the `.d.ts` files.**
43
64
  - `Input.onChange` receives `(value: string)`, not an event.
44
65
  - `placeholder` IS the label (floats up on fill). Don't add a separate `<label>`.
45
66
  - Checkbox/Radio take their `label` as a prop. Don't wrap them in `<label>`.
@@ -53,7 +74,7 @@ in this package.** This file is the short version: the rules you must follow.
53
74
  - `Badge variant="notification"` — internal to `<Notification>`; never use standalone or attach your own `onClick` to it.
54
75
  - `Notification` manages its own popover; pass `groups` (array of `{ label, items }`). It renders both the bell trigger and the panel. This is the only correct way to show a notification list.
55
76
 
56
- 6. **Mobile forms and action-heavy modals MUST use `<BottomSheet>`, not `<Modal>`.**
77
+ 7. **Mobile forms and action-heavy modals MUST use `<BottomSheet>`, not `<Modal>`.**
57
78
  Login, signup, settings panels, profile editors, any multi-field form,
58
79
  multi-step flow, long picker list, or action menu — on mobile (< 768px)
59
80
  these render as `<BottomSheet>`. Only simple `variant="alert"` and short
package/DESIGN.md ADDED
@@ -0,0 +1,263 @@
1
+ # DESIGN.md — @sarunyu/system-one
2
+
3
+ Visual identity guide for AI coding tools (Figma Make, Lovable, v0, Claude).
4
+ Read this before generating any UI. For component API and token class names, read `AGENTS.md` and `llms.txt`.
5
+
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ **Personality:** Corporate — structured, trustworthy, data-dense, professional.
11
+ **Feel:** Clean surfaces, strong hierarchy, controlled whitespace. Never playful, never decorative.
12
+ **Target context:** Enterprise web applications — dashboards, data tables, form-heavy workflows, financial UIs.
13
+
14
+ Design decisions lean toward clarity over expression. Every element earns its space.
15
+
16
+ ---
17
+
18
+ ## Colors
19
+
20
+ ### Brand palette
21
+
22
+ | Role | Light mode | Dark mode | Tailwind class |
23
+ |---|---|---|---|
24
+ | Primary action (buttons, links, active) | `#0a6ee7` | `#4792ed` | `bg-primary-action` / `text-primary-action` |
25
+ | Primary hover | `#095ec4` | `#91bef4` | `bg-primary-action-hover` |
26
+ | Primary active/pressed | `#074ea4` | — | `bg-primary-action-active` |
27
+ | Primary light tint | `#dae9fb` | — | `bg-primary-action-light` |
28
+ | Secondary accent (highlights, badges) | `#eb6101` | — | use `bg-visual-orange` |
29
+
30
+ ### Surfaces
31
+
32
+ | Role | Value | Tailwind class |
33
+ |---|---|---|
34
+ | Page background | `#ffffff` (light) / `#0f172a` (dark) | `bg-background` |
35
+ | Card / panel | `#ffffff` (light) / `#1e293b` (dark) | `bg-card` |
36
+ | Subtle secondary surface | `#f9fafb` | `bg-default-secondary` |
37
+ | Input background | `#f9fafb` | `bg-muted` |
38
+ | Hover state | `#f3f4f6` | `bg-hover-bg` |
39
+ | Disabled | `#f3f4f6` | `bg-disabled-bg` |
40
+
41
+ ### Status colors
42
+
43
+ | Status | Fill | Light surface | Tailwind class |
44
+ |---|---|---|---|
45
+ | Danger / error | `#fb2c36` | `#fef2f2` | `bg-destructive` / `bg-error-bg` |
46
+ | Warning | `#f0b100` | `#fefce8` | `bg-warning` / `bg-warning-light` |
47
+ | Success | `#00c951` | `#f0fdf4` | `bg-success` / `bg-success-bg` |
48
+ | Info | blue-500 | blue-50 | `bg-info` / `bg-info-light` |
49
+
50
+ ### Borders
51
+
52
+ Default border: `1px solid` — `border-border` (`#e5e7eb` light).
53
+ Dividers between sections: `border-divider` (lighter than border).
54
+ Never hard-code border colors.
55
+
56
+ ---
57
+
58
+ ## Typography
59
+
60
+ **Font family:** `Noto Sans Thai`, sans-serif — loaded via Google Fonts (wght 400 / 500 / 600).
61
+ Override globally: `--font-sans: "Your Font", sans-serif;`
62
+
63
+ ### Heading scale (pre-styled — do NOT add Tailwind text-* overrides)
64
+
65
+ | Tag | Size | Weight | Use for |
66
+ |---|---|---|---|
67
+ | `<h1>` | 24px | 600 | Page title |
68
+ | `<h2>` | 20px | 600 | Section title |
69
+ | `<h3>` | 18px | 600 | Card / panel heading |
70
+ | `<h4>` | 16px | 500 | Sub-section, field group label |
71
+
72
+ ### Body scale
73
+
74
+ | Class | Size | Use for |
75
+ |---|---|---|
76
+ | (default, no class) | 16px | Body text, form values |
77
+ | `text-sm` | 14px | Secondary labels, table cells, helper text |
78
+ | `text-xs` | 12px | Captions, timestamps, fine print |
79
+
80
+ ### Color rules
81
+
82
+ - Body / headings: `text-foreground`
83
+ - Secondary labels: `text-muted-foreground`
84
+ - Disabled: `text-disabled`
85
+ - Brand / link: `text-primary-action`
86
+ - Error: `text-destructive`
87
+
88
+ Never use `text-gray-*`, `text-blue-*`, or hex colors for text.
89
+
90
+ ---
91
+
92
+ ## Spacing
93
+
94
+ **Base unit:** 4px. All spacing values are multiples of 4px.
95
+
96
+ ### Layout spacing
97
+
98
+ | Context | Value | Tailwind |
99
+ |---|---|---|
100
+ | Page horizontal padding | 24px (desktop) / 16px (mobile) | `px-6 md:px-8` |
101
+ | Page vertical padding | 40px | `py-10` |
102
+ | Between major page sections | 48px | `gap-12` |
103
+ | Between related content blocks | 24px | `gap-6` |
104
+ | Between items in a cluster | 16px | `gap-4` |
105
+ | Inside a card / panel | 24px | `p-6` |
106
+ | Dense toolbar / header row | 12–16px | `gap-3` or `gap-4` |
107
+
108
+ ### Content width
109
+
110
+ | Layout | Max-width |
111
+ |---|---|
112
+ | Dashboard / wide content | `max-w-[1200px]` |
113
+ | Standard content page | `max-w-[960px]` |
114
+ | Form / narrow content | `max-w-[640px]` |
115
+ | Dialog / modal body | `max-w-[480px]` |
116
+
117
+ ---
118
+
119
+ ## Border radius
120
+
121
+ Default: **4px** (`rounded`). Corporate contexts use tight radius — avoid large curves.
122
+
123
+ | Usage | Value | Tailwind |
124
+ |---|---|---|
125
+ | Default (inputs, cards, buttons) | 4px | `rounded` |
126
+ | Tags, badges, chips | 6px | `rounded-md` |
127
+ | Pills | 999px | `rounded-full` |
128
+ | Modals, large panels | 8px | `rounded-lg` |
129
+
130
+ ---
131
+
132
+ ## Elevation / shadow
133
+
134
+ Use sparingly. Corporate UIs prefer border separation over heavy elevation.
135
+
136
+ | Level | Usage | Tailwind |
137
+ |---|---|---|
138
+ | None | Flat cards separated by border | — |
139
+ | Subtle | Floating cards, content panels | `shadow-sm` |
140
+ | Card | Event cards, interactive tiles | `shadow-card` |
141
+ | Popover | Dropdowns, menus, tooltips | `shadow-popover` |
142
+
143
+ ---
144
+
145
+ ## Layout patterns
146
+
147
+ ### Standard dashboard page
148
+
149
+ ```tsx
150
+ <main className="mx-auto w-full max-w-[1200px] px-6 md:px-8 py-10 flex flex-col gap-12">
151
+ <header className="flex items-start justify-between gap-4">
152
+ <div className="flex flex-col gap-1">
153
+ <h1>Page Title</h1>
154
+ <p className="text-sm text-muted-foreground">Supporting description</p>
155
+ </div>
156
+ <Button variant="primary" size="md">Primary action</Button>
157
+ </header>
158
+
159
+ <section className="flex flex-col gap-6">
160
+ <h2>Section</h2>
161
+ {/* content */}
162
+ </section>
163
+ </main>
164
+ ```
165
+
166
+ ### Sidebar + content
167
+
168
+ ```tsx
169
+ <div className="flex min-h-screen bg-background">
170
+ <aside className="w-64 shrink-0 border-r border-divider bg-card p-6 flex flex-col gap-2">
171
+ {/* navigation items */}
172
+ </aside>
173
+ <main className="flex-1 px-8 py-10 flex flex-col gap-12">
174
+ {/* page content */}
175
+ </main>
176
+ </div>
177
+ ```
178
+
179
+ ### Card grid (data tiles)
180
+
181
+ ```tsx
182
+ <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
183
+ {items.map(item => (
184
+ <Card key={item.id} title={item.title} description={item.description} />
185
+ ))}
186
+ </div>
187
+ ```
188
+
189
+ ### Form page
190
+
191
+ ```tsx
192
+ <main className="mx-auto w-full max-w-[640px] px-6 py-10 flex flex-col gap-8">
193
+ <h1>Form Title</h1>
194
+ <section className="flex flex-col gap-4">
195
+ <Input placeholder="Field label" value={v} onChange={setV} />
196
+ <Input placeholder="Another field" value={v2} onChange={setV2} />
197
+ <Dropdown placeholder="Select option" options={opts} value={sel} onChange={setSel} />
198
+ </section>
199
+ <div className="flex justify-end gap-3">
200
+ <Button variant="outline" size="md">Cancel</Button>
201
+ <Button variant="primary" size="md">Submit</Button>
202
+ </div>
203
+ </main>
204
+ ```
205
+
206
+ ### Data table page
207
+
208
+ ```tsx
209
+ <main className="mx-auto w-full max-w-[1200px] px-6 md:px-8 py-10 flex flex-col gap-6">
210
+ <header className="flex items-center justify-between gap-4">
211
+ <h1>Table Title</h1>
212
+ <div className="flex items-center gap-3">
213
+ <SearchInput placeholder="Search..." value={q} onChange={setQ} />
214
+ <Button variant="primary" size="md">Add new</Button>
215
+ </div>
216
+ </header>
217
+ <Table>
218
+ <TableRow header>
219
+ <TableHeaderCell>Column A</TableHeaderCell>
220
+ <TableHeaderCell>Column B</TableHeaderCell>
221
+ </TableRow>
222
+ {rows.map(row => (
223
+ <TableRow key={row.id}>
224
+ <TableCell>{row.a}</TableCell>
225
+ <TableCell>{row.b}</TableCell>
226
+ </TableRow>
227
+ ))}
228
+ </Table>
229
+ </main>
230
+ ```
231
+
232
+ ---
233
+
234
+ ## Visual do / don't
235
+
236
+ | Do | Don't |
237
+ |---|---|
238
+ | Use `bg-background`, `bg-card` for surfaces | Hard-code `#ffffff` or `bg-white` |
239
+ | Use `text-foreground` for body text | Use `text-gray-900` or `text-black` |
240
+ | Use `border-border` for dividers | Use `border-gray-200` |
241
+ | Use `rounded` (4px) by default | Use `rounded-xl` or `rounded-2xl` on data elements |
242
+ | Keep whitespace controlled: `gap-4`–`gap-6` inside sections | Over-pad with `gap-10`+ inside cards |
243
+ | One `variant="primary"` Button per context | Two or more primary buttons side by side |
244
+ | Separate sections with `gap-12` or a `border-divider` line | Use heavy drop shadows to separate sections |
245
+ | Use scale values — `max-w-5xl`, `h-80`, `w-64`, `gap-4`, `p-6`, `text-sm` | Use arbitrary brackets — `max-w-[1100px]`, `h-[317px]`, `gap-[14px]`, `text-[13px]` (won't compile in hosts without Tailwind; see AGENTS.md rule 3) |
246
+
247
+ ---
248
+
249
+ ## Component library
250
+
251
+ This design system ships 24 pre-built components. **Always use them — never recreate with raw HTML.**
252
+
253
+ Key components: `Button`, `Input`, `TextArea`, `SearchInput`, `Dropdown`, `DropdownMultiple`, `Checkbox`, `Radio`, `Toggle`, `DateInput`, `TimeInput`, `Tag`, `StatusTag`, `Chip`, `TabGroup`, `Card`, `Table` + `TableRow` + `TableHeaderCell` + `TableCell`, `Modal`, `BottomSheet`, `Alert`, `Toast`, `ToastStack`, `Notification`, `Badge`.
254
+
255
+ For props, variants, and usage rules → read `AGENTS.md` and `llms.txt` in this package.
256
+
257
+ ### Setup (required)
258
+
259
+ ```tsx
260
+ import "@sarunyu/system-one/styles.css";
261
+ ```
262
+
263
+ If the screen looks unstyled, this import is missing.