@moldable-ai/ui 0.2.20 → 0.2.21
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/dist/catalog/catalog-coverage.d.ts +15 -0
- package/dist/catalog/catalog-coverage.d.ts.map +1 -0
- package/dist/catalog/catalog-coverage.js +44 -0
- package/dist/catalog/catalog-manifest.d.ts.map +1 -1
- package/dist/catalog/catalog-manifest.js +35 -23
- package/dist/catalog/catalog-types.d.ts +10 -0
- package/dist/catalog/catalog-types.d.ts.map +1 -1
- package/dist/catalog/catalog-types.js +6 -0
- package/dist/catalog/component-catalog.d.ts.map +1 -1
- package/dist/catalog/component-catalog.js +16 -6
- package/dist/catalog/core-catalog-exclusions.d.ts +8 -0
- package/dist/catalog/core-catalog-exclusions.d.ts.map +1 -0
- package/dist/catalog/core-catalog-exclusions.js +151 -0
- package/dist/catalog/core-catalog.d.ts +0 -4
- package/dist/catalog/core-catalog.d.ts.map +1 -1
- package/dist/catalog/core-catalog.js +12 -98
- package/dist/catalog/core-collection-stories.d.ts +3 -0
- package/dist/catalog/core-collection-stories.d.ts.map +1 -0
- package/dist/catalog/core-collection-stories.js +42 -0
- package/dist/catalog/core-control-stories.d.ts +3 -0
- package/dist/catalog/core-control-stories.d.ts.map +1 -0
- package/dist/catalog/core-control-stories.js +94 -0
- package/dist/catalog/core-feedback-stories.d.ts +3 -0
- package/dist/catalog/core-feedback-stories.d.ts.map +1 -0
- package/dist/catalog/core-feedback-stories.js +50 -0
- package/dist/catalog/core-foundation-stories.d.ts +3 -0
- package/dist/catalog/core-foundation-stories.d.ts.map +1 -0
- package/dist/catalog/core-foundation-stories.js +53 -0
- package/dist/catalog/core-navigation-stories.d.ts +3 -0
- package/dist/catalog/core-navigation-stories.d.ts.map +1 -0
- package/dist/catalog/core-navigation-stories.js +25 -0
- package/dist/catalog/core-overlay-stories.d.ts +3 -0
- package/dist/catalog/core-overlay-stories.d.ts.map +1 -0
- package/dist/catalog/core-overlay-stories.js +20 -0
- package/dist/catalog/index.d.ts +3 -1
- package/dist/catalog/index.d.ts.map +1 -1
- package/dist/catalog/index.js +3 -1
- package/dist/components/chat/chat-panel.d.ts +0 -1
- package/dist/components/chat/chat-panel.d.ts.map +1 -1
- package/dist/components/chat/chat-panel.js +7 -11
- package/dist/components/ui/alert-dialog.d.ts +7 -3
- package/dist/components/ui/alert-dialog.d.ts.map +1 -1
- package/dist/components/ui/alert-dialog.js +9 -5
- package/dist/components/ui/alert.d.ts +19 -3
- package/dist/components/ui/alert.d.ts.map +1 -1
- package/dist/components/ui/alert.js +25 -8
- package/dist/components/ui/app-frame.d.ts +9 -3
- package/dist/components/ui/app-frame.d.ts.map +1 -1
- package/dist/components/ui/app-frame.js +45 -6
- package/dist/components/ui/collapsible.d.ts +9 -1
- package/dist/components/ui/collapsible.d.ts.map +1 -1
- package/dist/components/ui/collapsible.js +13 -2
- package/dist/components/ui/collection-navigation.d.ts +8 -0
- package/dist/components/ui/collection-navigation.d.ts.map +1 -0
- package/dist/components/ui/collection-navigation.js +19 -0
- package/dist/components/ui/command.d.ts +5 -1
- package/dist/components/ui/command.d.ts.map +1 -1
- package/dist/components/ui/command.js +13 -1
- package/dist/components/ui/confirm-dialog.d.ts +19 -0
- package/dist/components/ui/confirm-dialog.d.ts.map +1 -0
- package/dist/components/ui/confirm-dialog.js +45 -0
- package/dist/components/ui/date-picker.d.ts +24 -0
- package/dist/components/ui/date-picker.d.ts.map +1 -0
- package/dist/components/ui/date-picker.js +92 -0
- package/dist/components/ui/dialog.d.ts +4 -2
- package/dist/components/ui/dialog.d.ts.map +1 -1
- package/dist/components/ui/dialog.js +8 -5
- package/dist/components/ui/empty.d.ts +7 -2
- package/dist/components/ui/empty.d.ts.map +1 -1
- package/dist/components/ui/empty.js +20 -7
- package/dist/components/ui/grid.d.ts.map +1 -1
- package/dist/components/ui/grid.js +70 -46
- package/dist/components/ui/index.d.ts +4 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +4 -0
- package/dist/components/ui/list.d.ts +5 -1
- package/dist/components/ui/list.d.ts.map +1 -1
- package/dist/components/ui/list.js +27 -16
- package/dist/components/ui/material.d.ts +34 -0
- package/dist/components/ui/material.d.ts.map +1 -0
- package/dist/components/ui/material.js +34 -0
- package/dist/components/ui/message-scroller-controller.d.ts +162 -0
- package/dist/components/ui/message-scroller-controller.d.ts.map +1 -0
- package/dist/components/ui/message-scroller-controller.js +888 -0
- package/dist/components/ui/message-scroller-policy.d.ts +74 -0
- package/dist/components/ui/message-scroller-policy.d.ts.map +1 -0
- package/dist/components/ui/message-scroller-policy.js +129 -0
- package/dist/components/ui/message-scroller-primitive.d.ts +55 -0
- package/dist/components/ui/message-scroller-primitive.d.ts.map +1 -0
- package/dist/components/ui/message-scroller-primitive.js +226 -0
- package/dist/components/ui/message-scroller.d.ts +2 -2
- package/dist/components/ui/message-scroller.d.ts.map +1 -1
- package/dist/components/ui/message-scroller.js +3 -15
- package/dist/components/ui/navigation-button-group.d.ts +16 -0
- package/dist/components/ui/navigation-button-group.d.ts.map +1 -0
- package/dist/components/ui/navigation-button-group.js +9 -0
- package/dist/components/ui/popover.d.ts +9 -2
- package/dist/components/ui/popover.d.ts.map +1 -1
- package/dist/components/ui/popover.js +13 -3
- package/dist/components/ui/scroll-area.d.ts +8 -2
- package/dist/components/ui/scroll-area.d.ts.map +1 -1
- package/dist/components/ui/scroll-area.js +6 -3
- package/dist/components/ui/search-field.d.ts.map +1 -1
- package/dist/components/ui/segmented-control.d.ts.map +1 -1
- package/dist/components/ui/segmented-control.js +6 -5
- package/dist/components/ui/sheet.d.ts +4 -2
- package/dist/components/ui/sheet.d.ts.map +1 -1
- package/dist/components/ui/sheet.js +12 -9
- package/dist/components/ui/sonner.d.ts +1 -1
- package/dist/components/ui/sonner.d.ts.map +1 -1
- package/dist/components/ui/table.d.ts.map +1 -1
- package/dist/components/ui/table.js +7 -2
- package/dist/components/ui/toggle.d.ts +12 -4
- package/dist/components/ui/toggle.d.ts.map +1 -1
- package/dist/components/ui/toggle.js +13 -2
- package/dist/components/ui/toolbar.d.ts +9 -2
- package/dist/components/ui/toolbar.d.ts.map +1 -1
- package/dist/components/ui/toolbar.js +23 -4
- package/dist/components/ui/tooltip.d.ts +8 -3
- package/dist/components/ui/tooltip.d.ts.map +1 -1
- package/dist/components/ui/tooltip.js +11 -6
- package/dist/lib/frame-lifecycle.d.ts +1 -0
- package/dist/lib/frame-lifecycle.d.ts.map +1 -1
- package/dist/lib/frame-lifecycle.js +3 -2
- package/dist/lib/theme.d.ts.map +1 -1
- package/dist/lib/theme.js +2 -1
- package/docs/README.md +3 -1
- package/docs/adaptive-materials.md +79 -0
- package/docs/app-anatomy.md +3 -1
- package/docs/component-catalog.md +26 -3
- package/docs/design-tokens.md +17 -4
- package/docs/foundations.md +5 -3
- package/docs/standalone-app-windows.md +8 -0
- package/package.json +1 -2
- package/src/components/ui/alert-dialog.md +31 -0
- package/src/components/ui/alert.md +28 -6
- package/src/components/ui/app-frame.md +5 -0
- package/src/components/ui/collapsible.md +52 -0
- package/src/components/ui/combobox.md +0 -1
- package/src/components/ui/command.md +54 -0
- package/src/components/ui/date-field.md +1 -1
- package/src/components/ui/date-picker.md +55 -0
- package/src/components/ui/dialog.md +40 -0
- package/src/components/ui/empty.md +8 -3
- package/src/components/ui/grid.md +8 -4
- package/src/components/ui/icon-button.md +2 -2
- package/src/components/ui/list.md +35 -2
- package/src/components/ui/material.md +51 -0
- package/src/components/ui/navigation-button-group.md +46 -0
- package/src/components/ui/popover.md +31 -0
- package/src/components/ui/scroll-area.md +11 -7
- package/src/components/ui/search-field.md +1 -1
- package/src/components/ui/segmented-control.md +2 -5
- package/src/components/ui/sheet.md +30 -0
- package/src/components/ui/table.md +4 -2
- package/src/components/ui/toggle-button.md +48 -0
- package/src/components/ui/toolbar.md +5 -0
- package/src/components/ui/tooltip.md +31 -0
- package/src/styles/index.css +213 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Adaptive materials
|
|
2
|
+
|
|
3
|
+
Moldable uses restrained translucent material to separate controls and
|
|
4
|
+
navigation from the content they operate on. Material frames content; it does
|
|
5
|
+
not replace content surfaces.
|
|
6
|
+
|
|
7
|
+
## Roles
|
|
8
|
+
|
|
9
|
+
Use `regular` material for normal toolbar and window chrome, grouped controls,
|
|
10
|
+
menus, and temporary control overlays. It provides enough frosting for text
|
|
11
|
+
and icons to remain stable as content moves behind it.
|
|
12
|
+
|
|
13
|
+
Use `clear` material only for compact controls floating over photos, maps,
|
|
14
|
+
video, or another richly colored canvas. Check the control against the
|
|
15
|
+
lightest, darkest, and busiest content it can cover. If contrast is not stable,
|
|
16
|
+
use `regular`.
|
|
17
|
+
|
|
18
|
+
Documents, calendars, tables, forms, cards, sheets, inspectors, and primary
|
|
19
|
+
working canvases remain opaque. Do not stack translucent content cards to
|
|
20
|
+
create hierarchy.
|
|
21
|
+
|
|
22
|
+
## Components
|
|
23
|
+
|
|
24
|
+
`Material` applies one adaptive surface:
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
<Material asChild variant="clear" shape="circle" interactive>
|
|
28
|
+
<IconButton label="Center map" variant="ghost">
|
|
29
|
+
<Locate />
|
|
30
|
+
</IconButton>
|
|
31
|
+
</Material>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`MaterialGroup` applies one sampled layer to a related cluster:
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<MaterialGroup variant="regular" shape="capsule" spacing="compact">
|
|
38
|
+
<IconButton label="Previous" variant="ghost">
|
|
39
|
+
<ChevronLeft />
|
|
40
|
+
</IconButton>
|
|
41
|
+
<IconButton label="Next" variant="ghost">
|
|
42
|
+
<ChevronRight />
|
|
43
|
+
</IconButton>
|
|
44
|
+
</MaterialGroup>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Children of a `MaterialGroup` should be ordinary transparent or ghost
|
|
48
|
+
controls. Do not apply another `Material` to every child. A single grouped
|
|
49
|
+
sampler produces clearer hierarchy and avoids accumulated blur.
|
|
50
|
+
|
|
51
|
+
`Toolbar`, `AppFrameTitlebar`, and `AppFrameStatusbar` expose a `material`
|
|
52
|
+
property. Their normal chrome uses `regular`; pass `material="none"` for an
|
|
53
|
+
opaque or transparent composition that supplies its own surface.
|
|
54
|
+
|
|
55
|
+
## Fallback behavior
|
|
56
|
+
|
|
57
|
+
Every material starts from an opaque fallback. Translucent sampling is enabled
|
|
58
|
+
only when the renderer supports backdrop filtering.
|
|
59
|
+
|
|
60
|
+
- Reduced transparency uses opaque fills and removes blur and saturation.
|
|
61
|
+
- Increased contrast makes fills more opaque and strengthens borders.
|
|
62
|
+
- Forced colors use system surfaces and borders without blur or shadows.
|
|
63
|
+
- Reduced motion removes material press transforms.
|
|
64
|
+
|
|
65
|
+
The manual `data-transparency="reduced"`, `data-contrast="increased"`, and
|
|
66
|
+
`data-motion="reduced"` attributes mirror system preferences for deterministic
|
|
67
|
+
catalog and app testing.
|
|
68
|
+
|
|
69
|
+
Do not animate blur, saturation, or backdrop filters. They are expensive,
|
|
70
|
+
visually noisy, and difficult to make accessible. Limit the number of visible
|
|
71
|
+
sampled layers and avoid nesting them.
|
|
72
|
+
|
|
73
|
+
## Host boundary
|
|
74
|
+
|
|
75
|
+
CSS material samples content inside the app renderer. It cannot sample the
|
|
76
|
+
desktop behind a native window. Native behind-window material, window
|
|
77
|
+
transparency, active-window appearance, and energy policy remain host-owned
|
|
78
|
+
capabilities. Apps should use the same semantic variants regardless of which
|
|
79
|
+
adapter renders them.
|
package/docs/app-anatomy.md
CHANGED
|
@@ -9,7 +9,9 @@ canvas independent of the desktop shell.
|
|
|
9
9
|
```tsx
|
|
10
10
|
<AppFrame>
|
|
11
11
|
<AppFrameTitlebar>
|
|
12
|
-
<AppFrameToolbar>
|
|
12
|
+
<AppFrameToolbar>
|
|
13
|
+
{/* title, view controls, primary actions */}
|
|
14
|
+
</AppFrameToolbar>
|
|
13
15
|
</AppFrameTitlebar>
|
|
14
16
|
<AppFrameContent scrollable={false}>
|
|
15
17
|
{/* app-owned canvas and panes */}
|
|
@@ -20,6 +20,7 @@ const manifest = createCatalogManifest({
|
|
|
20
20
|
{
|
|
21
21
|
id: 'primary-action',
|
|
22
22
|
title: 'Primary action',
|
|
23
|
+
components: ['button'],
|
|
23
24
|
interactions: ['rest', 'focus-visible', 'disabled', 'loading'],
|
|
24
25
|
render: ({ interaction }) => (
|
|
25
26
|
<Button
|
|
@@ -45,6 +46,8 @@ Every public interactive component should cover:
|
|
|
45
46
|
- light and dark themes;
|
|
46
47
|
- regular and compact density;
|
|
47
48
|
- wide and narrow viewports;
|
|
49
|
+
- standard accessibility behavior plus reduced transparency, increased
|
|
50
|
+
contrast, and reduced motion where material or motion is part of the recipe;
|
|
48
51
|
- rest, focus-visible, disabled, invalid, selected, loading, and empty states
|
|
49
52
|
where those states apply;
|
|
50
53
|
- keyboard behavior in unit tests.
|
|
@@ -54,6 +57,26 @@ lets a visual-regression runner capture one addressable case at a time. Keep
|
|
|
54
57
|
catalog stories deterministic: fixed content, fixed dates, no network calls,
|
|
55
58
|
and no animation unless motion itself is under review.
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
Accessibility environments are opt-in per story through
|
|
61
|
+
`accessibilityModes`. Standard cases preserve the existing case ID; a
|
|
62
|
+
nonstandard mode is appended as the final segment. The catalog maps those
|
|
63
|
+
modes to deterministic `data-transparency`, `data-contrast`, and `data-motion`
|
|
64
|
+
attributes.
|
|
65
|
+
|
|
66
|
+
## Public component accountability
|
|
67
|
+
|
|
68
|
+
Every story declares the public visual component modules it exercises through
|
|
69
|
+
`components`. The core catalog test reads the barrel exports from
|
|
70
|
+
`components/ui/index.ts` and requires every module to be either:
|
|
71
|
+
|
|
72
|
+
- named by at least one deterministic story; or
|
|
73
|
+
- listed in `coreCatalogExclusions` with a concise reason.
|
|
74
|
+
|
|
75
|
+
Exclusions are visible debt, not permanent exemptions. Remove an exclusion in
|
|
76
|
+
the same change that adds representative stories. Unknown component ids, stale
|
|
77
|
+
exclusions, duplicate exclusions, and empty reasons fail the catalog test.
|
|
78
|
+
|
|
79
|
+
The core catalog covers window materials, semantic controls, collections,
|
|
80
|
+
navigation, representative popover material, and feedback recipes. Complex
|
|
81
|
+
portals and geometry-dependent components remain explicitly deferred until an
|
|
82
|
+
isolated browser fixture can make their states deterministic.
|
package/docs/design-tokens.md
CHANGED
|
@@ -119,15 +119,28 @@ related objects visually consistent. `rounded-window` is host-informed and
|
|
|
119
119
|
normally only useful in previews; the native host owns the actual window
|
|
120
120
|
shape.
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
Adaptive material has two semantic variants. Each includes fill, fallback,
|
|
123
|
+
border, highlight, blur, and saturation tokens:
|
|
123
124
|
|
|
124
|
-
- `--material-
|
|
125
|
-
- `--material-
|
|
126
|
-
|
|
125
|
+
- `--material-regular-*` supports normal toolbar and control chrome.
|
|
126
|
+
- `--material-clear-*` supports compact controls over media or a richly
|
|
127
|
+
colored canvas.
|
|
128
|
+
- `shadow-panel`, `shadow-overlay`, and `shadow-window` provide elevation
|
|
129
|
+
independently from translucency.
|
|
130
|
+
|
|
131
|
+
Use `Material` and `MaterialGroup` instead of assembling those tokens in app
|
|
132
|
+
markup. `MaterialGroup` owns one sampled layer for a related control cluster;
|
|
133
|
+
its children must not add nested material.
|
|
127
134
|
|
|
128
135
|
Translucency must have an opaque fallback. The token system removes blur and
|
|
129
136
|
uses opaque toolbar and overlay surfaces when the operating system requests
|
|
130
137
|
reduced transparency or an ancestor has `data-transparency="reduced"`.
|
|
138
|
+
Unsupported renderers stay on the same opaque fallback. Increased contrast
|
|
139
|
+
makes fills more opaque and strengthens their borders.
|
|
140
|
+
|
|
141
|
+
Material is a control and navigation affordance. Primary canvases, documents,
|
|
142
|
+
tables, calendars, forms, cards, sheets, and inspectors remain opaque. See
|
|
143
|
+
[Adaptive materials](./adaptive-materials.md) for composition rules.
|
|
131
144
|
|
|
132
145
|
## Motion
|
|
133
146
|
|
package/docs/foundations.md
CHANGED
|
@@ -37,9 +37,11 @@ Status color communicates status only; it is not decoration.
|
|
|
37
37
|
Use semantic tokens only. Do not introduce raw gray, zinc, white, or black
|
|
38
38
|
classes in app UI.
|
|
39
39
|
|
|
40
|
-
Use material
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
Use adaptive material only for navigation and control layers. Regular material
|
|
41
|
+
supports toolbars and grouped controls; clear material is reserved for compact
|
|
42
|
+
controls over media. Content canvases and content-bearing surfaces stay
|
|
43
|
+
opaque. Group related controls under one sampler and never nest material
|
|
44
|
+
effects.
|
|
43
45
|
|
|
44
46
|
## Motion
|
|
45
47
|
|
|
@@ -41,6 +41,14 @@ the document root. Composite content insets then resolve automatically. The
|
|
|
41
41
|
transport used to deliver those values belongs to the host integration layer,
|
|
42
42
|
not individual apps.
|
|
43
43
|
|
|
44
|
+
Dedicated windows use the host titlebar by default. An app with a unified
|
|
45
|
+
toolbar can declare `{ "window": { "titlebar": "app" } }` in `moldable.json`.
|
|
46
|
+
In that mode the host removes its strip and advertises the titlebar height and
|
|
47
|
+
leading window-control inset. `AppFrameTitlebar` consumes those values, sends
|
|
48
|
+
`startWindowDrag` on a non-interactive pointerdown, and sends
|
|
49
|
+
`titlebarDoubleClick` on a non-interactive double-click. The latter toggles
|
|
50
|
+
maximize as a cross-platform approximation of the macOS titlebar zoom action.
|
|
51
|
+
|
|
44
52
|
Window appearance roles are `--window-chrome-background`,
|
|
45
53
|
`--window-chrome-foreground`, `--window-chrome-muted-foreground`,
|
|
46
54
|
`--window-border`, and `--material-shadow-window`. The host may update the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moldable-ai/ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.21",
|
|
4
4
|
"description": "Shared UI components for Moldable applications",
|
|
5
5
|
"author": "Desiderata LLC",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -80,7 +80,6 @@
|
|
|
80
80
|
"@radix-ui/react-toggle": "^1.1.10",
|
|
81
81
|
"@radix-ui/react-toggle-group": "^1.1.11",
|
|
82
82
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
83
|
-
"@shadcn/react": "^0.2.1",
|
|
84
83
|
"@tailwindcss/typography": "^0.5.16",
|
|
85
84
|
"class-variance-authority": "^0.7.1",
|
|
86
85
|
"clsx": "^2.1.1",
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Alert Dialog and Confirm Dialog
|
|
2
|
+
|
|
3
|
+
Use `AlertDialog` when the user must acknowledge a consequential choice. Use the
|
|
4
|
+
composed anatomy for custom content and `ConfirmDialog` for the common
|
|
5
|
+
promise-aware confirmation path.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<ConfirmDialog
|
|
9
|
+
trigger={<Button variant="destructive">Delete recording</Button>}
|
|
10
|
+
title="Delete recording?"
|
|
11
|
+
description="This removes the local audio and transcript."
|
|
12
|
+
confirmLabel="Delete"
|
|
13
|
+
pendingLabel="Deleting…"
|
|
14
|
+
variant="destructive"
|
|
15
|
+
onConfirm={() => deleteRecording()}
|
|
16
|
+
/>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`ConfirmDialog` prevents duplicate submission, disables cancellation while the
|
|
20
|
+
operation is pending, closes only after success, and keeps failures in the
|
|
21
|
+
dialog. Pass `getErrorMessage` when a safe, actionable domain error can be
|
|
22
|
+
shown. The default error deliberately avoids exposing internal details.
|
|
23
|
+
|
|
24
|
+
`AlertDialogContent` supports `sm`, `default`, and `lg` and stays within the
|
|
25
|
+
host safe area. Use `AlertDialogBody` when explanation or affected-item content
|
|
26
|
+
can grow. Keep the consequence visible while the action is pending.
|
|
27
|
+
|
|
28
|
+
Use concrete labels such as “Delete recording,” not “OK.” Put the safe,
|
|
29
|
+
reversible action first in keyboard order and the confirming action last. Do
|
|
30
|
+
not use an alert dialog for ordinary navigation, long forms, or success
|
|
31
|
+
messages.
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
|
-
`Alert` presents
|
|
5
|
+
`Alert` presents a persistent inline callout that belongs to the current
|
|
6
|
+
surface. Use it for recoverable errors, permission or connection problems, and
|
|
7
|
+
information the user should notice before continuing.
|
|
6
8
|
|
|
7
9
|
Use `AlertDialog` when the user must confirm an action. Use `Empty` for the normal absence of data. Use a toast for brief feedback that does not need to remain in the layout.
|
|
8
10
|
|
|
@@ -12,23 +14,42 @@ Use `AlertDialog` when the user must confirm an action. Use `Empty` for the norm
|
|
|
12
14
|
import { CircleAlert } from 'lucide-react'
|
|
13
15
|
import { Alert, AlertDescription, AlertTitle } from '@moldable-ai/ui'
|
|
14
16
|
|
|
15
|
-
;<Alert
|
|
17
|
+
;<Alert tone="danger">
|
|
16
18
|
<CircleAlert />
|
|
17
19
|
<AlertTitle>Could not save</AlertTitle>
|
|
18
20
|
<AlertDescription>
|
|
19
21
|
The file changed on disk. Reload it, then try again.
|
|
20
22
|
</AlertDescription>
|
|
23
|
+
<AlertActions>
|
|
24
|
+
<Button size="sm">Reload</Button>
|
|
25
|
+
</AlertActions>
|
|
21
26
|
</Alert>
|
|
22
27
|
```
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
Dismissible informational callouts may use `AlertDismiss`. Dismissal state is
|
|
30
|
+
owned by the caller:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<Alert tone="info">
|
|
34
|
+
<InfoIcon />
|
|
35
|
+
<AlertTitle>Local-only data</AlertTitle>
|
|
36
|
+
<AlertDescription>This workspace has not been synced.</AlertDescription>
|
|
37
|
+
<AlertDismiss label="Dismiss local-only notice" onClick={dismiss} />
|
|
38
|
+
</Alert>
|
|
39
|
+
```
|
|
25
40
|
|
|
26
41
|
## API summary
|
|
27
42
|
|
|
28
|
-
- `
|
|
29
|
-
- `
|
|
43
|
+
- `tone`: `neutral`, `info`, `success`, `warning`, or `danger`.
|
|
44
|
+
- `density`: `compact` or `default`.
|
|
45
|
+
- Neutral through warning tones default to `role="status"`; danger defaults to
|
|
46
|
+
`role="alert"`. The native `role` prop can override that choice.
|
|
47
|
+
- `variant="default"` and `variant="destructive"` remain compatibility aliases.
|
|
30
48
|
- `AlertTitle`: the short, emphasized heading.
|
|
31
49
|
- `AlertDescription`: muted supporting content; supports nested paragraphs and controls.
|
|
50
|
+
- `AlertActions`: a compact action row.
|
|
51
|
+
- `AlertDismiss`: an icon action with a required accessible `label`; the caller
|
|
52
|
+
owns dismissal.
|
|
32
53
|
- All parts accept the native props for their rendered element and a `className`.
|
|
33
54
|
- A direct icon child on `Alert` receives the component’s grid placement and sizing.
|
|
34
55
|
|
|
@@ -44,9 +65,10 @@ An alert can include a compact retry or setup action in its description, but the
|
|
|
44
65
|
|
|
45
66
|
- Do not use an alert as decorative introductory copy.
|
|
46
67
|
- Do not show stack traces, raw exceptions, or secret values.
|
|
47
|
-
- Do not use `
|
|
68
|
+
- Do not use `danger` for neutral notices.
|
|
48
69
|
- Do not rely on the icon or color alone for meaning.
|
|
49
70
|
- Do not use `Alert` as a confirmation surface.
|
|
71
|
+
- Do not use an alert for brief success feedback that should be a toast.
|
|
50
72
|
|
|
51
73
|
## Moldable considerations
|
|
52
74
|
|
|
@@ -21,6 +21,9 @@ surface.
|
|
|
21
21
|
- Let the host render real window controls. Never draw imitation traffic lights.
|
|
22
22
|
- Make the app's primary canvas the visual focus; titlebars and status bars are
|
|
23
23
|
supporting structure.
|
|
24
|
+
- Titlebars and status bars use `material="regular"` by default. Use
|
|
25
|
+
`material="clear"` only when compact chrome overlays a rich canvas, or
|
|
26
|
+
`material="none"` when the composition supplies an opaque surface.
|
|
24
27
|
- The app frame does not make the outer window draggable. A decorated native
|
|
25
28
|
titlebar or host-owned drag region must provide that behavior.
|
|
26
29
|
- The host owns the `--window-*` inset variables. The component only consumes
|
|
@@ -31,3 +34,5 @@ surface.
|
|
|
31
34
|
tests. Runtime apps should normally use `mode="auto"`; a future host context
|
|
32
35
|
may set `data-moldable-display-mode` before render when a window still uses an
|
|
33
36
|
app iframe.
|
|
37
|
+
- Material samples only renderer content. Native behind-window material remains
|
|
38
|
+
host-owned.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Collapsible
|
|
2
|
+
|
|
3
|
+
`Collapsible` exposes the unstyled Radix disclosure primitive.
|
|
4
|
+
`CollapsibleSection` adds a consistent section trigger, state-aware chevron,
|
|
5
|
+
border, and content spacing.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<CollapsibleSection defaultOpen>
|
|
9
|
+
<CollapsibleSectionTrigger>Advanced options</CollapsibleSectionTrigger>
|
|
10
|
+
<CollapsibleSectionContent>
|
|
11
|
+
Controls that are useful less often.
|
|
12
|
+
</CollapsibleSectionContent>
|
|
13
|
+
</CollapsibleSection>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## When to use
|
|
17
|
+
|
|
18
|
+
Use a collapsible section for one independently disclosed region. Use
|
|
19
|
+
`Accordion` when several peer sections need coordinated one-at-a-time or
|
|
20
|
+
multi-section behavior.
|
|
21
|
+
|
|
22
|
+
## API
|
|
23
|
+
|
|
24
|
+
The base `Collapsible`, `CollapsibleTrigger`, and `CollapsibleContent` expose
|
|
25
|
+
the Radix props directly.
|
|
26
|
+
|
|
27
|
+
The section helpers add:
|
|
28
|
+
|
|
29
|
+
- `CollapsibleSection`: bordered section root.
|
|
30
|
+
- `CollapsibleSectionTrigger`: full-width trigger with a chevron driven by the
|
|
31
|
+
root `data-state`.
|
|
32
|
+
- `CollapsibleSectionContent`: standard inset content.
|
|
33
|
+
- `motion`: `default` or `none`.
|
|
34
|
+
- `contentClassName`: styles the inset inner content without changing the
|
|
35
|
+
animated viewport.
|
|
36
|
+
|
|
37
|
+
## Keyboard and accessibility
|
|
38
|
+
|
|
39
|
+
The trigger is a button with `aria-expanded` and `aria-controls` managed by
|
|
40
|
+
Radix. Space and Enter toggle it. The chevron is decorative.
|
|
41
|
+
|
|
42
|
+
## Motion
|
|
43
|
+
|
|
44
|
+
Motion is brief and uses the shared reduced-motion behavior. Set
|
|
45
|
+
`motion="none"` for content where movement would distract or when a parent owns
|
|
46
|
+
the transition.
|
|
47
|
+
|
|
48
|
+
## Don't
|
|
49
|
+
|
|
50
|
+
- Do not put another interactive control inside the trigger.
|
|
51
|
+
- Do not hide required validation errors or primary actions by default.
|
|
52
|
+
- Do not use a disclosure solely to make a sparse layout look busier.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Command
|
|
2
|
+
|
|
3
|
+
`Command` renders searchable, keyboard-driven actions and local choices.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
Use `CommandDialog` for an app-local command palette or picker with enough
|
|
8
|
+
options to benefit from search. Use the item anatomy helpers when a result has
|
|
9
|
+
supporting text or metadata.
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
<CommandItem value="Open project">
|
|
13
|
+
<CommandItemIcon>
|
|
14
|
+
<FolderIcon />
|
|
15
|
+
</CommandItemIcon>
|
|
16
|
+
<CommandItemContent>
|
|
17
|
+
<CommandItemTitle>Open project</CommandItemTitle>
|
|
18
|
+
<CommandItemDescription>Choose a local folder</CommandItemDescription>
|
|
19
|
+
</CommandItemContent>
|
|
20
|
+
<CommandShortcut>⌘O</CommandShortcut>
|
|
21
|
+
</CommandItem>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Anatomy
|
|
25
|
+
|
|
26
|
+
- `Command`, `CommandInput`, and `CommandList` own filtering and navigation.
|
|
27
|
+
- `CommandGroup`, `CommandEmpty`, and `CommandSeparator` organize results.
|
|
28
|
+
- `CommandItem` is the interactive cmdk option.
|
|
29
|
+
- `CommandItemIcon`, `CommandItemContent`, `CommandItemTitle`, and
|
|
30
|
+
`CommandItemDescription` provide consistent row alignment.
|
|
31
|
+
- `CommandShortcut` displays a trailing shortcut hint; it does not install the
|
|
32
|
+
shortcut.
|
|
33
|
+
|
|
34
|
+
Use `NotificationDot`, `Status`, or `Spinner` as a trailing child when a result
|
|
35
|
+
needs an indicator. Keep those states semantic instead of adding decoration to
|
|
36
|
+
the row anatomy.
|
|
37
|
+
|
|
38
|
+
## Keyboard and accessibility
|
|
39
|
+
|
|
40
|
+
cmdk owns arrow-key navigation, selection, and filtering. Give icon-only
|
|
41
|
+
information an accessible text equivalent. `CommandItemIcon` is decorative by
|
|
42
|
+
default because the adjacent title should name the command.
|
|
43
|
+
|
|
44
|
+
## Platform behavior
|
|
45
|
+
|
|
46
|
+
This is a portable renderer component. An app-local palette does not replace
|
|
47
|
+
the host command surface. Register host-visible commands through the Moldable
|
|
48
|
+
command API and use this component only for commands owned by the current app.
|
|
49
|
+
|
|
50
|
+
## Don't
|
|
51
|
+
|
|
52
|
+
- Do not create a second interactive row inside `CommandItem`.
|
|
53
|
+
- Do not install keyboard shortcuts from `CommandShortcut`.
|
|
54
|
+
- Do not use a command palette for a small fixed set that fits in a menu.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# DatePicker
|
|
2
|
+
|
|
3
|
+
`DatePicker` is a portable, date-only calendar popover. Its value is an ISO
|
|
4
|
+
calendar date (`YYYY-MM-DD`), so app storage does not introduce timezone
|
|
5
|
+
conversion.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<DatePicker
|
|
9
|
+
aria-label="Due date"
|
|
10
|
+
value={dueDate}
|
|
11
|
+
onValueChange={setDueDate}
|
|
12
|
+
min="2026-01-01"
|
|
13
|
+
clearable
|
|
14
|
+
/>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## DatePicker or DateField
|
|
18
|
+
|
|
19
|
+
- Use `DatePicker` when a predictable renderer-owned calendar is important.
|
|
20
|
+
- Use `DateField` when compact keyboard entry and the browser's date control
|
|
21
|
+
are preferable.
|
|
22
|
+
- Use the standalone `Calendar` for ranges, multiple dates, or an always
|
|
23
|
+
visible month.
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
- `value`, `defaultValue`: ISO `YYYY-MM-DD` or an empty string.
|
|
28
|
+
- `onValueChange`: receives the next ISO date or an empty string.
|
|
29
|
+
- `min`, `max`: inclusive ISO date limits.
|
|
30
|
+
- `placeholder`: trigger copy when empty.
|
|
31
|
+
- `locale`: the `react-day-picker` locale used by the calendar and display.
|
|
32
|
+
- `formatValue`: custom trigger rendering for the ISO value.
|
|
33
|
+
- `clearable`, `clearLabel`: optional clear action inside the popover.
|
|
34
|
+
- `density`: `compact`, `default`, or `comfortable`.
|
|
35
|
+
- `open`, `defaultOpen`, `onOpenChange`: controlled or uncontrolled popover.
|
|
36
|
+
- Remaining button props apply to the trigger.
|
|
37
|
+
|
|
38
|
+
## Keyboard and accessibility
|
|
39
|
+
|
|
40
|
+
Label the trigger through visible form text, `aria-labelledby`, or
|
|
41
|
+
`aria-label`. The trigger opens with Enter or Space. The calendar owns arrow,
|
|
42
|
+
Home, End, Page Up, and Page Down behavior. Selection closes the popover and
|
|
43
|
+
focus returns to the trigger.
|
|
44
|
+
|
|
45
|
+
## Platform behavior
|
|
46
|
+
|
|
47
|
+
This component is portable and uses no host API. A future native date or time
|
|
48
|
+
control must be introduced through a shared host capability with this
|
|
49
|
+
renderer-owned control as its fallback.
|
|
50
|
+
|
|
51
|
+
## Don't
|
|
52
|
+
|
|
53
|
+
- Do not put timestamps or UTC instants in this date-only value.
|
|
54
|
+
- Do not use this component for time, date-time, or date-range selection.
|
|
55
|
+
- Do not manually convert the selected value through `Date.toISOString()`.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Dialog
|
|
2
|
+
|
|
3
|
+
Use `Dialog` for focused work that temporarily blocks the current surface. Use
|
|
4
|
+
`AlertDialog` or `ConfirmDialog` for consequential confirmation, `Popover` for
|
|
5
|
+
small anchored controls, and `Sheet` for a secondary region that should retain
|
|
6
|
+
spatial context.
|
|
7
|
+
|
|
8
|
+
## Anatomy
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
<Dialog>
|
|
12
|
+
<DialogTrigger asChild>
|
|
13
|
+
<Button>Edit details</Button>
|
|
14
|
+
</DialogTrigger>
|
|
15
|
+
<DialogContent size="lg">
|
|
16
|
+
<DialogHeader>
|
|
17
|
+
<DialogTitle>Edit details</DialogTitle>
|
|
18
|
+
<DialogDescription>Update the selected record.</DialogDescription>
|
|
19
|
+
</DialogHeader>
|
|
20
|
+
<DialogBody>{/* the only scrolling region */}</DialogBody>
|
|
21
|
+
<DialogFooter>{/* actions remain reachable */}</DialogFooter>
|
|
22
|
+
</DialogContent>
|
|
23
|
+
</Dialog>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`DialogContent` supports `sm`, `default`, `lg`, and `full`. It limits itself to
|
|
27
|
+
the host-provided window and chat-safe insets. `DialogBody` owns vertical
|
|
28
|
+
scrolling; do not put overflow on both the content and body.
|
|
29
|
+
|
|
30
|
+
Keep dialogs opaque and visually stable. Translucent material belongs on small
|
|
31
|
+
temporary control overlays where seeing the underlying context is useful.
|
|
32
|
+
|
|
33
|
+
For async actions, keep the dialog controlled, disable duplicate submission,
|
|
34
|
+
preserve the action label width, show inline field errors, and close only after
|
|
35
|
+
success. Use `ConfirmDialog` when that is the entire workflow.
|
|
36
|
+
|
|
37
|
+
Every dialog needs a `DialogTitle`. Add `DialogDescription` when the outcome or
|
|
38
|
+
scope is not obvious. Escape, outside dismissal, initial focus, and focus return
|
|
39
|
+
come from the Radix primitive; do not replace them with manual document event
|
|
40
|
+
handlers.
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
EmptyTitle,
|
|
21
21
|
} from '@moldable-ai/ui'
|
|
22
22
|
|
|
23
|
-
;<Empty
|
|
23
|
+
;<Empty variant="pane" safeBottom>
|
|
24
24
|
<EmptyHeader>
|
|
25
25
|
<EmptyMedia variant="icon">
|
|
26
26
|
<Database />
|
|
@@ -52,6 +52,9 @@ For a successful zero state, omit the action when there is nothing useful to do:
|
|
|
52
52
|
## API summary
|
|
53
53
|
|
|
54
54
|
- `Empty`: centered flex container for the complete state.
|
|
55
|
+
- `Empty variant`: `compact`, `pane`, or `full`; defaults to `pane`.
|
|
56
|
+
- `Empty safeBottom`: adds host-provided chat clearance. Do not enable it when
|
|
57
|
+
an owning `AppFrameContent` or parent scroll region already applies clearance.
|
|
55
58
|
- `EmptyHeader`: groups media, title, and description.
|
|
56
59
|
- `EmptyMedia`: `variant="default"` or `variant="icon"`.
|
|
57
60
|
- `EmptyTitle`: primary label.
|
|
@@ -65,7 +68,7 @@ For a successful zero state, omit the action when there is nothing useful to do:
|
|
|
65
68
|
- Show one primary setup action when the state is blocked.
|
|
66
69
|
- Distinguish first-run, filtered-zero, permission, and successful-zero states.
|
|
67
70
|
- Keep the app’s normal shell or pane structure visible.
|
|
68
|
-
-
|
|
71
|
+
- Use `safeBottom` when the empty state itself owns a pane that reaches the bottom.
|
|
69
72
|
|
|
70
73
|
## Don't
|
|
71
74
|
|
|
@@ -79,4 +82,6 @@ For a successful zero state, omit the action when there is nothing useful to do:
|
|
|
79
82
|
|
|
80
83
|
An empty state should feel like part of a local instrument, not a landing page. Keep it visually small even when centered. If the desktop chat can resolve the state, provide specific app context or an explicit “Ask Moldable about this” affordance that prefills desktop chat; do not add another chat box.
|
|
81
84
|
|
|
82
|
-
For scrollable panes,
|
|
85
|
+
For scrollable panes, prefer `safeBottom` on the owning `ScrollArea`. Apply it
|
|
86
|
+
to `Empty` only when the empty state is the owner, so nested states do not add
|
|
87
|
+
the same safe area twice.
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
GridItemTitle,
|
|
19
19
|
} from '@moldable-ai/ui'
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
;<Grid
|
|
22
22
|
aria-label="Artifacts"
|
|
23
23
|
columns={3}
|
|
24
24
|
selectionMode="single"
|
|
@@ -56,14 +56,18 @@ Prefer changing this value at deliberate window breakpoints. A smaller window sh
|
|
|
56
56
|
|
|
57
57
|
## Interaction contract
|
|
58
58
|
|
|
59
|
-
- Arrow Left/Right moves
|
|
60
|
-
- Arrow Up/Down moves
|
|
61
|
-
- Home and End move to the first and last available tile.
|
|
59
|
+
- Arrow Left/Right moves within the current row and stops at its edge.
|
|
60
|
+
- Arrow Up/Down moves within the current column and stops at its edge.
|
|
61
|
+
- Home and End move to the first and last available tile in the current row.
|
|
62
|
+
- Control/Command + Home and End move to the first and last available tile in
|
|
63
|
+
the entire grid.
|
|
62
64
|
- Space changes selection.
|
|
63
65
|
- Enter changes selection and invokes `onAction`.
|
|
64
66
|
- A single pointer click changes selection. A double click invokes `onAction`.
|
|
65
67
|
- Disabled tiles are skipped.
|
|
66
68
|
- Buttons and links inside a tile preserve their own pointer behavior.
|
|
69
|
+
- When the grid first mounts, the first selected, enabled tile receives the
|
|
70
|
+
roving tab stop. If nothing is selected, the first enabled tile receives it.
|
|
67
71
|
|
|
68
72
|
## API summary
|
|
69
73
|
|