@sarunyu/system-one 2.0.1 → 2.0.2
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/llms.txt +164 -93
- package/package.json +1 -1
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @sarunyu/system-one
|
|
2
2
|
|
|
3
|
-
React UI component library for AI generation tools (Figma Make, v0, Lovable). You compose
|
|
3
|
+
React UI component library for AI generation tools (Figma Make, v0, Lovable). You compose pages from layout + UI primitives — both are in the library. Tailwind CSS v4 + CSS custom properties.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -37,6 +37,9 @@ Rules:
|
|
|
37
37
|
|
|
38
38
|
```tsx
|
|
39
39
|
import {
|
|
40
|
+
// Layout
|
|
41
|
+
Page, PageHeader, Section, Toolbar, Stack, CardGrid,
|
|
42
|
+
// UI
|
|
40
43
|
Button, Input, TextArea, SearchInput,
|
|
41
44
|
Dropdown, DropdownMultiple, OptionList,
|
|
42
45
|
Tag, StatusTag, Chip,
|
|
@@ -49,126 +52,196 @@ import {
|
|
|
49
52
|
|
|
50
53
|
---
|
|
51
54
|
|
|
52
|
-
##
|
|
55
|
+
## Color rules — read this before touching any className
|
|
53
56
|
|
|
54
|
-
|
|
57
|
+
**Never** use Tailwind's literal color utilities for brand or semantic roles. Only use design token CSS variables.
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
| Role | ✅ Use this token | ❌ Never this |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| Brand / CTA | `var(--primary-action)` | `bg-blue-600`, `text-blue-500` |
|
|
62
|
+
| Hover / active | `var(--primary-action-hover)`, `var(--primary-action-active)` | `hover:bg-blue-700` |
|
|
63
|
+
| Body text | `var(--foreground)` | `text-gray-900` |
|
|
64
|
+
| Secondary text | `var(--muted-foreground)` | `text-gray-500` |
|
|
65
|
+
| Page background | `var(--background)` | `bg-white`, `bg-gray-50` |
|
|
66
|
+
| Card surface | `var(--card)` | `bg-white` |
|
|
67
|
+
| Subtle surface | `var(--muted)` | `bg-gray-100` |
|
|
68
|
+
| Border | `var(--border)` | `border-gray-200` |
|
|
69
|
+
| Subtle divider | `var(--divider)` | `border-gray-100` |
|
|
70
|
+
| Success | `var(--success)` | `text-green-600` |
|
|
71
|
+
| Error / danger | `var(--destructive)` | `text-red-500` |
|
|
72
|
+
| Warning | `var(--accent-orange)` | `text-orange-400` |
|
|
57
73
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
- Centered auth/onboarding card: `max-w-[400px] mx-auto`.
|
|
61
|
-
- Never let content stretch edge-to-edge on desktop.
|
|
74
|
+
Usage in className: `className="bg-[var(--card)] text-[var(--foreground)] border-[var(--border)]"`
|
|
75
|
+
Usage in style: `style={{ color: "var(--primary-action)" }}`
|
|
62
76
|
|
|
63
|
-
|
|
77
|
+
---
|
|
64
78
|
|
|
65
|
-
|
|
66
|
-
- Between major sections: `space-y-12` or `mt-12`.
|
|
67
|
-
- Between related blocks inside a section: `space-y-6`.
|
|
68
|
-
- Between form fields: `space-y-4` (tight) or `space-y-5` (comfortable).
|
|
69
|
-
- Card grid gap: `gap-6`.
|
|
79
|
+
## Layout — design freely, but color with tokens
|
|
70
80
|
|
|
71
|
-
|
|
81
|
+
**Layout is yours to design.** Use any structure, spacing, grid, or visual treatment you want. The two hard rules are:
|
|
72
82
|
|
|
73
|
-
|
|
83
|
+
1. **Colors** — every color must come from a design token (see Color rules above). No `bg-blue-500`, no `text-gray-900`.
|
|
84
|
+
2. **UI components** — if the element matches a library component, use it (see The One Rule below).
|
|
74
85
|
|
|
75
|
-
|
|
76
|
-
- Section title (h2): `text-2xl font-semibold`
|
|
77
|
-
- Subsection (h3): `text-lg font-semibold`
|
|
78
|
-
- Body: `text-base` (default) — never smaller than `text-sm` for reading content
|
|
79
|
-
- Caption / meta: `text-sm text-[var(--muted-foreground)]`
|
|
86
|
+
Everything else — container widths, grids, flex layouts, padding, hero sections, sidebars, split-pane, masonry, sticky headers, full-bleed backgrounds — is open. Design whatever looks great.
|
|
80
87
|
|
|
81
|
-
###
|
|
88
|
+
### Layout convenience components (optional)
|
|
82
89
|
|
|
83
|
-
|
|
90
|
+
The library exports these if you want quick, consistent scaffolding. Use them when they fit; skip them and write raw Tailwind when they don't.
|
|
84
91
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
| Component | What it gives you |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `<Page width="lg">` | `max-w-[1200px] mx-auto px-6 py-10 flex flex-col gap-12` |
|
|
95
|
+
| `<PageHeader title actions eyebrow>` | Responsive title + description + right-aligned actions |
|
|
96
|
+
| `<Section title description actions>` | Content group with optional header, `flex flex-col gap-6` |
|
|
97
|
+
| `<Toolbar end>` | Left cluster + right cluster split with `ml-auto` |
|
|
98
|
+
| `<Stack direction gap align justify wrap>` | Flex col/row with typed gap scale |
|
|
99
|
+
| `<CardGrid cols>` | Responsive grid, always `gap-6` |
|
|
90
100
|
|
|
91
|
-
|
|
101
|
+
```tsx
|
|
102
|
+
// Using convenience components
|
|
103
|
+
<Page width="lg">
|
|
104
|
+
<PageHeader title="Events" actions={<Button variant="primary" size="md">Add</Button>} />
|
|
105
|
+
<Section title="All Events">
|
|
106
|
+
<CardGrid cols={3}><Card ... /></CardGrid>
|
|
107
|
+
</Section>
|
|
108
|
+
</Page>
|
|
109
|
+
|
|
110
|
+
// Or go fully custom — both are fine
|
|
111
|
+
<div className="min-h-screen bg-[var(--background)]">
|
|
112
|
+
<div className="relative h-[480px] bg-[var(--primary-action)] flex items-end pb-16 px-12">
|
|
113
|
+
<h1 className="text-5xl font-bold text-[var(--on-primary-action)]">Events</h1>
|
|
114
|
+
</div>
|
|
115
|
+
<div className="max-w-[1400px] mx-auto px-8 -mt-12 grid grid-cols-4 gap-6">
|
|
116
|
+
<Card variant="desktop" ... />
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
```
|
|
92
120
|
|
|
93
|
-
|
|
121
|
+
**Stack gap scale** (if used): `1`=4px · `2`=8px · `3`=12px · `4`=16px · `6`=24px · `8`=32px · `10`=40px · `12`=48px
|
|
94
122
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## The One Rule: use library UI components, never recreate them
|
|
126
|
+
|
|
127
|
+
If a UI element matches a component in the list below → import it. Do not rebuild it with raw HTML + Tailwind. Do not add classes that restyle its internal look (colors, border, padding, radius, focus ring). The component already owns those.
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
// ✅ CORRECT
|
|
131
|
+
<Input placeholder="Email" value={email} onChange={setEmail} />
|
|
132
|
+
<Button variant="primary" size="md">Sign in</Button>
|
|
133
|
+
<Tag text="Active" variant="green" />
|
|
134
|
+
|
|
135
|
+
// ❌ WRONG — never recreate library components
|
|
136
|
+
<input className="border rounded-xl px-4 py-3 w-full" placeholder="Email" />
|
|
137
|
+
<button className="bg-blue-600 text-white px-6 py-2 rounded-lg">Sign in</button>
|
|
138
|
+
<span className="bg-green-100 text-green-700 px-2 py-1 rounded">Active</span>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**If the element is NOT in the library → build it freely with Tailwind + tokens.** The library does NOT provide: modal/dialog, sidebar, table, accordion, tooltip, progress bar, avatar, breadcrumb, slider, toggle/switch, file upload, chart, carousel, skeleton, pagination, toast/banner, stepper, menu. Build these with plain HTML + Tailwind + the design tokens above.
|
|
98
142
|
|
|
99
143
|
---
|
|
100
144
|
|
|
101
|
-
## Starter
|
|
145
|
+
## Starter snippets
|
|
102
146
|
|
|
103
|
-
|
|
147
|
+
These are minimal correct examples. Layout structure is up to you — the important parts are the component imports and the `var(--...)` tokens.
|
|
148
|
+
|
|
149
|
+
**List page (using convenience components):**
|
|
104
150
|
|
|
105
151
|
```tsx
|
|
106
|
-
import {
|
|
152
|
+
import { Page, PageHeader, Section, Toolbar, CardGrid, Button, SearchInput, TabGroup, Card } from "@sarunyu/system-one"
|
|
107
153
|
|
|
108
|
-
export default function
|
|
154
|
+
export default function EventsPage() {
|
|
109
155
|
return (
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
<Button variant="primary" size="md">
|
|
156
|
+
<div className="min-h-screen bg-[var(--background)] text-[var(--foreground)]">
|
|
157
|
+
<Page width="lg">
|
|
158
|
+
<PageHeader
|
|
159
|
+
title="Events"
|
|
160
|
+
description="Browse and manage your events."
|
|
161
|
+
actions={<Button variant="primary" size="md">New Event</Button>}
|
|
162
|
+
/>
|
|
163
|
+
<Section title="All Events">
|
|
164
|
+
<Toolbar end={<SearchInput size="sm" placeholder="Search..." value="" onChange={() => {}} />}>
|
|
165
|
+
<TabGroup items={[{ id: "all", title: "All" }, { id: "mine", title: "Mine" }]} activeId="all" onChange={() => {}} size="md" />
|
|
166
|
+
</Toolbar>
|
|
167
|
+
<CardGrid cols={3}>
|
|
168
|
+
<Card variant="desktop" title="Annual Conference" date="Jun 23, 2024" time="08:30 - 12:00" location="Main Hall" count="150/200" tagStatus="registered" image="/banner.jpg" />
|
|
169
|
+
</CardGrid>
|
|
170
|
+
</Section>
|
|
171
|
+
</Page>
|
|
172
|
+
</div>
|
|
173
|
+
)
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**List page (custom layout — equally valid):**
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
import { Button, SearchInput, TabGroup, Card } from "@sarunyu/system-one"
|
|
181
|
+
|
|
182
|
+
export default function EventsPage() {
|
|
183
|
+
return (
|
|
184
|
+
<div className="min-h-screen bg-[var(--background)]">
|
|
185
|
+
{/* Hero */}
|
|
186
|
+
<div className="bg-[var(--primary-action)] px-12 pt-20 pb-32">
|
|
187
|
+
<h1 className="text-5xl font-bold text-[var(--on-primary-action)]">Events</h1>
|
|
188
|
+
<p className="mt-3 text-lg text-[var(--on-primary-action)] opacity-80">Browse and manage your events.</p>
|
|
189
|
+
</div>
|
|
190
|
+
{/* Content pulled up over hero */}
|
|
191
|
+
<div className="max-w-[1400px] mx-auto px-8 -mt-16">
|
|
192
|
+
<div className="flex items-center justify-between mb-6">
|
|
193
|
+
<TabGroup items={[{ id: "all", title: "All" }, { id: "mine", title: "Mine" }]} activeId="all" onChange={() => {}} size="md" />
|
|
194
|
+
<div className="flex gap-3">
|
|
195
|
+
<SearchInput size="sm" placeholder="Search..." value="" onChange={() => {}} />
|
|
196
|
+
<Button variant="primary" size="md">New Event</Button>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-6">
|
|
200
|
+
<Card variant="desktop" title="Annual Conference" date="Jun 23, 2024" time="08:30 - 12:00" location="Main Hall" count="150/200" tagStatus="registered" image="/banner.jpg" />
|
|
116
201
|
</div>
|
|
117
|
-
</header>
|
|
118
|
-
|
|
119
|
-
{/* Page body */}
|
|
120
|
-
<div className="max-w-[1200px] mx-auto px-6 py-12 space-y-12">
|
|
121
|
-
{/* Page header */}
|
|
122
|
-
<section className="space-y-3">
|
|
123
|
-
<h1 className="text-3xl md:text-4xl font-semibold tracking-tight">
|
|
124
|
-
Page title
|
|
125
|
-
</h1>
|
|
126
|
-
<p className="text-base text-[var(--muted-foreground)] max-w-[640px]">
|
|
127
|
-
One-line supporting description that sets context for the page.
|
|
128
|
-
</p>
|
|
129
|
-
</section>
|
|
130
|
-
|
|
131
|
-
{/* Filters */}
|
|
132
|
-
<section className="flex flex-wrap items-center gap-3">
|
|
133
|
-
<TabGroup
|
|
134
|
-
items={[{ id: "all", title: "All" }, { id: "mine", title: "Mine" }]}
|
|
135
|
-
activeId="all"
|
|
136
|
-
onChange={() => {}}
|
|
137
|
-
size="md"
|
|
138
|
-
/>
|
|
139
|
-
</section>
|
|
140
|
-
|
|
141
|
-
{/* Card grid */}
|
|
142
|
-
<section className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
143
|
-
{/* use <Card /> here */}
|
|
144
|
-
</section>
|
|
145
202
|
</div>
|
|
146
|
-
</
|
|
203
|
+
</div>
|
|
147
204
|
)
|
|
148
205
|
}
|
|
149
206
|
```
|
|
150
207
|
|
|
151
|
-
Form page
|
|
208
|
+
**Form page:**
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
import { Stack, Input, TextArea, DateInput, TimeInput, Dropdown, Button } from "@sarunyu/system-one"
|
|
212
|
+
|
|
213
|
+
<div className="max-w-[480px] mx-auto px-6 py-12 space-y-6">
|
|
214
|
+
<h1 className="text-3xl font-semibold text-[var(--foreground)]">Create Event</h1>
|
|
215
|
+
<Stack gap={5}>
|
|
216
|
+
<Input placeholder="Event Name" value={name} onChange={setName} />
|
|
217
|
+
<TextArea placeholder="Description" value={desc} onChange={setDesc} />
|
|
218
|
+
<div className="grid grid-cols-2 gap-3">
|
|
219
|
+
<DateInput placeholder="Start date" mode="single" value={date} onChange={setDate} />
|
|
220
|
+
<TimeInput placeholder="Start time" value={time} onChange={setTime} />
|
|
221
|
+
</div>
|
|
222
|
+
<Dropdown placeholder="Category" options={cats} value={cat} onChange={setCat} />
|
|
223
|
+
<Button variant="primary" size="md" className="w-full">Create Event</Button>
|
|
224
|
+
</Stack>
|
|
225
|
+
</div>
|
|
226
|
+
```
|
|
152
227
|
|
|
153
228
|
---
|
|
154
229
|
|
|
155
|
-
##
|
|
230
|
+
## Typography scale
|
|
156
231
|
|
|
157
|
-
|
|
232
|
+
The library does NOT preset h1–h6 — set them yourself with Tailwind. Always pair with token colors.
|
|
158
233
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
234
|
+
- Page title (h1): `text-3xl md:text-4xl font-semibold tracking-tight text-[var(--foreground)]`
|
|
235
|
+
- Section title (h2): `text-2xl font-semibold text-[var(--foreground)]`
|
|
236
|
+
- Subsection (h3): `text-lg font-semibold text-[var(--foreground)]`
|
|
237
|
+
- Body: `text-base text-[var(--foreground)]` — never smaller than `text-sm` for reading content
|
|
238
|
+
- Caption / meta: `text-sm text-[var(--muted-foreground)]`
|
|
164
239
|
|
|
165
|
-
|
|
166
|
-
<input className="border rounded-xl px-4 py-3 w-full" placeholder="Email" />
|
|
167
|
-
<button className="bg-blue-600 text-white px-6 py-2 rounded-lg">Sign in</button>
|
|
168
|
-
<span className="text-green-500 bg-green-500/10 px-2 py-1 rounded">Active</span>
|
|
169
|
-
```
|
|
240
|
+
### Radius
|
|
170
241
|
|
|
171
|
-
|
|
242
|
+
- Inputs, buttons, small elements: `rounded-md` (6px)
|
|
243
|
+
- Cards, panels: `rounded-xl` (12px) or `rounded-2xl` (16px)
|
|
244
|
+
- Pills / avatars: `rounded-full`
|
|
172
245
|
|
|
173
246
|
---
|
|
174
247
|
|
|
@@ -436,7 +509,7 @@ document.documentElement.classList.toggle("dark", isDark)
|
|
|
436
509
|
### TypeScript
|
|
437
510
|
|
|
438
511
|
```ts
|
|
439
|
-
import type { ButtonVariant, ButtonSize, TagVariant, ChipSize } from "@sarunyu/system-one"
|
|
512
|
+
import type { ButtonVariant, ButtonSize, TagVariant, ChipSize, PageWidth, StackGap } from "@sarunyu/system-one"
|
|
440
513
|
```
|
|
441
514
|
|
|
442
515
|
---
|
|
@@ -444,11 +517,9 @@ import type { ButtonVariant, ButtonSize, TagVariant, ChipSize } from "@sarunyu/s
|
|
|
444
517
|
## Checklist before you render
|
|
445
518
|
|
|
446
519
|
1. Stylesheet imported in the app root entry file? (see Setup)
|
|
447
|
-
2. Every UI element that matches a library component uses that component
|
|
448
|
-
3.
|
|
449
|
-
4.
|
|
450
|
-
5. h1 / h2 / h3
|
|
451
|
-
6. All brand + semantic colors use `var(--...)` tokens, not `bg-blue-500` etc.?
|
|
452
|
-
7. Only one `Button variant="primary"` per context?
|
|
520
|
+
2. Every UI element that matches a library component (Button, Input, Tag, etc.) uses that component — not raw HTML?
|
|
521
|
+
3. All colors use `var(--...)` tokens, not Tailwind literal color utilities (`bg-blue-500`, `text-gray-900`, etc.)?
|
|
522
|
+
4. Only one `Button variant="primary"` per context?
|
|
523
|
+
5. h1 / h2 / h3 use `text-[var(--foreground)]` (or `text-[var(--on-primary-action)]` on dark surfaces)?
|
|
453
524
|
|
|
454
525
|
If any answer is "no", fix it before shipping.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sarunyu/system-one",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A production-ready React design system built for AI-powered web generation tools (Figma Make, Lovable, V0). Tailwind CSS v4 + CSS custom properties for full theming support.",
|
|
6
6
|
"keywords": [
|