@moldable-ai/ui 0.2.26 → 0.2.31
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/component-catalog.d.ts +9 -2
- package/dist/catalog/component-catalog.d.ts.map +1 -1
- package/dist/catalog/component-catalog.js +11 -7
- package/dist/catalog/core-control-stories.d.ts.map +1 -1
- package/dist/catalog/core-control-stories.js +1 -1
- package/dist/catalog/core-foundation-stories.d.ts.map +1 -1
- package/dist/catalog/core-foundation-stories.js +15 -3
- package/dist/components/ui/app-frame.d.ts +20 -1
- package/dist/components/ui/app-frame.d.ts.map +1 -1
- package/dist/components/ui/app-frame.js +37 -7
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/badge.js +1 -1
- package/dist/components/ui/button.d.ts +5 -3
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/button.js +39 -10
- package/dist/components/ui/card.d.ts +12 -2
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/card.js +3 -2
- package/dist/components/ui/checkbox.d.ts +4 -1
- package/dist/components/ui/checkbox.d.ts.map +1 -1
- package/dist/components/ui/checkbox.js +4 -4
- package/dist/components/ui/context-menu.js +6 -6
- package/dist/components/ui/date-field.d.ts +1 -1
- package/dist/components/ui/dropdown-menu.js +6 -6
- package/dist/components/ui/icon-button.d.ts +1 -1
- package/dist/components/ui/icon-button.d.ts.map +1 -1
- package/dist/components/ui/icon-button.js +1 -0
- package/dist/components/ui/index.d.ts +1 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +1 -0
- package/dist/components/ui/input-group.d.ts +2 -2
- package/dist/components/ui/input.d.ts +6 -2
- package/dist/components/ui/input.d.ts.map +1 -1
- package/dist/components/ui/input.js +2 -2
- package/dist/components/ui/material.d.ts +8 -3
- package/dist/components/ui/material.d.ts.map +1 -1
- package/dist/components/ui/material.js +2 -2
- package/dist/components/ui/search-field.d.ts +3 -1
- package/dist/components/ui/search-field.d.ts.map +1 -1
- package/dist/components/ui/search-field.js +16 -6
- package/dist/components/ui/segmented-control.d.ts +3 -1
- package/dist/components/ui/segmented-control.d.ts.map +1 -1
- package/dist/components/ui/segmented-control.js +23 -17
- package/dist/components/ui/select.js +2 -2
- package/dist/components/ui/sidebar.d.ts +5 -3
- package/dist/components/ui/sidebar.d.ts.map +1 -1
- package/dist/components/ui/sidebar.js +53 -15
- package/dist/components/ui/status.d.ts +1 -1
- package/dist/components/ui/status.js +1 -1
- package/dist/components/ui/switch.d.ts +3 -1
- package/dist/components/ui/switch.d.ts.map +1 -1
- package/dist/components/ui/switch.js +3 -2
- package/dist/components/ui/toolbar-controls.d.ts +49 -0
- package/dist/components/ui/toolbar-controls.d.ts.map +1 -0
- package/dist/components/ui/toolbar-controls.js +47 -0
- package/dist/components/ui/toolbar.d.ts +5 -4
- package/dist/components/ui/toolbar.d.ts.map +1 -1
- package/dist/components/ui/toolbar.js +3 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- 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 +7 -0
- package/dist/lib/theme.d.ts +39 -5
- package/dist/lib/theme.d.ts.map +1 -1
- package/dist/lib/theme.js +105 -17
- package/dist/tokens/contracts.d.ts +79 -0
- package/dist/tokens/contracts.d.ts.map +1 -0
- package/dist/tokens/contracts.js +57 -0
- package/dist/tokens/index.d.ts +2 -0
- package/dist/tokens/index.d.ts.map +1 -0
- package/dist/tokens/index.js +1 -0
- package/docs/README.md +2 -0
- package/docs/adaptive-materials.md +14 -9
- package/docs/design-tokens.md +10 -6
- package/docs/foundations.md +3 -3
- package/docs/macos-design-audit.md +144 -0
- package/docs/native-integration.md +4 -4
- package/docs/platform-architecture.md +189 -0
- package/docs/standalone-app-windows.md +37 -0
- package/docs/visual-regression.md +6 -8
- package/package.json +13 -1
- package/src/components/ui/accordion.md +46 -0
- package/src/components/ui/alert.md +12 -4
- package/src/components/ui/app-frame.md +8 -5
- package/src/components/ui/aspect-ratio.md +37 -0
- package/src/components/ui/avatar.md +48 -0
- package/src/components/ui/breadcrumb.md +52 -0
- package/src/components/ui/button-group.md +43 -0
- package/src/components/ui/button.md +20 -4
- package/src/components/ui/calendar.md +42 -0
- package/src/components/ui/card.md +43 -0
- package/src/components/ui/carousel.md +47 -0
- package/src/components/ui/chart.md +52 -0
- package/src/components/ui/checkbox.md +36 -0
- package/src/components/ui/collapsible.md +2 -3
- package/src/components/ui/color-well.md +14 -4
- package/src/components/ui/combobox.md +3 -3
- package/src/components/ui/confirm-dialog.md +5 -4
- package/src/components/ui/context-menu.md +3 -2
- package/src/components/ui/date-field.md +6 -1
- package/src/components/ui/date-picker.md +6 -3
- package/src/components/ui/dialog.md +14 -12
- package/src/components/ui/drawer.md +58 -0
- package/src/components/ui/error-boundary-view.md +1 -1
- package/src/components/ui/field.md +2 -1
- package/src/components/ui/form.md +71 -0
- package/src/components/ui/grid.md +4 -3
- package/src/components/ui/icon-button.md +4 -1
- package/src/components/ui/input-group.md +49 -0
- package/src/components/ui/input-otp.md +56 -0
- package/src/components/ui/input.md +40 -0
- package/src/components/ui/inspector.md +47 -7
- package/src/components/ui/item.md +5 -3
- package/src/components/ui/kbd.md +30 -0
- package/src/components/ui/label.md +29 -0
- package/src/components/ui/list.md +2 -2
- package/src/components/ui/material.md +25 -12
- package/src/components/ui/menu-items.md +60 -0
- package/src/components/ui/menubar.md +58 -0
- package/src/components/ui/message-scroller-primitive.md +70 -0
- package/src/components/ui/message-scroller.md +86 -0
- package/src/components/ui/navigation-button-group.md +4 -3
- package/src/components/ui/navigation-menu.md +52 -0
- package/src/components/ui/number-input.md +8 -0
- package/src/components/ui/pagination.md +51 -0
- package/src/components/ui/panel.md +6 -0
- package/src/components/ui/popover.md +10 -7
- package/src/components/ui/progress.md +31 -0
- package/src/components/ui/radio-group.md +36 -0
- package/src/components/ui/resizable.md +2 -1
- package/src/components/ui/scroll-area.md +3 -1
- package/src/components/ui/search-field.md +6 -1
- package/src/components/ui/segmented-control.md +6 -1
- package/src/components/ui/separator.md +35 -0
- package/src/components/ui/sidebar.md +20 -3
- package/src/components/ui/skeleton.md +36 -0
- package/src/components/ui/slider.md +58 -0
- package/src/components/ui/spinner.md +41 -0
- package/src/components/ui/split-view.md +8 -4
- package/src/components/ui/switch.md +44 -0
- package/src/components/ui/table.md +7 -7
- package/src/components/ui/tabs.md +3 -1
- package/src/components/ui/textarea.md +41 -0
- package/src/components/ui/toggle-group.md +2 -2
- package/src/components/ui/toggle.md +9 -9
- package/src/components/ui/toolbar-controls.md +83 -0
- package/src/components/ui/toolbar.md +12 -6
- package/src/styles/index.css +199 -107
- package/src/tokens/contracts.ts +131 -0
- package/src/tokens/index.css +6 -0
- package/src/tokens/index.ts +23 -0
- package/src/tokens/macos-26/README.md +37 -0
- package/src/tokens/macos-26/aliases.css +53 -0
- package/src/tokens/macos-26/compatibility.css +7 -0
- package/src/tokens/macos-26/index.css +3 -0
- package/src/tokens/macos-26/source/provenance.generated.json +28 -0
- package/src/tokens/macos-26/source/sidebar.generated.css +29 -0
- package/src/tokens/macos-26/source.css +7 -0
- package/src/tokens/macos-26/web-adaptations.json +25 -0
- package/src/tokens/macos-26/web-adaptations.md +15 -0
- package/src/tokens/macos-27/accessibility.css +11 -0
- package/src/tokens/macos-27/aliases.css +304 -0
- package/src/tokens/macos-27/compatibility.css +212 -0
- package/src/tokens/macos-27/index.css +15 -0
- package/src/tokens/macos-27/recipes.css +23 -0
- package/src/tokens/macos-27/source/chrome.generated.css +338 -0
- package/src/tokens/macos-27/source/colors.generated.css +140 -0
- package/src/tokens/macos-27/source/context.generated.css +18 -0
- package/src/tokens/macos-27/source/controls.generated.css +764 -0
- package/src/tokens/macos-27/source/effects.generated.css +68 -0
- package/src/tokens/macos-27/source/kit.generated.css +50 -0
- package/src/tokens/macos-27/source/overlays-status.generated.css +931 -0
- package/src/tokens/macos-27/source/paint-styles.generated.css +81 -0
- package/src/tokens/macos-27/source/provenance.generated.json +62 -0
- package/src/tokens/macos-27/source/sizes.generated.css +385 -0
- package/src/tokens/macos-27/source/source.generated.json +554 -0
- package/src/tokens/macos-27/source/text-styles.generated.css +116 -0
- package/src/tokens/macos-27/source.css +17 -0
- package/src/tokens/macos-27/web-adaptations.css +98 -0
- package/src/tokens/macos-27/web-adaptations.json +163 -0
- package/src/tokens/macos-27/web-adaptations.md +117 -0
- package/src/tokens/moldable/brand.css +48 -0
- package/src/tokens/moldable/index.css +1 -0
- package/src/tokens/platform-contract.test.ts +290 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Moldable UI platform architecture
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Moldable applications use one stable UI contract while platform packs provide
|
|
6
|
+
versioned operating-system measurements and recipes.
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
immutable platform pack
|
|
10
|
+
→ Moldable semantic adapter
|
|
11
|
+
→ stable Moldable component API
|
|
12
|
+
→ optional Moldable brand overrides
|
|
13
|
+
→ app composition
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The current complete reference pack is `macos-27`. A partial `macos-26`
|
|
17
|
+
source module supplies the floating-sidebar recipe. Future packs can include
|
|
18
|
+
a newer macOS release, Windows, or a platform-neutral web fallback without
|
|
19
|
+
requiring apps to import version-specific tokens.
|
|
20
|
+
|
|
21
|
+
## Immutable platform packs
|
|
22
|
+
|
|
23
|
+
A platform pack contains factual source data only:
|
|
24
|
+
|
|
25
|
+
- semantic colors and appearance modes;
|
|
26
|
+
- typography metrics;
|
|
27
|
+
- control sizes, geometry, and state recipes;
|
|
28
|
+
- window, toolbar, menu, sidebar, and overlay measurements;
|
|
29
|
+
- material recipes and capability requirements;
|
|
30
|
+
- accessibility and native-host adaptations.
|
|
31
|
+
|
|
32
|
+
Published pack values never change in place. Corrections create a package
|
|
33
|
+
patch with an audit note; a new operating-system release gets a new pack.
|
|
34
|
+
Platform packs contain no artwork, images, icon paths, screenshots, fonts, or
|
|
35
|
+
copied component implementations.
|
|
36
|
+
|
|
37
|
+
Private source variables use a versioned namespace such as
|
|
38
|
+
`--m27-source-*` or `--m26-source-*` and are scoped to the source version:
|
|
39
|
+
|
|
40
|
+
```css
|
|
41
|
+
[data-ui-platform='macos'][data-ui-platform-version='27']
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This allows multiple packs to ship together without variable collisions.
|
|
45
|
+
|
|
46
|
+
Partial source modules do not become complete platform packs until they cover
|
|
47
|
+
the full stable contract. They can still contribute a deliberately versioned
|
|
48
|
+
component recipe, such as the macOS 26 floating sidebar.
|
|
49
|
+
|
|
50
|
+
## Stable Moldable contract
|
|
51
|
+
|
|
52
|
+
Applications and universal components consume only `--m-ui-*` recipe tokens
|
|
53
|
+
and stable React props. They never read versioned `--m*-source-*` variables
|
|
54
|
+
directly.
|
|
55
|
+
|
|
56
|
+
Examples:
|
|
57
|
+
|
|
58
|
+
```css
|
|
59
|
+
--m-ui-color-text-primary
|
|
60
|
+
--m-ui-color-accent
|
|
61
|
+
--m-ui-control-height
|
|
62
|
+
--m-ui-button-radius
|
|
63
|
+
--m-ui-toolbar-control-height
|
|
64
|
+
--m-ui-menu-item-height
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Each platform adapter maps its immutable source values to this contract. A
|
|
68
|
+
Moldable theme may then deliberately override a documented subset of semantic
|
|
69
|
+
roles, but cannot mutate the platform-pack source.
|
|
70
|
+
|
|
71
|
+
## Runtime selection
|
|
72
|
+
|
|
73
|
+
`ThemeProvider` resolves independent axes:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
<ThemeProvider
|
|
77
|
+
platform="macos"
|
|
78
|
+
platformVersion="27"
|
|
79
|
+
uiTheme="moldable"
|
|
80
|
+
sidebarStyle="floating"
|
|
81
|
+
appearance="system"
|
|
82
|
+
controlSize="medium"
|
|
83
|
+
/>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The resolved document attributes are:
|
|
87
|
+
|
|
88
|
+
```html
|
|
89
|
+
<html
|
|
90
|
+
data-ui-platform="macos"
|
|
91
|
+
data-ui-platform-version="27"
|
|
92
|
+
data-ui-platform-pack="macos-27"
|
|
93
|
+
data-ui-sidebar-style="floating"
|
|
94
|
+
data-ui-theme="moldable"
|
|
95
|
+
data-ui-appearance="dark"
|
|
96
|
+
data-control-size="medium"
|
|
97
|
+
></html>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Unsupported platform/version requests resolve to the explicit web fallback
|
|
101
|
+
pack rather than silently borrowing the latest macOS values.
|
|
102
|
+
|
|
103
|
+
## Independently selectable component recipes
|
|
104
|
+
|
|
105
|
+
An application can use one base platform pack while opting a component family
|
|
106
|
+
into a different, compatible anatomy. Public API names describe the result,
|
|
107
|
+
not the source OS version:
|
|
108
|
+
|
|
109
|
+
| `sidebarStyle` | Anatomy | Immutable source |
|
|
110
|
+
| -------------- | ---------------------------------------------------- | ---------------------- |
|
|
111
|
+
| `platform` | Follow the selected base platform | Selected platform pack |
|
|
112
|
+
| `floating` | Inset glass shell with independent radius and shadow | macOS 26 |
|
|
113
|
+
| `edge-to-edge` | Sidebar joined to the window/content edge | macOS 27 |
|
|
114
|
+
|
|
115
|
+
The macOS 27 edge-to-edge anatomy does not draw a standalone divider or
|
|
116
|
+
material background around the sidebar. The sidebar reveals the app/window
|
|
117
|
+
canvas beneath it, so each app can choose a plain color, image, or other
|
|
118
|
+
background for the whole composition. The hairline follows only the outer
|
|
119
|
+
window perimeter.
|
|
120
|
+
|
|
121
|
+
For an app-wide choice:
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
<ThemeProvider platform="macos" platformVersion="27" sidebarStyle="floating" />
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
For a single sidebar:
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
<Sidebar sidebarStyle="edge-to-edge">{/* … */}</Sidebar>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
`SIDEBAR_STYLES` is the registry boundary that records the source platform and
|
|
134
|
+
version for each semantic recipe. Components resolve stable
|
|
135
|
+
`--m-ui-sidebar-*` tokens and never branch on version numbers.
|
|
136
|
+
|
|
137
|
+
## Component strategy
|
|
138
|
+
|
|
139
|
+
### Universal components
|
|
140
|
+
|
|
141
|
+
Use one component when semantics and interaction behavior are shared:
|
|
142
|
+
|
|
143
|
+
- button, checkbox, radio group, switch;
|
|
144
|
+
- text, search, and number fields;
|
|
145
|
+
- slider, segmented control, progress;
|
|
146
|
+
- table, form, dialog, popover, tooltip;
|
|
147
|
+
- toolbar composition and command models.
|
|
148
|
+
|
|
149
|
+
Their DOM behavior remains accessible and platform-neutral. Platform recipes
|
|
150
|
+
control geometry and presentation.
|
|
151
|
+
|
|
152
|
+
### Platform adapters
|
|
153
|
+
|
|
154
|
+
Use a thin adapter when native ownership or interaction differs:
|
|
155
|
+
|
|
156
|
+
- native menu-bar integration;
|
|
157
|
+
- window controls and draggable titlebar regions;
|
|
158
|
+
- system file, color, date, sharing, and permission dialogs;
|
|
159
|
+
- native materials and backdrop capabilities;
|
|
160
|
+
- platform keyboard shortcuts and pointer conventions.
|
|
161
|
+
|
|
162
|
+
The app imports the stable Moldable API. The provider/host selects the adapter.
|
|
163
|
+
|
|
164
|
+
### Version-specific implementations
|
|
165
|
+
|
|
166
|
+
Only create a version-specific component when CSS recipe changes cannot express
|
|
167
|
+
the difference in semantics or anatomy. Keep the version branch at the
|
|
168
|
+
registry boundary:
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
const windowChrome = platformRegistry.resolve({
|
|
172
|
+
platform: 'macos',
|
|
173
|
+
version: '27',
|
|
174
|
+
capability: 'windowChrome',
|
|
175
|
+
})
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Do not scatter checks such as `if (macOSVersion >= 27)` through components.
|
|
179
|
+
|
|
180
|
+
## Catalog contract
|
|
181
|
+
|
|
182
|
+
The core component catalog shows resolved stable components and their state,
|
|
183
|
+
appearance, density, viewport, accessibility, and native-capability matrices.
|
|
184
|
+
The Moldable UI showcase owns raw platform-pack reference pages and
|
|
185
|
+
platform/version comparisons. Explicit Moldable overrides remain separately
|
|
186
|
+
identifiable in both surfaces.
|
|
187
|
+
|
|
188
|
+
Together these surfaces keep OS fidelity, Moldable design decisions, and
|
|
189
|
+
compatibility behavior independently reviewable.
|
|
@@ -50,6 +50,43 @@ leading window-control inset. A top `Toolbar` consumes those values, sends
|
|
|
50
50
|
maximize as a cross-platform approximation of the macOS titlebar zoom action.
|
|
51
51
|
Interactive descendants are automatically excluded from dragging.
|
|
52
52
|
|
|
53
|
+
Native behind-window material is also app-scoped and default-off. The native
|
|
54
|
+
host must know about background, titlebar, and sidebar requests before creating
|
|
55
|
+
the window, so apps declare them in `moldable.json`:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"window": {
|
|
60
|
+
"titlebar": "host",
|
|
61
|
+
"nativeMaterial": {
|
|
62
|
+
"background": true,
|
|
63
|
+
"titlebar": true,
|
|
64
|
+
"sidebar": true
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
For renderer-owned background and sidebar material, the shared frame must opt
|
|
71
|
+
in too:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
<AppFrame nativeMaterial={{ background: true, sidebar: true }}>
|
|
75
|
+
<SidebarProvider>
|
|
76
|
+
<Sidebar>{/* navigation */}</Sidebar>
|
|
77
|
+
<AppFrameContent>{/* primary canvas */}</AppFrameContent>
|
|
78
|
+
</SidebarProvider>
|
|
79
|
+
</AppFrame>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The manifest allows the host to build the native window correctly. The
|
|
83
|
+
`AppFrame` option yields the portable canvas fill to the host's frosted
|
|
84
|
+
`UnderWindowBackground` material and allows the shared `Sidebar` to declare its
|
|
85
|
+
measured region. These options are independent: apps may opt into any
|
|
86
|
+
combination of background, titlebar, and sidebar. If either side of an opt-in is
|
|
87
|
+
absent, or the platform or accessibility settings do not support sampling, the
|
|
88
|
+
corresponding surface keeps its portable semantic fill.
|
|
89
|
+
|
|
53
90
|
Window appearance roles are `--window-chrome-background`,
|
|
54
91
|
`--window-chrome-foreground`, `--window-chrome-muted-foreground`,
|
|
55
92
|
`--window-border`, and `--material-shadow-window`. The host may update the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Visual and accessibility regression
|
|
2
2
|
|
|
3
|
-
The
|
|
4
|
-
|
|
3
|
+
The runner exercises every authored story in the core component catalog. It
|
|
4
|
+
does not start the desktop shell or any Moldable-managed app.
|
|
5
5
|
|
|
6
6
|
## What runs
|
|
7
7
|
|
|
@@ -32,8 +32,7 @@ one element:
|
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
Playwright performs real hover, focus, and held-pointer interactions on that
|
|
35
|
-
element
|
|
36
|
-
exemplars.
|
|
35
|
+
element for every story that declares those live states.
|
|
37
36
|
|
|
38
37
|
Every captured case also receives an axe WCAG 2 A/AA and WCAG 2.1 A/AA scan.
|
|
39
38
|
Serious and critical violations fail. Per-story suppressions belong in
|
|
@@ -67,10 +66,9 @@ directory.
|
|
|
67
66
|
## Determinism and skips
|
|
68
67
|
|
|
69
68
|
Stories must use fixed inputs and no live data, network, wall-clock timers, or
|
|
70
|
-
unseeded randomness. Add an unavoidable
|
|
71
|
-
`
|
|
72
|
-
|
|
73
|
-
are not allowed.
|
|
69
|
+
unseeded randomness. Add an unavoidable skip to `deterministicStorySkips` in
|
|
70
|
+
`visual-tests/visual-matrix.ts` with a specific reason. Skips are reported in
|
|
71
|
+
the runner summary; silent conditional skips are not allowed.
|
|
74
72
|
|
|
75
73
|
## CI
|
|
76
74
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moldable-ai/ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.31",
|
|
4
4
|
"description": "Shared UI components for Moldable applications",
|
|
5
5
|
"author": "Desiderata LLC",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -31,6 +31,17 @@
|
|
|
31
31
|
"import": "./dist/catalog/index.js",
|
|
32
32
|
"require": "./dist/catalog/index.js"
|
|
33
33
|
},
|
|
34
|
+
"./tokens": {
|
|
35
|
+
"types": "./dist/tokens/index.d.ts",
|
|
36
|
+
"import": "./dist/tokens/index.js",
|
|
37
|
+
"require": "./dist/tokens/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./tokens/macos-27": "./src/tokens/macos-27/index.css",
|
|
40
|
+
"./platforms/macos-27": "./src/tokens/macos-27/index.css",
|
|
41
|
+
"./platforms/macos-27/source": "./src/tokens/macos-27/source.css",
|
|
42
|
+
"./tokens/macos-26": "./src/tokens/macos-26/index.css",
|
|
43
|
+
"./platforms/macos-26": "./src/tokens/macos-26/index.css",
|
|
44
|
+
"./platforms/macos-26/source": "./src/tokens/macos-26/source.css",
|
|
34
45
|
"./styles": "./src/styles/index.css"
|
|
35
46
|
},
|
|
36
47
|
"files": [
|
|
@@ -39,6 +50,7 @@
|
|
|
39
50
|
"src/components/ui/*.md",
|
|
40
51
|
"src/lib/*.md",
|
|
41
52
|
"src/styles",
|
|
53
|
+
"src/tokens",
|
|
42
54
|
"LICENSE"
|
|
43
55
|
],
|
|
44
56
|
"scripts": {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Accordion
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
`Accordion` organizes related sections into independently expandable items. Use
|
|
6
|
+
it when several peer sections should share one disclosure pattern; use
|
|
7
|
+
`Collapsible` for a single disclosed region.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import {
|
|
13
|
+
Accordion,
|
|
14
|
+
AccordionContent,
|
|
15
|
+
AccordionItem,
|
|
16
|
+
AccordionTrigger,
|
|
17
|
+
} from '@moldable-ai/ui'
|
|
18
|
+
|
|
19
|
+
;<Accordion type="single" collapsible>
|
|
20
|
+
<AccordionItem value="storage">
|
|
21
|
+
<AccordionTrigger>Storage</AccordionTrigger>
|
|
22
|
+
<AccordionContent>
|
|
23
|
+
Files remain in the current Moldable workspace.
|
|
24
|
+
</AccordionContent>
|
|
25
|
+
</AccordionItem>
|
|
26
|
+
</Accordion>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## API
|
|
30
|
+
|
|
31
|
+
- `Accordion` exposes the Radix root props, including `type="single"` or
|
|
32
|
+
`type="multiple"`, controlled state, and orientation.
|
|
33
|
+
- `AccordionItem` requires the Radix item `value` and adds a dividing border.
|
|
34
|
+
- `AccordionTrigger` renders a full-width trigger with a state-aware chevron.
|
|
35
|
+
- `AccordionContent` provides the open and close animation. Its `className`
|
|
36
|
+
styles the inner content wrapper; remaining props apply to the Radix content
|
|
37
|
+
element.
|
|
38
|
+
- Radix manages trigger relationships, expanded state, and keyboard behavior.
|
|
39
|
+
|
|
40
|
+
## Quality bar
|
|
41
|
+
|
|
42
|
+
- Keep trigger labels short and make each section understandable when closed.
|
|
43
|
+
- Choose single or multiple expansion based on the task, not visual density.
|
|
44
|
+
- Do not put another interactive control inside a trigger.
|
|
45
|
+
- Do not hide required validation errors or the only primary action in a closed
|
|
46
|
+
item.
|
|
@@ -11,8 +11,15 @@ Use `AlertDialog` when the user must confirm an action. Use `Empty` for the norm
|
|
|
11
11
|
## Usage patterns
|
|
12
12
|
|
|
13
13
|
```tsx
|
|
14
|
-
import { CircleAlert } from 'lucide-react'
|
|
15
|
-
import {
|
|
14
|
+
import { CircleAlert, InfoIcon } from 'lucide-react'
|
|
15
|
+
import {
|
|
16
|
+
Alert,
|
|
17
|
+
AlertActions,
|
|
18
|
+
AlertDescription,
|
|
19
|
+
AlertDismiss,
|
|
20
|
+
AlertTitle,
|
|
21
|
+
Button,
|
|
22
|
+
} from '@moldable-ai/ui'
|
|
16
23
|
|
|
17
24
|
;<Alert tone="danger">
|
|
18
25
|
<CircleAlert />
|
|
@@ -40,8 +47,9 @@ owned by the caller:
|
|
|
40
47
|
|
|
41
48
|
## API summary
|
|
42
49
|
|
|
43
|
-
- `tone`: `neutral`, `info`, `success`, `warning`, or `danger
|
|
44
|
-
|
|
50
|
+
- `tone`: `neutral`, `info`, `success`, `warning`, or `danger`; defaults to
|
|
51
|
+
`neutral`.
|
|
52
|
+
- `density`: `compact` or `default`; defaults to `default`.
|
|
45
53
|
- Neutral through warning tones default to `role="status"`; danger defaults to
|
|
46
54
|
`role="alert"`. The native `role` prop can override that choice.
|
|
47
55
|
- `variant="default"` and `variant="destructive"` remain compatibility aliases.
|
|
@@ -4,7 +4,7 @@ The top-level shell for an app that can run in its own window or inside a host
|
|
|
4
4
|
surface.
|
|
5
5
|
|
|
6
6
|
```tsx
|
|
7
|
-
<AppFrame>
|
|
7
|
+
<AppFrame nativeMaterial={{ background: true, sidebar: true }}>
|
|
8
8
|
<Toolbar position="top">
|
|
9
9
|
<ToolbarTitle>Today</ToolbarTitle>
|
|
10
10
|
<ToolbarActions>{/* compact actions */}</ToolbarActions>
|
|
@@ -29,8 +29,11 @@ surface.
|
|
|
29
29
|
- `AppFrameContent` applies the shared chat-safe padding by default. The value is
|
|
30
30
|
zero in a standalone window and is updated by the embedded host lifecycle.
|
|
31
31
|
- Use `mode="embedded"` or `mode="window"` only for deterministic previews and
|
|
32
|
-
tests. Runtime apps should normally use `mode="auto"`;
|
|
33
|
-
|
|
34
|
-
app iframe.
|
|
32
|
+
tests. Runtime apps should normally use `mode="auto"`; the host may set
|
|
33
|
+
`data-moldable-display-mode` when a window still uses an app iframe.
|
|
35
34
|
- Material samples only renderer content. Native behind-window material remains
|
|
36
|
-
host-owned.
|
|
35
|
+
host-owned. `nativeMaterial={{ background: true }}` reveals the host's
|
|
36
|
+
frosted full-window material, while `nativeMaterial={{ sidebar: true }}`
|
|
37
|
+
allows a compatible sidebar to declare its region. Declare each matching
|
|
38
|
+
`window.nativeMaterial` option in `moldable.json`. Every option defaults off,
|
|
39
|
+
and portable semantic fills remain in unsupported environments.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# AspectRatio
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
`AspectRatio` reserves a stable rectangular area for media whose width and
|
|
6
|
+
height should scale together. Use it for previews, thumbnails, video, and other
|
|
7
|
+
content where layout shift would be distracting.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { AspectRatio } from '@moldable-ai/ui'
|
|
13
|
+
|
|
14
|
+
;<AspectRatio ratio={16 / 9} className="rounded-control overflow-hidden">
|
|
15
|
+
<img
|
|
16
|
+
src={previewUrl}
|
|
17
|
+
alt="Workspace preview"
|
|
18
|
+
className="size-full object-cover"
|
|
19
|
+
/>
|
|
20
|
+
</AspectRatio>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## API
|
|
24
|
+
|
|
25
|
+
- Accepts the Radix aspect-ratio root props.
|
|
26
|
+
- `ratio` is the desired width divided by height, such as `16 / 9` or `1`.
|
|
27
|
+
- The component adds `data-slot="aspect-ratio"` and otherwise leaves content
|
|
28
|
+
rendering to the caller.
|
|
29
|
+
|
|
30
|
+
## Quality bar
|
|
31
|
+
|
|
32
|
+
- Set an explicit ratio that matches the expected media.
|
|
33
|
+
- Give images useful alternative text, or an empty `alt` when decorative.
|
|
34
|
+
- Choose `object-cover` or `object-contain` deliberately; the component does
|
|
35
|
+
not crop or fit its child.
|
|
36
|
+
- Do not use an aspect ratio wrapper when the content must determine its own
|
|
37
|
+
height.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Avatar
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
`Avatar` presents a person, account, or other recognizable identity in a
|
|
6
|
+
compact circular frame. It includes image, fallback, badge, and overlapping
|
|
7
|
+
group primitives.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import {
|
|
13
|
+
Avatar,
|
|
14
|
+
AvatarFallback,
|
|
15
|
+
AvatarGroup,
|
|
16
|
+
AvatarGroupCount,
|
|
17
|
+
AvatarImage,
|
|
18
|
+
} from '@moldable-ai/ui'
|
|
19
|
+
|
|
20
|
+
;<AvatarGroup>
|
|
21
|
+
<Avatar size="sm">
|
|
22
|
+
<AvatarImage src={owner.photoUrl} alt={owner.name} />
|
|
23
|
+
<AvatarFallback>RM</AvatarFallback>
|
|
24
|
+
</Avatar>
|
|
25
|
+
<AvatarGroupCount>+3</AvatarGroupCount>
|
|
26
|
+
</AvatarGroup>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## API
|
|
30
|
+
|
|
31
|
+
- `Avatar`: Radix root props plus `size="sm"`, `"default"`, or `"lg"`;
|
|
32
|
+
defaults to `default`.
|
|
33
|
+
- `AvatarImage`: Radix image props.
|
|
34
|
+
- `AvatarFallback`: Radix fallback props, including delayed fallback behavior.
|
|
35
|
+
- `AvatarBadge`: native `span` props for a compact corner marker.
|
|
36
|
+
- `AvatarGroup` and `AvatarGroupCount`: native `div` props for an overlapping
|
|
37
|
+
group and its remaining count.
|
|
38
|
+
|
|
39
|
+
## Quality bar
|
|
40
|
+
|
|
41
|
+
- Provide a stable fallback, usually initials or a short recognizable mark.
|
|
42
|
+
- Use meaningful image `alt` text, or empty `alt` when adjacent text already
|
|
43
|
+
names the same identity.
|
|
44
|
+
- Keep one size across an avatar group.
|
|
45
|
+
- Give a badge additional accessible context when its color or icon conveys
|
|
46
|
+
status.
|
|
47
|
+
- Do not use an avatar as an unlabeled action; wrap it in the appropriate
|
|
48
|
+
button or link when interactive.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Breadcrumb
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
`Breadcrumb` shows the current location within a hierarchy and lets users
|
|
6
|
+
return to ancestor levels. Use it for nested app content, not as a substitute
|
|
7
|
+
for browser history or primary navigation.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import {
|
|
13
|
+
Breadcrumb,
|
|
14
|
+
BreadcrumbItem,
|
|
15
|
+
BreadcrumbLink,
|
|
16
|
+
BreadcrumbList,
|
|
17
|
+
BreadcrumbPage,
|
|
18
|
+
BreadcrumbSeparator,
|
|
19
|
+
} from '@moldable-ai/ui'
|
|
20
|
+
|
|
21
|
+
;<Breadcrumb>
|
|
22
|
+
<BreadcrumbList>
|
|
23
|
+
<BreadcrumbItem>
|
|
24
|
+
<BreadcrumbLink href="/projects">Projects</BreadcrumbLink>
|
|
25
|
+
</BreadcrumbItem>
|
|
26
|
+
<BreadcrumbSeparator />
|
|
27
|
+
<BreadcrumbItem>
|
|
28
|
+
<BreadcrumbPage>Launch plan</BreadcrumbPage>
|
|
29
|
+
</BreadcrumbItem>
|
|
30
|
+
</BreadcrumbList>
|
|
31
|
+
</Breadcrumb>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## API
|
|
35
|
+
|
|
36
|
+
- `Breadcrumb` renders a `nav` with `aria-label="breadcrumb"`.
|
|
37
|
+
- `BreadcrumbList` and `BreadcrumbItem` render an `ol` and `li`.
|
|
38
|
+
- `BreadcrumbLink` renders an anchor; `asChild` applies its behavior to a
|
|
39
|
+
caller-provided link component.
|
|
40
|
+
- `BreadcrumbPage` marks the current page with `aria-current="page"` and
|
|
41
|
+
disabled link semantics.
|
|
42
|
+
- `BreadcrumbSeparator` is hidden from assistive technology and uses a right
|
|
43
|
+
chevron unless children are provided.
|
|
44
|
+
- `BreadcrumbEllipsis` renders a presentation-only overflow marker.
|
|
45
|
+
|
|
46
|
+
## Quality bar
|
|
47
|
+
|
|
48
|
+
- End with exactly one current page and do not make it navigable.
|
|
49
|
+
- Represent omitted middle levels with `BreadcrumbEllipsis`; keep the root and
|
|
50
|
+
current location visible.
|
|
51
|
+
- Keep labels concise and preserve their hierarchy on narrow layouts.
|
|
52
|
+
- Do not add slash characters in text; use `BreadcrumbSeparator`.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# ButtonGroup
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
`ButtonGroup` joins closely related controls into one compact visual group. Use
|
|
6
|
+
it for adjacent actions or a control assembled from buttons, inputs, and select
|
|
7
|
+
triggers.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { Button, ButtonGroup, ButtonGroupSeparator } from '@moldable-ai/ui'
|
|
13
|
+
|
|
14
|
+
;<ButtonGroup aria-label="Text alignment">
|
|
15
|
+
<Button variant="outline">Left</Button>
|
|
16
|
+
<Button variant="outline">Center</Button>
|
|
17
|
+
<Button variant="outline">Right</Button>
|
|
18
|
+
<ButtonGroupSeparator />
|
|
19
|
+
<Button variant="outline">Justify</Button>
|
|
20
|
+
</ButtonGroup>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## API
|
|
24
|
+
|
|
25
|
+
- `ButtonGroup` accepts native `div` props and
|
|
26
|
+
`orientation="horizontal" | "vertical"`; visual orientation defaults to
|
|
27
|
+
`horizontal`. It renders `role="group"`.
|
|
28
|
+
- Direct children share adjoining corners and borders. Focused children rise
|
|
29
|
+
above neighboring borders.
|
|
30
|
+
- `ButtonGroupText` accepts native `div` props and `asChild`; use it for
|
|
31
|
+
non-interactive text or an icon beside the controls.
|
|
32
|
+
- `ButtonGroupSeparator` accepts `Separator` props and defaults to
|
|
33
|
+
`orientation="vertical"`. Set it to `horizontal` inside a vertical group.
|
|
34
|
+
- `buttonGroupVariants` is exported for composing the group layout.
|
|
35
|
+
|
|
36
|
+
## Quality bar
|
|
37
|
+
|
|
38
|
+
- Add an accessible label when the group’s purpose is not already named.
|
|
39
|
+
- Keep every action independently focusable and labeled.
|
|
40
|
+
- Use semantic button variants and shared controls so theme and density tokens
|
|
41
|
+
remain consistent.
|
|
42
|
+
- Do not group unrelated actions merely to save space.
|
|
43
|
+
- Do not use `ButtonGroupText` for an action.
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
|
-
`Button` starts an immediate action or, with `asChild`, gives button styling
|
|
5
|
+
`Button` starts an immediate action or, with `asChild`, gives button styling to
|
|
6
|
+
another interactive element. Use it for commands such as save, run, refresh,
|
|
7
|
+
connect, archive, and open.
|
|
6
8
|
|
|
7
9
|
Use a link for navigation. Use `Toggle` when the control represents an on/off view state, and `ToggleGroup` when the user chooses among a small set of modes.
|
|
8
10
|
|
|
@@ -31,7 +33,13 @@ import { RefreshCw } from 'lucide-react'
|
|
|
31
33
|
</Button>
|
|
32
34
|
```
|
|
33
35
|
|
|
34
|
-
Keep toolbar actions compact (`xs`, `sm`, `icon-xs`, or
|
|
36
|
+
Keep ordinary pane-toolbar actions compact (`xs`, `sm`, `icon-xs`, or
|
|
37
|
+
`icon-sm`). In an app-owned native titlebar, use the 36px controls provided by
|
|
38
|
+
`ToolbarButton` and `ToolbarIconButton`. Reserve `default` or `lg` for the
|
|
39
|
+
primary action in a form, setup state, or focused control dock. Set `loading`
|
|
40
|
+
while that button's async action is in flight. The button blocks pointer and
|
|
41
|
+
keyboard activation, exposes `aria-busy`, keeps its accessible label mounted,
|
|
42
|
+
and centers a width-stable spinner.
|
|
35
43
|
|
|
36
44
|
Use `loading` for the action that started the request. Disable the whole form only when editing during the request would be unsafe or would invalidate the submitted payload; do not disable unrelated controls merely to communicate progress.
|
|
37
45
|
|
|
@@ -45,8 +53,16 @@ For links that should look like buttons:
|
|
|
45
53
|
|
|
46
54
|
## API summary
|
|
47
55
|
|
|
48
|
-
- `variant`: `default`, `
|
|
49
|
-
|
|
56
|
+
- `variant`: `default`, `prominent`, `bordered`, `borderless`, `tinted`,
|
|
57
|
+
`toolbar`, `destructive`, `destructive-tinted`, `outline`, `secondary`,
|
|
58
|
+
`ghost`, or `link`. Defaults to `default`; `default` and `prominent` share
|
|
59
|
+
the prominent recipe. Prefer the toolbar-control wrappers instead of
|
|
60
|
+
applying `toolbar` directly.
|
|
61
|
+
- `size`: `default`, `xs`, `sm`, `lg`, `xl`, `mini`, `small`, `medium`,
|
|
62
|
+
`large`, `icon`, `icon-xs`, `icon-sm`, `icon-lg`, or `icon-xl`. Defaults to
|
|
63
|
+
`default`.
|
|
64
|
+
- `controlSize`: overrides the platform control-size token resolved from
|
|
65
|
+
`size`; accepts `mini`, `small`, `medium`, `large`, or `xl`.
|
|
50
66
|
- `asChild`: renders a Radix `Slot` so the child owns the element and semantics.
|
|
51
67
|
- `loading`: blocks activation, applies disabled behavior and `aria-busy`, and overlays the shared `Spinner` without unmounting or resizing the label. Defaults to `false`.
|
|
52
68
|
- Accepts native button props, including `type`, `disabled`, `aria-*`, and event handlers.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Calendar
|
|
2
|
+
|
|
3
|
+
An always-visible `react-day-picker` calendar for single dates, ranges,
|
|
4
|
+
multiple dates, and custom month layouts. Use `DatePicker` when the calendar
|
|
5
|
+
should open from a compact date-only field.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Calendar } from '@moldable-ai/ui'
|
|
9
|
+
|
|
10
|
+
;<Calendar
|
|
11
|
+
aria-label="Choose a due date"
|
|
12
|
+
mode="single"
|
|
13
|
+
selected={date}
|
|
14
|
+
onSelect={setDate}
|
|
15
|
+
disabled={{ before: new Date() }}
|
|
16
|
+
/>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## API
|
|
20
|
+
|
|
21
|
+
- Accepts the current `DayPicker` props, including `mode`, `selected`,
|
|
22
|
+
`onSelect`, `month`, `locale`, `disabled`, and `showWeekNumber`.
|
|
23
|
+
- `showOutsideDays` defaults to `true`.
|
|
24
|
+
- `captionLayout` defaults to `label`.
|
|
25
|
+
- `buttonVariant` sets the shared `Button` variant used by previous and next
|
|
26
|
+
month controls; it defaults to `ghost`.
|
|
27
|
+
- `formatters` and `components` extend or replace the wrapper defaults. The
|
|
28
|
+
default month-dropdown formatter uses abbreviated month names.
|
|
29
|
+
- `className` styles the root. Entries in `classNames` replace the
|
|
30
|
+
corresponding wrapper class entry.
|
|
31
|
+
- `CalendarDayButton` is exported for advanced `DayPicker` composition; the
|
|
32
|
+
built-in calendar already installs it.
|
|
33
|
+
|
|
34
|
+
## Keyboard and quality
|
|
35
|
+
|
|
36
|
+
Day buttons use native button activation. Arrow keys move by day or week;
|
|
37
|
+
Shift+Left/Right moves by month, Shift+Up/Down by year, Page Up/Down by month,
|
|
38
|
+
Shift+Page Up/Down by year, and Home/End to the week boundary.
|
|
39
|
+
|
|
40
|
+
Provide a visible label or accessible name, pass the intended locale, and keep
|
|
41
|
+
disabled dates explainable outside the grid. Store a date-only selection
|
|
42
|
+
without converting it through UTC unless the domain is truly time-based.
|