@nocoo/basalt 3.1.0 → 3.2.1
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/ai/DESIGN.md +128 -55
- package/ai/INTEGRATION.md +9 -9
- package/ai/USAGE.md +1 -1
- package/ai/registry.json +166 -124
- package/dist/charts/config.d.ts +1 -1
- package/dist/charts/config.js +1 -1
- package/dist/charts/config.js.map +1 -1
- package/dist/charts/frame.js +2 -2
- package/dist/charts/frame.js.map +1 -1
- package/dist/charts/heatmap-calendar.js +4 -4
- package/dist/charts/heatmap-calendar.js.map +1 -1
- package/dist/charts/heatmap-matrix.js +5 -5
- package/dist/charts/heatmap-matrix.js.map +1 -1
- package/dist/charts/sparkline.js +1 -1
- package/dist/charts/sparkline.js.map +1 -1
- package/dist/charts/stat-card.js +1 -1
- package/dist/charts/stat-card.js.map +1 -1
- package/dist/components/alert-dialog.js +4 -4
- package/dist/components/alert-dialog.js.map +1 -1
- package/dist/components/app-header.js +1 -1
- package/dist/components/app-header.js.map +1 -1
- package/dist/components/app-shell.js +1 -1
- package/dist/components/app-shell.js.map +1 -1
- package/dist/components/approval-card.js +5 -6
- package/dist/components/approval-card.js.map +1 -1
- package/dist/components/avatar.js +1 -1
- package/dist/components/avatar.js.map +1 -1
- package/dist/components/chat-bubble.js +1 -1
- package/dist/components/chat-bubble.js.map +1 -1
- package/dist/components/chat-composer.js +1 -1
- package/dist/components/chat-composer.js.map +1 -1
- package/dist/components/chat-header.js +1 -1
- package/dist/components/chat-header.js.map +1 -1
- package/dist/components/chat-inbox.js +1 -1
- package/dist/components/chat-inbox.js.map +1 -1
- package/dist/components/chat-markdown.js +1 -1
- package/dist/components/chat-markdown.js.map +1 -1
- package/dist/components/chat-message.js +2 -2
- package/dist/components/chat-message.js.map +1 -1
- package/dist/components/code.js +5 -4
- package/dist/components/code.js.map +1 -1
- package/dist/components/command-palette.js +2 -2
- package/dist/components/command-palette.js.map +1 -1
- package/dist/components/context-cards.js +6 -6
- package/dist/components/context-cards.js.map +1 -1
- package/dist/components/context-menu.js +1 -1
- package/dist/components/context-menu.js.map +1 -1
- package/dist/components/data-table.js +127 -124
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/dialog.js +2 -2
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/diff-table.js +3 -3
- package/dist/components/diff-table.js.map +1 -1
- package/dist/components/dropdown-menu.js +1 -1
- package/dist/components/dropdown-menu.js.map +1 -1
- package/dist/components/editable-nav-item.js +2 -2
- package/dist/components/editable-nav-item.js.map +1 -1
- package/dist/components/file-dropzone.js +1 -1
- package/dist/components/file-dropzone.js.map +1 -1
- package/dist/components/filter-bar.js +1 -1
- package/dist/components/filter-bar.js.map +1 -1
- package/dist/components/icon-picker.js +3 -3
- package/dist/components/icon-picker.js.map +1 -1
- package/dist/components/inline-editable.js +1 -1
- package/dist/components/inline-editable.js.map +1 -1
- package/dist/components/input-area.js +1 -1
- package/dist/components/input-area.js.map +1 -1
- package/dist/components/input-group.js +2 -2
- package/dist/components/input-group.js.map +1 -1
- package/dist/components/layer-card.d.ts +6 -4
- package/dist/components/layer-card.js +61 -71
- package/dist/components/layer-card.js.map +1 -1
- package/dist/components/link.js +1 -1
- package/dist/components/link.js.map +1 -1
- package/dist/components/loader.js +1 -1
- package/dist/components/loader.js.map +1 -1
- package/dist/components/menu-bar.js +2 -2
- package/dist/components/menu-bar.js.map +1 -1
- package/dist/components/multi-select.js +1 -1
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/overlay.d.ts +3 -6
- package/dist/components/overlay.js +3 -3
- package/dist/components/overlay.js.map +1 -1
- package/dist/components/page-header.d.ts +2 -2
- package/dist/components/page-header.js +7 -7
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/recommendation-card.js +2 -2
- package/dist/components/recommendation-card.js.map +1 -1
- package/dist/components/responsive-master-detail.js +2 -2
- package/dist/components/responsive-master-detail.js.map +1 -1
- package/dist/components/scroll-area.js +1 -1
- package/dist/components/scroll-area.js.map +1 -1
- package/dist/components/section-rule.js +1 -1
- package/dist/components/section-rule.js.map +1 -1
- package/dist/components/segment-control.js +1 -1
- package/dist/components/segment-control.js.map +1 -1
- package/dist/components/select.js +2 -2
- package/dist/components/select.js.map +1 -1
- package/dist/components/sensitive-input.js +1 -1
- package/dist/components/sensitive-input.js.map +1 -1
- package/dist/components/sheet.js +3 -3
- package/dist/components/sheet.js.map +1 -1
- package/dist/components/sidebar.js +3 -3
- package/dist/components/sidebar.js.map +1 -1
- package/dist/components/skeleton-line.js +1 -1
- package/dist/components/skeleton-line.js.map +1 -1
- package/dist/components/stat-strip.js +1 -1
- package/dist/components/stat-strip.js.map +1 -1
- package/dist/components/table.d.ts +2 -0
- package/dist/components/table.js +10 -12
- package/dist/components/table.js.map +1 -1
- package/dist/components/tabs.js +2 -2
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/tag-badge.js +1 -1
- package/dist/components/tag-badge.js.map +1 -1
- package/dist/components/tag-color-picker.js +2 -2
- package/dist/components/tag-color-picker.js.map +1 -1
- package/dist/components/text.js +2 -2
- package/dist/components/text.js.map +1 -1
- package/dist/components/thinking.js +1 -1
- package/dist/components/thinking.js.map +1 -1
- package/dist/components/toast.js +1 -1
- package/dist/components/toast.js.map +1 -1
- package/dist/components/tool-chips.js +2 -2
- package/dist/components/tool-chips.js.map +1 -1
- package/dist/components/toolbar.js +8 -8
- package/dist/components/toolbar.js.map +1 -1
- package/dist/styles/base.css +71 -0
- package/dist/styles/standalone.css +187 -168
- package/dist/styles/tailwind.css +9 -2
- package/dist/styles/tokens.css +86 -40
- package/dist/utils/navigation.d.ts +1 -1
- package/package.json +1 -1
package/ai/DESIGN.md
CHANGED
|
@@ -46,18 +46,30 @@ or content surface. Card and layout boundaries use their own four-step roles:
|
|
|
46
46
|
| Large | `--basalt-space-card-lg` | `--basalt-space-layout-lg` | `1.5rem` | 24px |
|
|
47
47
|
| Extra large | `--basalt-space-card-xl` | `--basalt-space-layout-xl` | `2rem` | 32px |
|
|
48
48
|
|
|
49
|
-
Card padding defaults to medium. LayerCard
|
|
50
|
-
and
|
|
49
|
+
Card padding defaults to medium. LayerCard headers flow into Body by default:
|
|
50
|
+
16px horizontal/top insets, no bottom inset and an 8px internal gap, without a divider.
|
|
51
|
+
`Header divided` uses 16px on all sides and a bottom rule. Disclosure headers
|
|
52
|
+
(`Header asChild`) keep 16px horizontal / 12px vertical insets and show their
|
|
53
|
+
bottom rule only when open. Footer keeps 16px horizontal / 12px vertical insets;
|
|
54
|
+
Body/Well use 16px. `padding="sm|md|lg|xl"` selects unstructured
|
|
51
55
|
card padding; structured cards keep their slot-owned insets. Compact composite
|
|
52
56
|
card panels use the same 16/12px panel aliases. Their internal buttons and rows
|
|
53
57
|
keep control spacing; do not stretch action rows to the card scale.
|
|
54
58
|
|
|
59
|
+
Compact card/panel headers (`CodeBlock` header, `ContextCards` chunk header and
|
|
60
|
+
`LayerCard.Header asChild`) share a 44px single-line reference height: a 20px line
|
|
61
|
+
box plus 12px vertical panel inset on each side. Header action buttons use
|
|
62
|
+
`size="sm"` and `-my-basalt-space-sm` so they never inflate the header bar.
|
|
63
|
+
Wrapping and enlarged text may grow the header; do not impose a fixed height.
|
|
64
|
+
|
|
55
65
|
Layout grids default to medium (16px). ContentIsland owns 16px insets on mobile,
|
|
56
66
|
24px on tablets and 24px vertical / 32px horizontal from 1024px. The catalog shell
|
|
57
|
-
keeps 8px outside the island on mobile and 12px from 768px
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
67
|
+
keeps 8px outside the island on mobile and 12px from 768px; AppHeader uses the
|
|
68
|
+
same 8px / 12px horizontal inset to align with that outer island boundary, not its
|
|
69
|
+
inner content edge. Ordinary application sections use 24px gaps, including catalog
|
|
70
|
+
documentation. SectionRule uses 12px content separation for compact labels and
|
|
71
|
+
16px for reading headings. `Grid gap="sm|md|lg|xl"` and semantic utilities such as
|
|
72
|
+
`gap-basalt-layout-xl` select these tiers.
|
|
61
73
|
There is no universal height for either category.
|
|
62
74
|
|
|
63
75
|
Dialog and AlertDialog panels use 16px outer insets on mobile and 24px from
|
|
@@ -67,24 +79,32 @@ small floating menus have separate inset contracts.
|
|
|
67
79
|
Form rhythm distinguishes a field from a group: label/control/hint spacing stays
|
|
68
80
|
8px, related fields use 16px layout gaps, and separate sections use 24px. A form's
|
|
69
81
|
stack owns those gaps; individual Field components do not add outer margins.
|
|
70
|
-
DialogFooter
|
|
71
|
-
Do not add a matching margin at every caller or
|
|
82
|
+
DialogFooter, AlertDialogFooter and SheetFooter own 16px separation from content
|
|
83
|
+
and keep 8px between actions. Do not add a matching margin at every caller or
|
|
84
|
+
enlarge controls to open a form.
|
|
72
85
|
|
|
73
86
|
Metric cards use the shared `StatCard`, not a hand-built Header/Body split. A single
|
|
74
87
|
16px inset owns the title, value, comparison and supporting chart; 12px separates
|
|
75
88
|
the heading, metric and content groups, and 4px separates value/supporting text.
|
|
76
89
|
Keep the comparison next to the metric in reading order, before the chart. Icons
|
|
77
|
-
are small unboxed heading cues, not a second painted surface.
|
|
78
|
-
|
|
79
|
-
|
|
90
|
+
are small unboxed heading cues, not a second painted surface. `StatCard` titles
|
|
91
|
+
use 14px (`text-basalt-base`); primary metric numerals in `StatCard`, `StatStrip`
|
|
92
|
+
and dashboard KPIs use 24px (`text-basalt-3xl`), tabular alignment and natural
|
|
93
|
+
wrapping. Compact trend plots use 4rem geometry, not `flex-1` to fill the card;
|
|
94
|
+
analytical charts with axes remain separate surfaces.
|
|
80
95
|
Show the time window and disclose a nonzero line-chart scale. Bar charts keep
|
|
81
96
|
their zero baseline. Metric cards have no internal divider or decorative border.
|
|
82
97
|
|
|
98
|
+
Action horizontal insets use `--basalt-space-control-x-sm` (10px),
|
|
99
|
+
`--basalt-space-control-x` (12px) and `--basalt-space-control-x-lg` (16px).
|
|
100
|
+
Vertical padding and icon gaps stay compact; Select uses the shared control gap.
|
|
101
|
+
TagBadge uses 6px horizontal padding at `sm` and 8px at `md`.
|
|
83
102
|
All nonzero padding, margin and gaps use the appropriate category scale or aliases.
|
|
84
103
|
Zero, auto margins and hairline seams are structural exceptions, not new density
|
|
85
104
|
levels. Negative margins may cancel an owned boundary, not invent a new gap.
|
|
86
|
-
|
|
87
|
-
|
|
105
|
+
Container spacing uses 4px multiples (4/8/12/16/24/32px); 2px and 6px
|
|
106
|
+
control-internal spacing remains unchanged. Use `p-basalt-card`, `gap-basalt-layout`,
|
|
107
|
+
`gap-basalt-space-sm`, etc. Default nav insets and field gaps remain 8px. Selectable rows use 8px horizontal / 6px vertical
|
|
88
108
|
insets and an 8px icon gap. Sidebar destinations alone use 8px vertical padding;
|
|
89
109
|
menus, editable navigation and chat rows retain their compact role. One component
|
|
90
110
|
owns each boundary: nested sections must not accidentally double the same inset.
|
|
@@ -140,8 +160,10 @@ The shared classes calculate natural size as follows:
|
|
|
140
160
|
Descriptions, wrapping and actions can make a banner taller.
|
|
141
161
|
- Action rows: 22px text line (`--basalt-line-row`) + 6px vertical padding each
|
|
142
162
|
side = 34px. Body prose/code retain the 20px line box. Compound inputs own one
|
|
143
|
-
outer border; inset children do not add another. Segmented tracks keep
|
|
144
|
-
on a 20px line box: 30px items + 2px track inset per side = 34px.
|
|
163
|
+
outer border; inset children do not add another. Segmented tracks keep 14px text
|
|
164
|
+
on a 20px line box: 30px items + 2px track inset per side = 34px. A horizontally
|
|
165
|
+
scrolling SegmentControl viewport adds 4px clearance on all four edges and uses
|
|
166
|
+
matching scroll-padding; this does not enlarge the ToggleGroup track.
|
|
145
167
|
- Sidebar destination and disclosure rows use the same 22px line box with 8px
|
|
146
168
|
vertical padding, yielding 38px reference rows without changing shared controls.
|
|
147
169
|
- Cards, dialogs and layout containers have no mandatory height. Textareas and
|
|
@@ -165,12 +187,26 @@ interaction contracts; do not change their containment as a global workaround.
|
|
|
165
187
|
- Radius choices: `--basalt-radius-sm` (.25rem), `-md` (.5rem), `-lg` (.75rem)
|
|
166
188
|
and `-full` (pill/circle); `none` and `inherit` are structural choices. Widget,
|
|
167
189
|
card and island aliases reference those choices; no per-component radii.
|
|
168
|
-
- Typography
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
190
|
+
- Typography is positional, not component-specific. Use only the four font-size
|
|
191
|
+
tokens below, with `--basalt-leading-*` for line boxes. Do not shrink text to
|
|
192
|
+
fit a fixed box or introduce responsive intermediate sizes.
|
|
193
|
+
|
|
194
|
+
| Tier | Reference | Token / utility | Roles |
|
|
195
|
+
| --- | --- | --- | --- |
|
|
196
|
+
| Auxiliary | 12px / `.75rem` | `--basalt-text-sm` / `text-basalt-sm` | Badges, table column headers, field hints/errors, sidebar uppercase group/partition labels, secondary metadata, chart axes/legends/tooltips, inline code and code block source (`font-mono`) |
|
|
197
|
+
| Body | 14px / `.875rem` | `--basalt-text-base` / `text-basalt-base` | Body prose, all interactive controls and option rows (including ApprovalCard, RecommendationCard, Table cells and ContextCards), card/panel titles (LayerCard.Header, CodeBlock title, ContextCards header, StatCard title, Popover title and Empty title), PageHeader descriptions and modal/sheet descriptions (DialogDescription, AlertDialogDescription and SheetDescription) |
|
|
198
|
+
| Section | 18px / `1.125rem` | `--basalt-text-xl` / `text-basalt-xl` | Section/category h2/h3 headings, SectionRule variant="heading" h2, modal/drawer titles (DialogTitle, AlertDialogTitle and SheetTitle) |
|
|
199
|
+
| Page / metric | 24px / `1.5rem` | `--basalt-text-3xl` / `text-basalt-3xl` | Page main title (PageHeader h1) and primary KPI numerals (StatCard value, StatStrip value and dashboard metrics) |
|
|
200
|
+
|
|
201
|
+
The only independent display-scale exemptions are LandingPage
|
|
202
|
+
(`src/styles/landing.css`), LoginPage (`src/pages/LoginPage.tsx`) and the 404
|
|
203
|
+
display in NotFound (`src/pages/NotFound.tsx`, `text-basalt-10xl` only). Every
|
|
204
|
+
other `src/` font-size class must use one of the four canonical utilities.
|
|
205
|
+
- Surfaces preserve the matte L0/L1/L2/L3 hierarchy. LayerCard adds a subtle
|
|
206
|
+
`ring-1 ring-basalt-border/50` perimeter; `outlined` strengthens it. Headers
|
|
207
|
+
use 14px medium-weight foreground text with tight tracking. Controls contrast
|
|
208
|
+
with their parent: document/surface roots use `--basalt-secondary`, while cards
|
|
209
|
+
and deeper surfaces use `--basalt-bright` for their control fill. Hover uses `--basalt-hover`,
|
|
174
210
|
`--basalt-primary-hover` or `--basalt-destructive-hover`, not caller opacity.
|
|
175
211
|
- Semantic states, tags, data series and brand imagery may choose semantic
|
|
176
212
|
palettes; keep foreground/background pairs and verify both themes. Centralize
|
|
@@ -184,12 +220,13 @@ interaction contracts; do not change their containment as a global workaround.
|
|
|
184
220
|
lightness in dark mode), never the darker decorative `accent` or `muted` fill.
|
|
185
221
|
Do not add decorative side bars, selection outlines, shadows or pseudo-element
|
|
186
222
|
frames. Navigation uses foreground contrast and medium weight alongside fill;
|
|
187
|
-
existing semantic checkmarks and tab underlines remain.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
223
|
+
existing semantic checkmarks and tab underlines remain. Underline tabs use
|
|
224
|
+
active foreground text and the bottom indicator only, without a rounded box
|
|
225
|
+
or selected background. Both primary and secondary text retain at least 4.5:1 contrast.
|
|
226
|
+
- Hover is transient and follows the configured primary. `--basalt-hover` is
|
|
227
|
+
a complete CSS color, mixed against `--basalt-surface-elevated` at 18% primary
|
|
228
|
+
in both light and dark modes. Moving menu and command highlights use
|
|
229
|
+
this uniform matte fill, without gradients or decorative borders.
|
|
193
230
|
SegmentControl and ToggleGroup selected items use `--basalt-primary` and its
|
|
194
231
|
contrast-corrected foreground; they are accent controls, not neutral navigation.
|
|
195
232
|
Neutral row selection retains its independent selected tokens.
|
|
@@ -203,20 +240,30 @@ interaction contracts; do not change their containment as a global workaround.
|
|
|
203
240
|
expose that state instead of switching to a gray secondary variant alone.
|
|
204
241
|
Checkbox/radio/switch glyphs, primary/destructive actions and semantic diff
|
|
205
242
|
colors keep their semantic fills. Color swatches retain their actual palette.
|
|
206
|
-
- Keyboard focus is separate from selection.
|
|
207
|
-
|
|
243
|
+
- Keyboard focus is separate from selection. Ordinary focus uses a 1px theme
|
|
244
|
+
`--basalt-ring` stroke with a 2px outer offset; flush structural targets use the
|
|
245
|
+
same stroke inset with a 2px negative offset (`basalt-focus-inset`). External
|
|
246
|
+
focus targets need 4px clearance inside their nearest clipping container;
|
|
247
|
+
existing padding of at least 4px counts and is not stacked. Forced-colors mode
|
|
248
|
+
may use a 2px system outline. Focus causes no layout shift, and error indicators
|
|
249
|
+
remain independent. Navigation uses inset focus so overflow and collapsed groups
|
|
250
|
+
cannot clip it. Disabled controls retain
|
|
208
251
|
subdued opacity and cannot become moving-hover targets; selection never lowers
|
|
209
252
|
opacity or mutes its primary label.
|
|
210
|
-
- SidebarPartition is a major section label (12px
|
|
211
|
-
spacing). SidebarGroup is a compact disclosure label
|
|
212
|
-
22px line box, 8px inset, 12px
|
|
213
|
-
hover-highlight target. Ordinary sidebar
|
|
214
|
-
|
|
215
|
-
rails omit labels. Icons stay centered on the 68px collapsed rail, and the brand
|
|
253
|
+
- SidebarPartition is a major section label (12px / `text-basalt-sm`, semibold,
|
|
254
|
+
uppercase, 16px top spacing). SidebarGroup is a compact disclosure label
|
|
255
|
+
(12px / `text-basalt-sm`, semibold, uppercase, 22px line box, 8px inset, 12px
|
|
256
|
+
group separation), not a destination or hover-highlight target. Ordinary sidebar
|
|
257
|
+
destinations use 14px (`text-basalt-base`) text and 8px row insets. Groups preserve
|
|
258
|
+
keyboard expansion and chevron motion; collapsed rails omit labels. Icons stay centered on the 68px collapsed rail, and the brand
|
|
216
259
|
mark keeps the same center when expanded. Do not trade that axis for a global
|
|
217
260
|
left-edge alignment.
|
|
218
261
|
- Content wells use the actual surface hierarchy, not selected tokens or muted
|
|
219
262
|
fills. Skeletons, progress tracks and decorative code marks may remain subdued.
|
|
263
|
+
Skeleton shimmer uses foreground at 10% opacity so it remains visible in both themes.
|
|
264
|
+
- The first eight numbered chart tokens resolve to distinct colors in both themes;
|
|
265
|
+
supplementary series use matte HSL values independently of the control accent.
|
|
266
|
+
Sparkline bars use uniform full opacity, never positional dimming.
|
|
220
267
|
|
|
221
268
|
## Motion and performance
|
|
222
269
|
|
|
@@ -259,19 +306,20 @@ catalog states and source viewers. Do not add a second `main`, viewport height,
|
|
|
259
306
|
page background, wrapper card or page padding inside the island. A bounded chat
|
|
260
307
|
workspace can use `h-full min-h-0`; it must not create a nested viewport.
|
|
261
308
|
|
|
262
|
-
Every catalog route uses the same ShowcasePage header:
|
|
263
|
-
|
|
264
|
-
reading width. Page sections use 24px
|
|
265
|
-
|
|
266
|
-
pages do not override the shared scale.
|
|
267
|
-
for the library index, category guides,
|
|
309
|
+
Every catalog route uses the same ShowcasePage header: 24px main titles
|
|
310
|
+
(`text-basalt-3xl`), 14px descriptions (`text-basalt-base`) on a 20px line box,
|
|
311
|
+
8px title separation and a 65ch maximum reading width. Page sections use 24px
|
|
312
|
+
separation regardless of route category. PageHeader size choices must preserve
|
|
313
|
+
the same positional font sizes; catalog pages do not override the shared scale.
|
|
314
|
+
ShowcasePage marks `variant="document"` for the library index, category guides,
|
|
315
|
+
component documentation and source viewers.
|
|
268
316
|
The shell owns the complete breadcrumb trail from Dashboard through the library,
|
|
269
317
|
category and component to the current route. Ancestors are links; the current
|
|
270
318
|
route appears once as nonlinked text with aria-current. Source views include their
|
|
271
319
|
component parent. Narrow headers keep every segment reachable by scrolling the
|
|
272
320
|
breadcrumb region without overflowing the page.
|
|
273
|
-
Document sections use `SectionRule variant="heading"`:
|
|
274
|
-
headings without the compact dashed rule. Component previews retain their own
|
|
321
|
+
Document sections use `SectionRule variant="heading"`: 18px (`text-basalt-xl`)
|
|
322
|
+
sentence-case headings without the compact dashed rule. Component previews retain their own
|
|
275
323
|
scope; document typography must not cascade into copied controls. Headers have
|
|
276
324
|
natural height, no scenic wrappers, negative insets or fixed empty openings.
|
|
277
325
|
|
|
@@ -286,8 +334,10 @@ category uses LayerCard.Header above its grid, not individual cards per componen
|
|
|
286
334
|
Its light surface is white-toned; dark mode uses the same surface hierarchy rather
|
|
287
335
|
than a fixed white fill.
|
|
288
336
|
|
|
289
|
-
Cards with
|
|
290
|
-
related content with a shared internal gap,
|
|
337
|
+
Cards with distinct heading/body regions use `LayerCard.Header` and
|
|
338
|
+
`LayerCard.Body`; use one Body for related content with a shared internal gap,
|
|
339
|
+
not a padded Body for every line. Short overview prose blocks may keep their
|
|
340
|
+
heading and text in one unstructured card inset without Header/Body slots.
|
|
291
341
|
Structured roots and slots must not receive extra outer padding or margins.
|
|
292
342
|
Unstructured cards select `padding` rather than overriding it with utilities.
|
|
293
343
|
Do not paint a fixed surface onto LayerCard or recreate cards with rounded,
|
|
@@ -295,6 +345,21 @@ painted divs. Use library controls and tables instead of rebuilding their spacin
|
|
|
295
345
|
focus, selection and motion in page CSS. Semantic color overrides and purposeful
|
|
296
346
|
chart/canvas geometry remain separate from shared control geometry.
|
|
297
347
|
|
|
348
|
+
### Island hierarchy
|
|
349
|
+
|
|
350
|
+
The shell is L0 (`--basalt-background`). `ContentIsland` is the L1 gray canvas
|
|
351
|
+
(`--basalt-card`); its first `LayerCard` islands are L2 (`--basalt-secondary`),
|
|
352
|
+
white-toned in light mode and elevated in both themes.
|
|
353
|
+
|
|
354
|
+
Inside `ShowcasePage` / `ContentIsland`, only structural chrome sits directly on
|
|
355
|
+
L1: `PageHeader`, `SectionRule` headings, and top-level navigation tabs or filter
|
|
356
|
+
bars that are not attached to a single card. All substantive content blocks MUST
|
|
357
|
+
be encapsulated inside L2 `LayerCard` islands: rationales, guidelines, lists,
|
|
358
|
+
forms, interactive demos, tables, and empty or loading states. A region heading
|
|
359
|
+
does not make its content a surface. Revealed filter forms belong in a `LayerCard`,
|
|
360
|
+
not directly on the L1 canvas. Keep page and region headings outside the content
|
|
361
|
+
islands rather than wrapping the whole page in another card.
|
|
362
|
+
|
|
298
363
|
### Alignment hierarchy
|
|
299
364
|
|
|
300
365
|
Alignment is local to a meaningful scope, not a requirement that every text node
|
|
@@ -309,20 +374,25 @@ start at the page edge. Establish the outer rail before composing the inner one:
|
|
|
309
374
|
|
|
310
375
|
Related text keeps its rail across sorting, selection and missing optional icons.
|
|
311
376
|
Numeric headings and values share the end rail; a sort glyph sits inward of that
|
|
312
|
-
label rather than pushing it away from the values. Reserve the same glyph slot
|
|
377
|
+
label with a 4px gap rather than pushing it away from the values. Reserve the same glyph slot
|
|
313
378
|
for Keep, Add and Remove instead of indenting only changed rows. Ordinary button
|
|
314
379
|
padding is not a table-header inset. Preserve the focus target through a shared
|
|
315
380
|
header control rather than compensating with negative page margins.
|
|
316
381
|
|
|
317
|
-
Table cells keep
|
|
382
|
+
Table cells keep 12px horizontal / 8px vertical insets and 40px reference rows.
|
|
383
|
+
Headers use medium weight and 0.04em tracking. Body rows have a subtle bottom
|
|
384
|
+
hairline except the last row; the native separate-border layout paints that
|
|
385
|
+
hairline on cells as well. Striping is off by default; `Table striped` opts into
|
|
386
|
+
alternating current-surface row fills, independently of hover and selection.
|
|
318
387
|
An edge attached to a panel uses `--basalt-space-table-edge` (the panel's 16px
|
|
319
|
-
horizontal inset), independently of the space between columns.
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
388
|
+
horizontal inset), independently of the space between columns. DataTable owns
|
|
389
|
+
this through `edge="attached"`; native Table compositions can use
|
|
390
|
+
`ps-basalt-table-edge` and `pe-basalt-table-edge` on the corresponding edge cells.
|
|
391
|
+
A full-width cell uses both. Simple tables without rowSpan or nested tables may
|
|
392
|
+
instead opt into automatic first/last-cell alignment through a wrapper marked
|
|
393
|
+
`data-basalt-table-container` and `data-edge="attached"`. The column owner must
|
|
394
|
+
mark actual edge cells explicitly for rowSpan or nested tables. Row fills and
|
|
395
|
+
header rules remain full width. An already inset table retains the default cell spacing.
|
|
326
396
|
TableCaption owns its 16px horizontal and 12px vertical panel insets, without an
|
|
327
397
|
outside margin. Its text must not touch an enclosing table frame's bottom edge.
|
|
328
398
|
|
|
@@ -379,7 +449,10 @@ to recreate ordinary actions, selects or inputs.
|
|
|
379
449
|
`bun run design:check` scans library components/helpers and catalog examples,
|
|
380
450
|
including CSS, for raw spacing/type/radius/motion values, fixed action overrides
|
|
381
451
|
and inline design repairs. The landing route's own CSS is exempt from the spacing,
|
|
382
|
-
radius and type rules and still keeps motion tokens.
|
|
452
|
+
radius and type rules and still keeps motion tokens. Noncanonical Basalt font-size
|
|
453
|
+
classes are rejected, including responsive and important variants; only NotFound's
|
|
454
|
+
`text-basalt-10xl` and LoginPage's independent scale are exempt from the source
|
|
455
|
+
font-size check. It derives dashboard page requirements from App routes
|
|
383
456
|
and checks template ownership, duplicate slot spacing, recreated card surfaces,
|
|
384
457
|
ordinary native controls in pages and page-level control padding overrides.
|
|
385
458
|
It rejects compact control padding on content panels, raw application disclosures,
|
package/ai/INTEGRATION.md
CHANGED
|
@@ -45,7 +45,7 @@ AppShell ← dashboard and catalog routes
|
|
|
45
45
|
├── Sidebar ← product title + version + nav
|
|
46
46
|
└── AppMain ← id="main-content"
|
|
47
47
|
├── AppHeader ← crumbs + current page | top-right
|
|
48
|
-
└── island wrap ← px-basalt-space-lg pb-basalt-space-lg md:px-basalt-
|
|
48
|
+
└── island wrap ← px-basalt-space-lg pb-basalt-space-lg md:px-basalt-layout-sm md:pb-basalt-layout-sm
|
|
49
49
|
└── ContentIsland
|
|
50
50
|
├── PageHeader ← title + subtitle | create / short filters
|
|
51
51
|
│ ← optional own-row complex filters
|
|
@@ -390,7 +390,7 @@ Bounded shells use border-box `height/max-height: 100dvh`. Document shells use `
|
|
|
390
390
|
<AppSkipLink>Skip to content</AppSkipLink>
|
|
391
391
|
<AppMain>
|
|
392
392
|
<AppHeader title="Field notes" actions={actions} />
|
|
393
|
-
<div className="flex min-h-0 min-w-0 flex-1 flex-col md:px-basalt-
|
|
393
|
+
<div className="flex min-h-0 min-w-0 flex-1 flex-col md:px-basalt-layout-sm md:pb-basalt-layout-sm">
|
|
394
394
|
<ContentIsland mobileSurface="edge-to-edge">
|
|
395
395
|
<div className="mx-auto max-w-prose px-basalt-space-lg py-basalt-space-lg md:p-0">{content}</div>
|
|
396
396
|
</ContentIsland>
|
|
@@ -428,11 +428,11 @@ Do not wrap those regions in another full-viewport column. Do not set `h-screen`
|
|
|
428
428
|
|
|
429
429
|
### Shared navigation geometry
|
|
430
430
|
|
|
431
|
-
`SidebarNav` and `NavigationMenuList` own one `--basalt-space-nav-inset` (8px) boundary and `--basalt-space-nav-gap` (
|
|
431
|
+
`SidebarNav` and `NavigationMenuList` own one `--basalt-space-nav-inset` (8px) boundary and `--basalt-space-nav-gap` (4px) between rows. Sidebar groups do not add another horizontal inset. Sidebar destinations and search use 8px horizontal/vertical padding, an 8px icon gap and a 22px line box for a 38px reference row. This is local to Sidebar: editable/folder rows, horizontal navigation links and menus retain 6px vertical padding and 34px rows. Header and search wrapper use the navigation inset. SidebarFooter instead owns 16px horizontal and bottom padding plus 8px top padding; keep the same 68px rail centering and expanded layout without duplicating that inset. Do not add caller-owned padding to compensate for missing package geometry.
|
|
432
432
|
|
|
433
433
|
Use `SidebarNav` for vertical lists, including standalone lists of `EditableNavItem` / `FolderNavItem`; `NavigationMenuList` owns horizontal/vertical Radix navigation. Both compose the existing list-local hover adapter. One background moves with transform between enabled rows. Sidebar hover appears at the actual pointer row and disappears there on leave or over a gap/disclosure label; it never launches from or returns to the active route or stale pointer focus. Only continuous row-to-row hover animates. Keyboard focus remains independent. NavigationMenuList retains its focus/selection-following behavior. Nested lists own separate highlights. Hidden, disabled and actively renamed rows are excluded. Geometry reads are batched per animation frame, same-row pointer motion causes no updates, and reduced motion disables transitions. Navigation state, routes and rename operations remain application-owned; the adapter is View-only.
|
|
434
434
|
|
|
435
|
-
`SidebarHeader`
|
|
435
|
+
`SidebarHeader` pads horizontally by the navigation inset; `SidebarFooter` owns its larger footer boundary. Brand, version pill, and collapse control go directly in the header. The version string is read from the app `package.json` at build time. Never hardcode it. `SidebarPartition` aligns with row text. `SidebarGroup` adds only section spacing, never a second item gutter.
|
|
436
436
|
|
|
437
437
|
```tsx excerpt:sidebar-expanded-structure
|
|
438
438
|
<Sidebar collapsed={collapsed}>
|
|
@@ -662,7 +662,7 @@ export function AppFrame() {
|
|
|
662
662
|
title={title}
|
|
663
663
|
actions={<ThemeToggle aria-label={`Toggle theme (now ${theme})`} />}
|
|
664
664
|
/>
|
|
665
|
-
<div className="flex min-h-0 flex-1 flex-col px-basalt-space-lg pb-basalt-space-lg md:px-basalt-
|
|
665
|
+
<div className="flex min-h-0 flex-1 flex-col px-basalt-space-lg pb-basalt-space-lg md:px-basalt-layout-sm md:pb-basalt-layout-sm">
|
|
666
666
|
<ContentIsland>
|
|
667
667
|
<Outlet />
|
|
668
668
|
</ContentIsland>
|
|
@@ -675,7 +675,7 @@ export function AppFrame() {
|
|
|
675
675
|
|
|
676
676
|
<a id="appheader-and-breadcrumbs"></a>
|
|
677
677
|
|
|
678
|
-
`AppHeader` defaults to `h-14`, matching `SidebarHeader`; `density="compact"` uses a 52px row with 44px minimum targets. `sticky` keeps it visible within the current scroll owner; see §6 for safe-area positioning.
|
|
678
|
+
`AppHeader` defaults to `h-14`, matching `SidebarHeader`; `density="compact"` uses a 52px row with 44px minimum targets. Its horizontal inset is 8px on mobile and 12px from 768px, aligning with the outer ContentIsland wrapper rather than the island's inner card edge. `sticky` keeps it visible within the current scroll owner; see §6 for safe-area positioning.
|
|
679
679
|
|
|
680
680
|
### AppHeader API & Contracts
|
|
681
681
|
|
|
@@ -759,7 +759,7 @@ The catalog's app-local `RouteScrollReset` wraps each leaf page inside its Suspe
|
|
|
759
759
|
|
|
760
760
|
The `/forms`, `/settings`, `/data`, and `/chat` examples demonstrate local state and simulated requests, including failure/retry and cancellation. Their viewmodels own data and timers; Views own native FormData, focus, and responsive layout. Replace the local service adapter when integrating a backend. Theme selection uses the shared provider; local profile, uploads, and chat changes do not update a real account.
|
|
761
761
|
|
|
762
|
-
`PageHeader` is flush on `ContentIsland`. The island owns 16px mobile insets, 24px tablet insets, and 32px horizontal / 24px vertical desktop insets. Do not wrap the header in another card or add page padding. `PageHeader.size` is `"md" | "lg" | "xl"` (default `"md"`); larger headings use 16/24px descriptions, all title/description pairs use an 8px gap. `SectionRule variant="heading"` gives reading sections a 20px sentence-case title without the compact dashed rule. Controls and card slots keep their compact geometry.
|
|
762
|
+
`PageHeader` is flush on `ContentIsland`. The island owns 16px mobile insets, 24px tablet insets, and 32px horizontal / 24px vertical desktop insets. `AppHeader` remains aligned to the outer island boundary (8px mobile, 12px from 768px), not this inner content edge. Do not wrap the header in another card or add page padding. `PageHeader.size` is `"md" | "lg" | "xl"` (default `"md"`); larger headings use 16/24px descriptions, all title/description pairs use an 8px gap. `SectionRule variant="heading"` gives reading sections a 20px sentence-case title without the compact dashed rule. Controls and card slots keep their compact geometry.
|
|
763
763
|
|
|
764
764
|
### Create and filters
|
|
765
765
|
|
|
@@ -930,7 +930,7 @@ Input, Select, secondary / outline Button use `bg-basalt-control` (`--basalt-con
|
|
|
930
930
|
|
|
931
931
|
`Table` sets `data-basalt-table`. Zebra, hover, and selected paint on `td`, from `--basalt-zebra-fill`, `--basalt-hover` and `--basalt-selected`. Selection adds no decorative side bar or frame; semantic add/remove diff tints are preserved.
|
|
932
932
|
|
|
933
|
-
Neutral selected states use the brighter `--basalt-selected` surface, readable `--basalt-selected-foreground` and navigation font weight, without decorative side bars or selected borders. Never use `accent` or `muted` to signal selection. Existing semantic checkmarks and tab underlines remain; do not add a decorative frame at the white ceiling. A moving hover layer must not erase the selected row. Sidebar, navigation menus, editable navigation and ChatInbox share this behavior and inset keyboard focus; neutral Button variants also honor `aria-pressed` and `aria-current`. Segments and tabs retain their existing measured indicator motion. Primary/destructive actions, check/radio/switch glyphs and semantic diffs keep their semantic colors. See [DESIGN.md](DESIGN.md#selection-and-navigation-hierarchy).
|
|
933
|
+
Neutral selected states use the brighter `--basalt-selected` surface, readable `--basalt-selected-foreground` and navigation font weight, without decorative side bars or selected borders. Never use `accent` or `muted` to signal selection. Existing semantic checkmarks and tab underlines remain; do not add a decorative frame at the white ceiling. A moving hover layer must not erase the selected row. Sidebar, navigation menus, editable navigation and ChatInbox share this behavior and inset keyboard focus; neutral Button variants also honor `aria-pressed` and `aria-current`. Focus is separate from selection: ordinary targets use the 1px theme `--basalt-ring` stroke with a 2px outer offset; flush targets use the same stroke inset with a 2px negative offset. External focus targets need at least 4px clearance inside their nearest clipping container; existing 4px padding counts and is not stacked. Focus does not shift layout, error indicators stay independent, and forced-colors mode may use a 2px system outline. Segments and tabs retain their existing measured indicator motion. Primary/destructive actions, check/radio/switch glyphs and semantic diffs keep their semantic colors. See [DESIGN.md](DESIGN.md#selection-and-navigation-hierarchy).
|
|
934
934
|
|
|
935
935
|
`DescriptionList` is layout and type only. It is not a surface.
|
|
936
936
|
|
|
@@ -1925,7 +1925,7 @@ Thinking and ToolChips share row padding; disclosures rotate only their own chev
|
|
|
1925
1925
|
|
|
1926
1926
|
The standalone build generates every Tailwind utility once in canonical order. Do not append handwritten copies of `.p-0`, `.bg-transparent` or other native utilities after generated axis/state rules: a later shorthand can silently erase semantic padding. Browser acceptance measures actual computed insets in both CSS entrypoints, under foreign host spacing and semantic overrides.
|
|
1927
1927
|
|
|
1928
|
-
Public Radio, Checkbox, Switch and SegmentControl group roots establish the scoped `.basalt-ui` reset. Fieldsets and legends have no browser-default padding/margin inside that boundary; standalone and Tailwind consumers must have identical group insets. Host form groups outside Basalt remain untouched.
|
|
1928
|
+
Public Radio, Checkbox, Switch and SegmentControl group roots establish the scoped `.basalt-ui` reset. Fieldsets and legends have no browser-default padding/margin inside that boundary; standalone and Tailwind consumers must have identical group insets. SegmentControl's horizontal scrolling viewport has 4px focus clearance on every edge and matching scroll-padding so keyboard navigation can reveal end items; the ToggleGroup track retains its 2px compact inset and 34px item geometry. Host form groups outside Basalt remain untouched.
|
|
1929
1929
|
|
|
1930
1930
|
Native form legends do not participate in a fieldset's flex gap. Radio, Checkbox and Switch legends therefore own `margin-bottom: var(--basalt-space-field-gap)` (8px) independently of the group's row layout. Do not replace the semantic legend or add wrapper divs to simulate this spacing. Override the existing field-gap token when a different group density is required.
|
|
1931
1931
|
|
package/ai/USAGE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Basalt AI & Machine Usage Guide
|
|
2
2
|
|
|
3
|
-
This document describes how AI code assistants, automated agents, and developers can consume `@nocoo/basalt` (v3.1
|
|
3
|
+
This document describes how AI code assistants, automated agents, and developers can consume `@nocoo/basalt` (v3.2.1).
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|