@sableui/react 0.11.0 → 0.13.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 +10 -4
- package/CHANGELOG.md +199 -0
- package/DESIGN.md +3 -3
- package/README.md +15 -1
- package/bin/sable.mjs +254 -10
- package/dist/components/app-header/app-header.meta.js +2 -1
- package/dist/components/button/button.js +3 -0
- package/dist/components/button/button.meta.js +1 -1
- package/dist/components/button/button.variants.js +1 -1
- package/dist/components/button-group/button-group.js +17 -0
- package/dist/components/button-group/button-group.meta.js +72 -0
- package/dist/components/button-group/index.js +7 -0
- package/dist/components/caret-menu/caret-menu.js +221 -0
- package/dist/components/caret-menu/caret-menu.meta.js +119 -0
- package/dist/components/caret-menu/index.js +8 -0
- package/dist/components/chat-composer/chat-composer.js +30 -7
- package/dist/components/chat-composer/chat-composer.meta.js +27 -8
- package/dist/components/combobox/combobox.meta.js +26 -0
- package/dist/components/input-group/index.js +7 -0
- package/dist/components/input-group/input-group.js +66 -0
- package/dist/components/input-group/input-group.meta.js +106 -0
- package/dist/components/menu/index.js +2 -0
- package/dist/components/menu/menu.js +51 -9
- package/dist/components/menu/menu.meta.js +11 -2
- package/dist/components/menubar/index.js +8 -0
- package/dist/components/menubar/menubar.js +42 -0
- package/dist/components/menubar/menubar.meta.js +99 -0
- package/dist/components/message-scroller/message-scroller.meta.js +4 -0
- package/dist/components/navigation-menu/index.js +19 -0
- package/dist/components/navigation-menu/navigation-menu.js +108 -0
- package/dist/components/navigation-menu/navigation-menu.meta.js +141 -0
- package/dist/components/overflow-menu/overflow-menu.meta.js +13 -1
- package/dist/components/pagination/pagination.js +11 -5
- package/dist/components/pagination/pagination.meta.js +21 -3
- package/dist/components/scroller/scroller.js +8 -4
- package/dist/components/scroller/scroller.meta.js +6 -0
- package/dist/components/sheet/sheet.js +82 -9
- package/dist/components/sheet/sheet.meta.js +41 -4
- package/dist/components/sheet/sheet.variants.js +8 -1
- package/dist/components/sidebar/sidebar.js +13 -2
- package/dist/components/sidebar/sidebar.meta.js +10 -0
- package/dist/components/streaming-text/streaming-text.meta.js +5 -1
- package/dist/file-hashes.json +49 -33
- package/dist/icon-sets/reicon.js +2 -0
- package/dist/index.d.ts +660 -164
- package/dist/index.js +12 -1
- package/dist/lib/palette.js +46 -6
- package/dist/lib/taxonomy.js +5 -0
- package/dist/lib/use-caret-trigger.js +187 -0
- package/dist/lib/use-copy.js +6 -1
- package/dist/lib/use-smooth-wheel.js +164 -0
- package/dist/palette.css +243 -165
- package/dist/patterns/chat-panel.js +1 -1
- package/dist/patterns/chat-panel.meta.js +1 -0
- package/dist/styles.css +25 -0
- package/llms/components/app-header.md +1 -1
- package/llms/components/button-group.md +55 -0
- package/llms/components/button.md +1 -1
- package/llms/components/caret-menu.md +100 -0
- package/llms/components/chat-composer.md +24 -7
- package/llms/components/combobox.md +12 -0
- package/llms/components/input-group.md +78 -0
- package/llms/components/menu.md +16 -1
- package/llms/components/menubar.md +110 -0
- package/llms/components/message-scroller.md +1 -0
- package/llms/components/navigation-menu.md +113 -0
- package/llms/components/overflow-menu.md +26 -1
- package/llms/components/pagination.md +15 -3
- package/llms/components/scroller.md +1 -0
- package/llms/components/sheet.md +18 -3
- package/llms/components/sidebar.md +2 -0
- package/llms/components/streaming-text.md +2 -1
- package/llms/patterns/chat-panel.md +4 -1
- package/llms/reference/token-intent.md +1 -1
- package/llms/tasks/building-a-chat.md +158 -0
- package/llms/tasks/building-with-sable.md +4 -1
- package/llms/tasks/converting-an-app.md +7 -0
- package/llms/tasks/extending-a-component.md +170 -0
- package/llms/tasks/getting-started.md +22 -4
- package/llms/tasks/migrating-from-shadcn.md +351 -0
- package/llms-full.txt +1322 -27
- package/llms.txt +13 -4
- package/package.json +3 -2
- package/registry.json +979 -23
- package/scripts/lint-rules.mjs +35 -0
- package/scripts/wiring.mjs +541 -0
- package/skills/entry/SKILL.md +3 -2
- package/skills/sable/SKILL.md +26 -5
- package/targets/ios.json +45 -0
- package/dist/lib/use-wheel-to-horizontal.js +0 -65
package/skills/sable/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sable
|
|
3
|
-
description: Build original websites and apps with Sable, turn inspiration into reusable presets, audit existing interfaces,
|
|
3
|
+
description: Build original websites and apps with Sable, turn inspiration into reusable presets, audit existing interfaces, polish a selected design, and fix a scoped defect on a short path. Use for Sable design and UI work, not unrelated backend tasks.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Sable
|
|
@@ -9,7 +9,27 @@ Build the user's idea with the installed Sable library. The product brief determ
|
|
|
9
9
|
content, structure, and behavior; a preset supplies theme values and design guidance.
|
|
10
10
|
References inform an original direction. A reference or preset is optional.
|
|
11
11
|
|
|
12
|
-
##
|
|
12
|
+
## Fix: the short path
|
|
13
|
+
|
|
14
|
+
A `fix` is a scoped change to UI that already uses Sable: a wrong prop or variant,
|
|
15
|
+
a lint or doctor finding, a broken state, one control swapped for the right one.
|
|
16
|
+
It needs this section and the CLI from "Resolve and set up the installed library";
|
|
17
|
+
skip the manifest, the design guides, and the finish checklist below.
|
|
18
|
+
|
|
19
|
+
1. Read only what the change touches: `sable component <Name> --props`, the
|
|
20
|
+
example you need (`sable search "<need>"` finds it), `sable token <group>` or
|
|
21
|
+
`sable utility <name>` for a styling question, and `sable docs <foundation>`
|
|
22
|
+
only when the fix is about type, spacing, motion, or accessibility.
|
|
23
|
+
2. Change the smallest amount of code that fixes it. A defect inside a Sable
|
|
24
|
+
component is patched, not restyled (see the end of this file).
|
|
25
|
+
3. Run `sable check <changed paths>` and the project's own build and type checks,
|
|
26
|
+
then look at the affected state rendered, in every colour mode the app ships.
|
|
27
|
+
|
|
28
|
+
Escalate to `polish` and its finish checklist when the change moves layout or
|
|
29
|
+
hierarchy, touches a signature surface, spans more than one screen or flow, or
|
|
30
|
+
the check turns up more than the fix. Say that you escalated, and why.
|
|
31
|
+
|
|
32
|
+
## Finish checklist — before you call any build or polish done
|
|
13
33
|
|
|
14
34
|
1. Run `sable check <source paths>` (default `src`). It runs `sable doctor`,
|
|
15
35
|
`sable lint`, and `sable grade` and exits 1 if any fails. Repair the findings
|
|
@@ -51,9 +71,10 @@ These are agent skill modes, not shell commands. Use `$sable` in Codex and
|
|
|
51
71
|
| `inspire <references or description>` | Study the inspiration, develop a direction, and save a previewable, editable preset. Stop before a full product build. |
|
|
52
72
|
| `audit <existing interface>` | Inspect existing work and report prioritized design, behavior, accessibility, and Sable-contract findings. Apply repairs only when requested. |
|
|
53
73
|
| `polish <target or instruction>` | Improve the current product or preset while preserving its selected direction, then verify affected states. |
|
|
74
|
+
| `fix <target or finding>` | Repair one scoped defect in existing Sable UI on the short path at the top of this file, escalating to `polish` when it grows. |
|
|
54
75
|
|
|
55
76
|
`create` is an alias for `build`. A bare new-product brief means `build`; an editing
|
|
56
|
-
follow-up means `polish`. A request for direction only stops before implementation.
|
|
77
|
+
follow-up means `polish`, unless it names one defect, which is a `fix`. A request for direction only stops before implementation.
|
|
57
78
|
“Show alternatives” produces bounded rendered studies and stops at comparison when
|
|
58
79
|
the user reserves the choice. Explore only when requested or when competing choices
|
|
59
80
|
materially affect the brief; do not require three designs for every build.
|
|
@@ -140,7 +161,7 @@ Before UI code, run `sable manifest --json`, read `sable docs building-with-sabl
|
|
|
140
161
|
foundations through `sable docs typography|spacing|shape|surfaces|motion|scrolling|accessibility`.
|
|
141
162
|
The installed catalog and guides are authoritative for API and token names.
|
|
142
163
|
|
|
143
|
-
**Required for every build and
|
|
164
|
+
**Required for every build and polish:**
|
|
144
165
|
|
|
145
166
|
1. Search the installed catalog for every recognizable element or behavior:
|
|
146
167
|
`sable search "<need>" --json`. Inspect the matching
|
|
@@ -251,7 +272,7 @@ contract violations, design judgments, intentional choices, and verified library
|
|
|
251
272
|
gaps. A visual-only review leaves code and unobserved behavior untested. For
|
|
252
273
|
`polish`, reuse the existing direction and inspect the affected product or preset.
|
|
253
274
|
|
|
254
|
-
Every build ends with the finish checklist
|
|
275
|
+
Every build and polish ends with the finish checklist near the top of this skill. Notes on it:
|
|
255
276
|
|
|
256
277
|
- `sable check` gives one combined result; while iterating, `sable lint <paths> --json`,
|
|
257
278
|
`sable doctor`, and `sable grade <paths>` run the parts separately.
|
package/targets/ios.json
CHANGED
|
@@ -218,6 +218,15 @@
|
|
|
218
218
|
],
|
|
219
219
|
"defaultContext": "Everything else"
|
|
220
220
|
},
|
|
221
|
+
"ButtonGroup": {
|
|
222
|
+
"source": "ButtonGroup",
|
|
223
|
+
"strategy": "preserve",
|
|
224
|
+
"importFrom": "@sableui/react",
|
|
225
|
+
"components": [
|
|
226
|
+
"ButtonGroup"
|
|
227
|
+
],
|
|
228
|
+
"guidance": "Use the Sable component as it is, in the preset. Adapt layout and touch targets to the phone; do not swap in a native lookalike or restyle it."
|
|
229
|
+
},
|
|
221
230
|
"Calendar": {
|
|
222
231
|
"source": "Calendar",
|
|
223
232
|
"strategy": "preserve",
|
|
@@ -236,6 +245,15 @@
|
|
|
236
245
|
],
|
|
237
246
|
"guidance": "Use the Sable component as it is, in the preset. Adapt layout and touch targets to the phone; do not swap in a native lookalike or restyle it."
|
|
238
247
|
},
|
|
248
|
+
"CaretMenu": {
|
|
249
|
+
"source": "CaretMenu",
|
|
250
|
+
"strategy": "preserve",
|
|
251
|
+
"importFrom": "@sableui/react",
|
|
252
|
+
"components": [
|
|
253
|
+
"CaretMenu"
|
|
254
|
+
],
|
|
255
|
+
"guidance": "Use the Sable component as it is, in the preset. Adapt layout and touch targets to the phone; do not swap in a native lookalike or restyle it."
|
|
256
|
+
},
|
|
239
257
|
"Carousel": {
|
|
240
258
|
"source": "Carousel",
|
|
241
259
|
"strategy": "preserve",
|
|
@@ -498,6 +516,15 @@
|
|
|
498
516
|
],
|
|
499
517
|
"guidance": "Use the Sable component as it is, in the preset. Adapt layout and touch targets to the phone; do not swap in a native lookalike or restyle it."
|
|
500
518
|
},
|
|
519
|
+
"InputGroup": {
|
|
520
|
+
"source": "InputGroup",
|
|
521
|
+
"strategy": "preserve",
|
|
522
|
+
"importFrom": "@sableui/react",
|
|
523
|
+
"components": [
|
|
524
|
+
"InputGroup"
|
|
525
|
+
],
|
|
526
|
+
"guidance": "Use the Sable component as it is, in the preset. Adapt layout and touch targets to the phone; do not swap in a native lookalike or restyle it."
|
|
527
|
+
},
|
|
501
528
|
"Kbd": {
|
|
502
529
|
"source": "Kbd",
|
|
503
530
|
"strategy": "preserve",
|
|
@@ -570,6 +597,15 @@
|
|
|
570
597
|
],
|
|
571
598
|
"guidance": "Use the Sable component as it is, in the preset. Adapt layout and touch targets to the phone; do not swap in a native lookalike or restyle it."
|
|
572
599
|
},
|
|
600
|
+
"Menubar": {
|
|
601
|
+
"source": "Menubar",
|
|
602
|
+
"strategy": "preserve",
|
|
603
|
+
"importFrom": "@sableui/react",
|
|
604
|
+
"components": [
|
|
605
|
+
"Menubar"
|
|
606
|
+
],
|
|
607
|
+
"guidance": "Use the Sable component as it is, in the preset. Adapt layout and touch targets to the phone; do not swap in a native lookalike or restyle it."
|
|
608
|
+
},
|
|
573
609
|
"Message": {
|
|
574
610
|
"source": "Message",
|
|
575
611
|
"strategy": "preserve",
|
|
@@ -606,6 +642,15 @@
|
|
|
606
642
|
],
|
|
607
643
|
"guidance": "Use the Sable component as it is, in the preset. Adapt layout and touch targets to the phone; do not swap in a native lookalike or restyle it."
|
|
608
644
|
},
|
|
645
|
+
"NavigationMenu": {
|
|
646
|
+
"source": "NavigationMenu",
|
|
647
|
+
"strategy": "preserve",
|
|
648
|
+
"importFrom": "@sableui/react",
|
|
649
|
+
"components": [
|
|
650
|
+
"NavigationMenu"
|
|
651
|
+
],
|
|
652
|
+
"guidance": "Use the Sable component as it is, in the preset. Adapt layout and touch targets to the phone; do not swap in a native lookalike or restyle it."
|
|
653
|
+
},
|
|
609
654
|
"Note": {
|
|
610
655
|
"source": "Note",
|
|
611
656
|
"strategy": "preserve",
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
// src/lib/use-wheel-to-horizontal.ts
|
|
4
|
-
import { useCallback, useRef } from "react";
|
|
5
|
-
var LINE_HEIGHT = 16;
|
|
6
|
-
var PAGE_HEIGHT = 400;
|
|
7
|
-
function toPixels(delta, mode) {
|
|
8
|
-
if (mode === 1) return delta * LINE_HEIGHT;
|
|
9
|
-
if (mode === 2) return delta * PAGE_HEIGHT;
|
|
10
|
-
return delta;
|
|
11
|
-
}
|
|
12
|
-
function useWheelToHorizontal(enabled = true) {
|
|
13
|
-
const nodeRef = useRef(null);
|
|
14
|
-
const onWheel = useCallback((event) => {
|
|
15
|
-
const el = nodeRef.current;
|
|
16
|
-
if (!el) return;
|
|
17
|
-
if (event.shiftKey) return;
|
|
18
|
-
if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) return;
|
|
19
|
-
if (event.deltaY === 0) return;
|
|
20
|
-
const delta = toPixels(event.deltaY, event.deltaMode);
|
|
21
|
-
const max = el.scrollWidth - el.clientWidth;
|
|
22
|
-
if (max <= 0) return;
|
|
23
|
-
const atStart = Math.round(el.scrollLeft) <= 0;
|
|
24
|
-
const atEnd = Math.round(el.scrollLeft) >= max;
|
|
25
|
-
if (delta < 0 && atStart || delta > 0 && atEnd) return;
|
|
26
|
-
event.preventDefault();
|
|
27
|
-
el.scrollLeft += delta;
|
|
28
|
-
}, []);
|
|
29
|
-
return useCallback(
|
|
30
|
-
(node) => {
|
|
31
|
-
const previous = nodeRef.current;
|
|
32
|
-
if (previous === node) return;
|
|
33
|
-
previous?.removeEventListener("wheel", onWheel);
|
|
34
|
-
nodeRef.current = node;
|
|
35
|
-
if (node && enabled) {
|
|
36
|
-
node.addEventListener("wheel", onWheel, { passive: false });
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
[enabled, onWheel]
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
function scrollRegionKeyDown(event, orientation) {
|
|
43
|
-
const el = event.currentTarget;
|
|
44
|
-
const horizontal = orientation === "horizontal";
|
|
45
|
-
const page = horizontal ? el.clientWidth : el.clientHeight;
|
|
46
|
-
const step = Math.max(40, page * 0.2);
|
|
47
|
-
const back = horizontal ? "ArrowLeft" : "ArrowUp";
|
|
48
|
-
const forward = horizontal ? "ArrowRight" : "ArrowDown";
|
|
49
|
-
const axis = horizontal ? "scrollLeft" : "scrollTop";
|
|
50
|
-
const max = horizontal ? el.scrollWidth - el.clientWidth : el.scrollHeight - el.clientHeight;
|
|
51
|
-
let next = null;
|
|
52
|
-
if (event.key === back) next = el[axis] - step;
|
|
53
|
-
else if (event.key === forward) next = el[axis] + step;
|
|
54
|
-
else if (event.key === "Home") next = 0;
|
|
55
|
-
else if (event.key === "End") next = max;
|
|
56
|
-
else if (event.key === "PageUp") next = el[axis] - page;
|
|
57
|
-
else if (event.key === "PageDown") next = el[axis] + page;
|
|
58
|
-
if (next === null) return;
|
|
59
|
-
event.preventDefault();
|
|
60
|
-
el[axis] = Math.max(0, Math.min(max, next));
|
|
61
|
-
}
|
|
62
|
-
export {
|
|
63
|
-
scrollRegionKeyDown,
|
|
64
|
-
useWheelToHorizontal
|
|
65
|
-
};
|