@sakaniui/react 0.4.6 → 0.4.8
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 +225 -0
- package/README.md +2 -0
- package/dist/{TopBar-C6gcyAqg.cjs → TopBar-Cjp7d4Vn.cjs} +1 -1
- package/dist/{TopBar-DtglKg4p.js → TopBar-DrobSPbL.js} +10 -9
- package/dist/blocks.cjs +1 -1
- package/dist/blocks.mjs +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/style.css +1 -1
- package/package.json +3 -2
package/AGENTS.md
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# Sakani UI — guide for AI agents
|
|
2
|
+
|
|
3
|
+
You are building with `@sakaniui/react`. This file is the *why* behind the system: what each
|
|
4
|
+
piece is for, when it is the wrong choice, and what to do when nothing fits. Props and types are
|
|
5
|
+
in the shipped `.d.ts` files; live examples are at https://www.sakaniui.com/docs. Read this file
|
|
6
|
+
first, then open a component's docs page for its props.
|
|
7
|
+
|
|
8
|
+
Full machine-readable index: https://www.sakaniui.com/llms.txt (and `/llms-full.txt`).
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Setup you must get right
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import '@sakaniui/react/tokens.css'; // design tokens (CSS variables) — once, at the app root
|
|
16
|
+
import '@sakaniui/react/style.css'; // component styles — once
|
|
17
|
+
import { Button, Card } from '@sakaniui/react';
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- **Both CSS imports are required.** Without `tokens.css` every component renders unstyled or
|
|
21
|
+
black-and-white, because every colour, space, radius and shadow is a CSS variable defined there.
|
|
22
|
+
- **Dark mode is a class.** Put `className="dark"` on any container; everything inside re-themes.
|
|
23
|
+
Do not write per-component dark styles.
|
|
24
|
+
- **Surface is a second axis, independent of light/dark:** `data-surface="solid" | "glass" | "liquid"`
|
|
25
|
+
on a container. Components inside adapt. See §4.
|
|
26
|
+
|
|
27
|
+
## 2. Principles (apply these when a case is not covered)
|
|
28
|
+
|
|
29
|
+
1. **Tokens, never literals.** Colours, spacing, radius, shadows come from `var(--color-…)`,
|
|
30
|
+
`var(--space-…)`, `var(--radius-…)`. A hex value in your code will not follow dark mode, glass
|
|
31
|
+
surfaces or future theme changes. If you need a colour that has no token, pick the nearest
|
|
32
|
+
semantic token and say so; do not invent a hex.
|
|
33
|
+
2. **Semantic roles over raw values.** Use `--color-fg-default / -muted / -subtle`, `--color-bg-surface /
|
|
34
|
+
-canvas / -subtle`, `--color-border-subtle / -default / -focus`, `--color-accent-*`. The role says
|
|
35
|
+
what the colour is *for*, which is what survives a re-theme.
|
|
36
|
+
3. **One primary action per view.** A single filled `primary` Button marks the thing the user most
|
|
37
|
+
likely wants. Two filled buttons compete and make neither primary. Put the second action in
|
|
38
|
+
`secondary` or `outline`, the third in `ghost`.
|
|
39
|
+
4. **Use the component, don't restyle a `<button>`.** Buttons carry hover, press, focus-visible,
|
|
40
|
+
loading and (on glass) liquid behaviour. A hand-styled `<button>` silently misses every future
|
|
41
|
+
improvement. (Two components shipped with raw buttons and were fixed in 0.4.6 and 0.4.7 for exactly
|
|
42
|
+
this reason.)
|
|
43
|
+
5. **States are CSS, not props.** Hover, focus-visible and disabled are pseudo-classes. Don't try to
|
|
44
|
+
force a hover state with a prop; none exists. Exceptions are documented presentational states
|
|
45
|
+
(e.g. `BoardCard state="dragging"`).
|
|
46
|
+
6. **Accessibility is part of the API, not an extra.** Icon-only controls require a label
|
|
47
|
+
(`aria-label`, or `label` on `socialLinks`). Status changes use live regions (`Alert`, `Toast`,
|
|
48
|
+
`Spinner`, `EmptyState` are `role="status"`/`alert`). Never remove focus rings.
|
|
49
|
+
7. **Don't fake what the system doesn't do.** `Toast` is presentational — you own queueing and
|
|
50
|
+
positioning. `Menu` is a surface — you own anchoring (pair it with `Popover`). Dragging is a
|
|
51
|
+
look, not a behaviour. Check "Behaviour you must supply" in the table below before assuming.
|
|
52
|
+
8. **Compose in slots, don't fork.** Components expose slots (`leading`, `trailing`, `meta`,
|
|
53
|
+
`assignees`, `icon`, `actions`). Fill a slot with other system components rather than copying a
|
|
54
|
+
component's markup.
|
|
55
|
+
|
|
56
|
+
## 2b. Token names — use exactly these (anything else does not exist)
|
|
57
|
+
|
|
58
|
+
A CSS variable that isn't defined silently resolves to nothing: no error, just broken spacing or
|
|
59
|
+
colour. Do not guess names (`--fg-muted`, `--bg-canvas`, `--spacing-4` and `--space-3` are all **wrong**).
|
|
60
|
+
|
|
61
|
+
- **Space** — `--space-N` where **N is the pixel value**: `0, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 32, 40, 48, 64, 80, 96`. So `--space-6` is 6px (not 24px)
|
|
62
|
+
and `--space-24` is 24px. There is no `--space-3` or `--space-5`.
|
|
63
|
+
- **Text** — `--color-fg-default`, `--color-fg-muted`, `--color-fg-subtle`, `--color-fg-on-accent`,
|
|
64
|
+
`--color-fg-on-inverse`.
|
|
65
|
+
- **Backgrounds** — `--color-bg-canvas` (page), `--color-bg-surface` (cards, panels), `--color-bg-subtle`,
|
|
66
|
+
`--color-bg-muted`, `--color-bg-inverse`.
|
|
67
|
+
- **Borders** — `--color-border-subtle`, `--color-border-default`, `--color-border-strong`,
|
|
68
|
+
`--color-border-focus`.
|
|
69
|
+
- **Brand/status** — `--color-accent-{default,hover,active,subtle,fg}`; for `danger`, `success`,
|
|
70
|
+
`warning`, `info`: `--color-<status>-{bg,border,fg,solid}` plus a 50–950 scale.
|
|
71
|
+
- **Radius** — `--radius-{none,2xs,xs,sm,md,lg,xl,2xl,3xl,full}` (`md` = 8px is the default control radius).
|
|
72
|
+
- **Shadow** — `--shadow-{xs,sm,md,lg,xl,2xl}`. **Font** — `--font-sans`, `--font-mono`.
|
|
73
|
+
**Motion** — `--transition-{fast,base,hover,slow}`.
|
|
74
|
+
- Full, resolved list for light and dark: https://www.sakaniui.com/docs/tokens
|
|
75
|
+
|
|
76
|
+
## 3. When nothing fits
|
|
77
|
+
|
|
78
|
+
Work down this list and stop at the first that works:
|
|
79
|
+
|
|
80
|
+
1. **A variant or slot of an existing component** (most "missing" cases are one).
|
|
81
|
+
2. **Compose two or three existing components** inside a `Card` or a block layout.
|
|
82
|
+
3. **Compose from tokens** — your own element styled only with `var(--…)` values and system
|
|
83
|
+
components inside. Match the 8px radius (`--radius-md`) and token spacing of neighbours.
|
|
84
|
+
4. **Say what is missing.** If the need is real and not covered, tell the user plainly
|
|
85
|
+
("the system has no X; I built Y from tokens") instead of silently approximating. Do not present a
|
|
86
|
+
workaround as a system component.
|
|
87
|
+
|
|
88
|
+
Never: invent props that aren't in the `.d.ts`, import from `dist/` internals, or copy the
|
|
89
|
+
CSS of a component into your own file.
|
|
90
|
+
|
|
91
|
+
## 4. Glass and Liquid Glass
|
|
92
|
+
|
|
93
|
+
- **`solid`** (default): opaque, crisp. Use for dense data — tables, forms, charts. Reading speed
|
|
94
|
+
beats atmosphere.
|
|
95
|
+
- **`glass`**: frosted translucency. Use for chrome floating over content: sidebars, bars, popovers.
|
|
96
|
+
- **`liquid`**: real refraction that bends what is behind it. Use sparingly, for a few large
|
|
97
|
+
navigational or hero surfaces over a rich image or gradient. It needs something visually
|
|
98
|
+
interesting behind it; over a flat colour it adds cost and nothing else.
|
|
99
|
+
- **Don't put data inside liquid.** Keep tables, inputs and charts on `data-surface="solid"` inside a
|
|
100
|
+
liquid layout so numbers stay legible.
|
|
101
|
+
- **Refraction renders in Chromium only.** Safari and Firefox get a frosted fallback with the same rim.
|
|
102
|
+
Design so the fallback is acceptable, not broken. Use `refraction="off"` to preview the fallback.
|
|
103
|
+
- **Cost is per lens.** Each liquid surface runs an SVG filter. Dozens on one screen will lag; a
|
|
104
|
+
handful is fine. Large static lenses are baked to a canvas automatically (`bake`).
|
|
105
|
+
- **`LiquidBackdrop` supplies what is behind the lens.** A lens needs a backdrop to refract; wrap
|
|
106
|
+
the photo/gradient in `LiquidBackdrop`.
|
|
107
|
+
|
|
108
|
+
## 5. Component guide — what it's for, why it behaves that way, when not to use it
|
|
109
|
+
|
|
110
|
+
Format: **Use for** · **Why it is built this way** · **Not for / instead**.
|
|
111
|
+
|
|
112
|
+
### Actions
|
|
113
|
+
- **Button** — Use for any action that does something. *Why:* 5 variants × 3 sizes mirror Figma 1:1;
|
|
114
|
+
`loading` disables interaction so double-submits can't happen. *Not for* navigation → `Link`; icon-only →
|
|
115
|
+
`IconButton`. One `primary` per view.
|
|
116
|
+
- **IconButton** — Use for compact, recognisable actions (close, more, add). *Why:* square, same variant
|
|
117
|
+
logic as Button, and `aria-label` is required because a glyph alone is unusable with a screen reader.
|
|
118
|
+
*Not for* anything whose icon isn't universally obvious → `Button` with a label.
|
|
119
|
+
- **Link** — Use for navigation. *Why:* a link goes somewhere, a button does something; mixing them breaks
|
|
120
|
+
keyboard and assistive-tech expectations.
|
|
121
|
+
|
|
122
|
+
### Status and feedback
|
|
123
|
+
- **Alert** — Use for a message that belongs to the page or a section and stays until resolved.
|
|
124
|
+
*Not for* transient confirmation → `Toast`.
|
|
125
|
+
- **Toast** — Use for short-lived confirmation or error after an action. *Why:* presentational only;
|
|
126
|
+
queueing and positioning are the app's job, so it fits any notification system. *Not for* anything the user
|
|
127
|
+
must act on — a toast disappears.
|
|
128
|
+
- **Badge** — Use for a short status, category or count. *Why:* 6 colours × subtle/solid, no sizes, no
|
|
129
|
+
borders — it is a label, not a control. *Not for* clickable filters → `FilterChip`.
|
|
130
|
+
- **Tooltip** — Use for brief supplementary text on hover/focus. *Why:* pure CSS, so it works with
|
|
131
|
+
keyboard focus. *Not for* essential information (touch users never see hover) or interactive content →
|
|
132
|
+
`Popover`.
|
|
133
|
+
- **Spinner / Progress / Skeleton** — Spinner: an action is running, unknown length. Progress: known
|
|
134
|
+
completion (give `value`) or an indeterminate page load (omit it). Skeleton: the *shape* of content that is
|
|
135
|
+
about to appear. *Why:* a skeleton keeps layout stable and tells the user what is coming; a spinner only
|
|
136
|
+
says "wait". Prefer Skeleton for first-load of lists/cards.
|
|
137
|
+
- **EmptyState** — Use when a list, table or panel has nothing to show. *Why three types:* `no-data`
|
|
138
|
+
(nothing exists → action is to create), `no-results` (a filter hides things → relax the filter),
|
|
139
|
+
`error` (request failed → retry). They are different situations needing different actions; one generic
|
|
140
|
+
message wastes the moment. Override `title`/`description` with specifics wherever possible.
|
|
141
|
+
|
|
142
|
+
### Forms
|
|
143
|
+
- **Input / Textarea / Select / Combobox** — Input: free text. Select: choose one from a short fixed list
|
|
144
|
+
(it is a custom listbox, not native `<select>`, so the open state matches the design). Combobox: search a
|
|
145
|
+
long list or pick several (multi, with chips). *Why:* choosing the lightest control that fits keeps forms
|
|
146
|
+
fast; don't use a Combobox for four options.
|
|
147
|
+
- **Checkbox / Radio / Switch** — Checkbox: independent yes/no, or multiple choices. Radio: exactly one of a
|
|
148
|
+
few (give them a shared `name`). Switch: an immediate on/off that takes effect now; a checkbox is for
|
|
149
|
+
things applied on submit.
|
|
150
|
+
- **SegmentedControl** — Use to switch between 2–6 views or modes of the *same* content. *Not for*
|
|
151
|
+
navigation between pages → `Tabs`.
|
|
152
|
+
- **FileUpload / AvatarUpload** — Use for files / profile photos respectively.
|
|
153
|
+
- **Always give inputs a visible label** (`Input` has one built in). Placeholders are not labels.
|
|
154
|
+
|
|
155
|
+
### Navigation
|
|
156
|
+
- **Sidebar family** (`Sidebar`, `SidebarItem`, …) — Use for app-level navigation. Expanded 248px,
|
|
157
|
+
collapsed 64px. Compose the parts; don't build a sidebar from scratch.
|
|
158
|
+
- **TopBar** — Use beside the sidebar for search, breadcrumb, tabs, or chat context. Slots (`left`,
|
|
159
|
+
`actions`, `account`) are composed by the caller.
|
|
160
|
+
- **Tabs** — Switch between peer panels in one place. **Breadcrumb** — show where a deep page sits.
|
|
161
|
+
**Pagination** — move through pages of a long list. **Stepper** — a fixed multi-step flow; completed /
|
|
162
|
+
current / upcoming states; motion is choreographed on step change.
|
|
163
|
+
- **Menu** — a list of actions in a surface; *you* anchor it (pair with `Popover`). **Popover** — floating
|
|
164
|
+
panel on click; closes on outside click or Escape.
|
|
165
|
+
- **Modal** — Use only when the task genuinely must interrupt (confirm destructive action, short focused
|
|
166
|
+
form). Anything the user might want to refer back to the page for → `Popover` or inline.
|
|
167
|
+
|
|
168
|
+
### Content and data
|
|
169
|
+
- **Card** — a container surface for a unit of content, optionally with actions. Not a layout wrapper for
|
|
170
|
+
everything.
|
|
171
|
+
- **Table** — dense, comparable records. **StatCard** — one headline metric with trend. **ListItem** — a
|
|
172
|
+
row in a list. **Charts** — pick by question: trend over time → Line/Area; compare categories → Bar;
|
|
173
|
+
part of whole → Pie/Donut (few slices only); progress to a target → Radial; compare several measures →
|
|
174
|
+
Radar; drop-off → Funnel; intensity across two dimensions → Heatmap.
|
|
175
|
+
- **Avatar / AvatarGroup** — Avatar type is inferred: `src` → image, `initials` → initials, else icon.
|
|
176
|
+
Prefer a real image when you have one; initials are the fallback, not the default.
|
|
177
|
+
- **BoardCard / BoardColumn** — kanban pieces. `BoardColumn state="loading"` styles the column; *you* pass
|
|
178
|
+
Skeleton-filled `BoardCard`s as children. `state="dragging"` only styles; implement drag yourself.
|
|
179
|
+
- **ProfileCard / TeamCard** — ProfileCard: compact (row) or detailed (centred, with bio/social). TeamCard:
|
|
180
|
+
portrait-led with a location bar. Both want a real photo.
|
|
181
|
+
|
|
182
|
+
### Blocks
|
|
183
|
+
Blocks (`CRMDashboardBlock`, `DataTableBlock`, `KanbanBoardBlock`, `LoginBlock`, …) are composed
|
|
184
|
+
screens, not primitives. Use one when it matches the screen you are building; otherwise compose primitives.
|
|
185
|
+
Many Figma-frame blocks have a fixed design width — put them in a container at least that wide or scale them.
|
|
186
|
+
|
|
187
|
+
## 6. Moments an AI product needs (compose these today)
|
|
188
|
+
|
|
189
|
+
The system has no dedicated AI components yet. Until it does, build these moments from existing parts,
|
|
190
|
+
and **tell the user when you are composing** rather than implying a dedicated component exists.
|
|
191
|
+
|
|
192
|
+
- **The model isn't sure.** State uncertainty in words next to the claim, not hidden in colour. Use an
|
|
193
|
+
`Alert` (`color="info"` or `"warning"`) or a `Badge` ("Low confidence"). Offer the next step: verify,
|
|
194
|
+
rephrase, or ask for more context.
|
|
195
|
+
- **Showing a source.** Attach sources to the claim they support, as `Link`s or `Tags`/`Badge`s with a
|
|
196
|
+
visible domain or title. A claim without a reachable source should look different from one with it.
|
|
197
|
+
- **A request that will not be completed.** Say what was declined and why in plain language, then what
|
|
198
|
+
*can* be done. Use `Alert` (not an error toast — the user did nothing wrong) plus an alternative action
|
|
199
|
+
as a `secondary` Button.
|
|
200
|
+
- **A response that is only half there.** Streaming or partial: show `Skeleton` or a `Spinner` for the
|
|
201
|
+
missing remainder, keep what has arrived, and make interruption possible. Never present a truncated
|
|
202
|
+
answer as complete; mark it ("Response cut off") and offer retry. Use `EmptyState type="error"` only
|
|
203
|
+
when nothing usable arrived.
|
|
204
|
+
- **Chat.** `MessageBubble`, `ConversationItem`, `ChatComposer` cover the shell. Keep the composer
|
|
205
|
+
reachable while a response is streaming.
|
|
206
|
+
|
|
207
|
+
## 7. Behaviour you must supply (the system will not do these)
|
|
208
|
+
|
|
209
|
+
| Component | You own |
|
|
210
|
+
|---|---|
|
|
211
|
+
| Toast | queueing, positioning, auto-dismiss timing |
|
|
212
|
+
| Menu | anchoring/positioning (pair with Popover) |
|
|
213
|
+
| BoardCard `dragging` | drag-and-drop logic and drop targets |
|
|
214
|
+
| BoardColumn `loading` | the skeleton cards inside it |
|
|
215
|
+
| Blocks | data fetching and state; they are presentational |
|
|
216
|
+
| LiquidGlass | a backdrop worth refracting (`LiquidBackdrop`) |
|
|
217
|
+
|
|
218
|
+
## 8. Checklist before you finish
|
|
219
|
+
|
|
220
|
+
- [ ] Both CSS files imported once; no hex/px literals where a token exists.
|
|
221
|
+
- [ ] Exactly one `primary` Button per view; no hand-styled `<button>`.
|
|
222
|
+
- [ ] Every icon-only control has an accessible name.
|
|
223
|
+
- [ ] Looks right inside `className="dark"`.
|
|
224
|
+
- [ ] If you used glass/liquid: acceptable in the frosted fallback; data surfaces stay `solid`.
|
|
225
|
+
- [ ] You said so wherever you composed something the system doesn't provide.
|
package/README.md
CHANGED
|
@@ -31,6 +31,8 @@ Then import the tokens once at your app's entry point, and any component from th
|
|
|
31
31
|
import '@sakaniui/react/tokens.css';
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
> **Building with AI?** `AGENTS.md` (shipped in this package) explains *why* components behave as they do and what to do when nothing fits. Index for agents: https://www.sakaniui.com/llms.txt
|
|
35
|
+
|
|
34
36
|
## Quick start (contributing / browsing the source)
|
|
35
37
|
|
|
36
38
|
```bash
|