@sakaniui/react 0.4.7 → 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.
Files changed (3) hide show
  1. package/AGENTS.md +225 -0
  2. package/README.md +2 -0
  3. 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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sakaniui/react",
3
- "version": "0.4.7",
3
+ "version": "0.4.8",
4
4
  "description": "Sakani Design System — token-driven React components and blocks with light & dark modes, plus built-in glass and Apple-style liquid glass surfaces.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -34,7 +34,8 @@
34
34
  "**/*.css"
35
35
  ],
36
36
  "files": [
37
- "dist"
37
+ "dist",
38
+ "AGENTS.md"
38
39
  ],
39
40
  "publishConfig": {
40
41
  "access": "public"