@threadlabs/looma 0.36.0 → 0.37.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/components/shared/icons.js +3 -0
- package/components/ui-avatar/ui-avatar.html +1 -1
- package/components/ui-avatar-group/ui-avatar-group.html +1 -1
- package/components/ui-button/ui-button.html +3 -12
- package/components/ui-card/ui-card.html +5 -5
- package/components/ui-checkbox/ui-checkbox.html +0 -6
- package/components/ui-color-picker/ui-color-picker.html +0 -9
- package/components/ui-combobox/ui-combobox.html +1 -13
- package/components/ui-cycle-button/ui-cycle-button.html +41 -0
- package/components/ui-cycle-button/ui-cycle-button.js +19 -0
- package/components/ui-dialog/ui-dialog.html +1 -1
- package/components/ui-icon/ui-icon.html +3 -0
- package/components/ui-icon-button/ui-icon-button.html +10 -14
- package/components/ui-input/ui-input.html +1 -16
- package/components/ui-input-group/ui-input-group.html +0 -10
- package/components/ui-menu/ui-menu.html +1 -1
- package/components/ui-popover/ui-popover.html +1 -1
- package/components/ui-radio/ui-radio.html +0 -6
- package/components/ui-select/ui-select.html +2 -8
- package/components/ui-switch/ui-switch.html +0 -6
- package/components/ui-tooltip/ui-tooltip.html +1 -1
- package/dist/index.js +47 -46
- package/docs/README.md +47 -8
- package/docs/card.html +2 -1
- package/docs/catalog.json +214 -39
- package/docs/customizer-render.mjs +8 -7
- package/docs/customizer.js +39 -21
- package/docs/theme.mjs +6 -5
- package/docs/value-editors.mjs +4 -3
- package/editor/icons.d.ts +3 -0
- package/editor/index.js +4 -1
- package/package.json +2 -2
- package/styles/ui-avatar-group.css +1 -1
- package/styles/ui-avatar.css +1 -1
- package/styles/ui-button.css +2 -14
- package/styles/ui-card.css +1 -1
- package/styles/ui-checkbox.css +0 -9
- package/styles/ui-color-picker.css +0 -13
- package/styles/ui-combobox.css +2 -28
- package/styles/ui-cycle-button.css +36 -0
- package/styles/ui-dialog.css +2 -2
- package/styles/ui-icon-button.css +6 -13
- package/styles/ui-input-group.css +0 -13
- package/styles/ui-input.css +2 -18
- package/styles/ui-menu.css +1 -1
- package/styles/ui-popover.css +1 -1
- package/styles/ui-radio.css +0 -9
- package/styles/ui-select.css +3 -10
- package/styles/ui-switch.css +0 -9
- package/styles/ui-tooltip.css +1 -1
- package/theme-system.css +19 -18
- package/tokens.css +20 -25
- package/vanilla/UiCycleButton.d.ts +29 -0
- package/vanilla/UiCycleButton.js +85 -0
- package/vanilla/UiIcon.js +1 -1
- package/vanilla/index.js +1 -0
- package/vue/UiAvatar.vue +1 -1
- package/vue/UiAvatarGroup.vue +1 -1
- package/vue/UiButton.vue +2 -11
- package/vue/UiCard.vue +5 -3
- package/vue/UiCheckbox.vue +0 -6
- package/vue/UiColorPicker.vue +0 -9
- package/vue/UiCombobox.vue +2 -26
- package/vue/UiCycleButton.d.ts +69 -0
- package/vue/UiCycleButton.js +2 -0
- package/vue/UiCycleButton.vue +403 -0
- package/vue/UiDialog.vue +6 -2
- package/vue/UiIcon.vue +22 -0
- package/vue/UiIconButton.vue +2 -16
- package/vue/UiInput.vue +1 -22
- package/vue/UiInputGroup.vue +0 -10
- package/vue/UiMenu.vue +3 -1
- package/vue/UiPopover.vue +3 -1
- package/vue/UiRadio.vue +0 -6
- package/vue/UiSelect.vue +2 -8
- package/vue/UiSwitch.vue +0 -6
- package/vue/UiTooltip.vue +3 -1
- package/vue/chunks/UiAffordanceScope.js +1 -1
- package/vue/chunks/UiAvatar.js +2 -2
- package/vue/chunks/UiAvatarGroup.js +2 -2
- package/vue/chunks/UiBadge.js +1 -1
- package/vue/chunks/UiBreadcrumbItem.js +1 -1
- package/vue/chunks/UiBreadcrumbs.js +1 -1
- package/vue/chunks/UiButton.js +3 -3
- package/vue/chunks/UiCallout.js +1 -1
- package/vue/chunks/UiCard.js +4 -4
- package/vue/chunks/UiCheckbox.js +2 -2
- package/vue/chunks/UiCluster.js +1 -1
- package/vue/chunks/UiColorPicker.js +2 -2
- package/vue/chunks/UiCombobox.js +2 -2
- package/vue/chunks/UiContainer.js +1 -1
- package/vue/chunks/UiContextMenu.js +1 -1
- package/vue/chunks/UiCover.js +1 -1
- package/vue/chunks/UiCurveEditor.js +1 -1
- package/vue/chunks/UiCycleButton.js +352 -0
- package/vue/chunks/UiDescriptionItem.js +1 -1
- package/vue/chunks/UiDescriptionList.js +1 -1
- package/vue/chunks/UiDialog.js +2 -2
- package/vue/chunks/UiDisclosure.js +1 -1
- package/vue/chunks/UiEditable.js +1 -1
- package/vue/chunks/UiEditorBlockActions.js +1 -1
- package/vue/chunks/UiEditorChipEditor.js +1 -1
- package/vue/chunks/UiEditorCodeLanguage.js +1 -1
- package/vue/chunks/UiEditorFootnoteEditor.js +1 -1
- package/vue/chunks/UiEditorImageToolbar.js +1 -1
- package/vue/chunks/UiEditorInsertTableGrid.js +1 -1
- package/vue/chunks/UiEditorLinkCard.js +1 -1
- package/vue/chunks/UiEditorLinkForm.js +1 -1
- package/vue/chunks/UiEditorMentionMenu.js +1 -1
- package/vue/chunks/UiEditorMentionMenuItem.js +1 -1
- package/vue/chunks/UiEditorSlashMenu.js +1 -1
- package/vue/chunks/UiEditorSlashMenuGroup.js +1 -1
- package/vue/chunks/UiEditorSlashMenuItem.js +1 -1
- package/vue/chunks/UiEditorSurface.js +1 -1
- package/vue/chunks/UiEditorTableContextMenu.js +1 -1
- package/vue/chunks/UiEditorTableOverlay.js +1 -1
- package/vue/chunks/UiEditorTableToolbar.js +1 -1
- package/vue/chunks/UiEditorToolbar.js +1 -1
- package/vue/chunks/UiFloatingActionButton.js +1 -1
- package/vue/chunks/UiFormField.js +1 -1
- package/vue/chunks/UiGrid.js +1 -1
- package/vue/chunks/UiIcon.js +70 -2
- package/vue/chunks/UiIconButton.js +4 -4
- package/vue/chunks/UiImage.js +1 -1
- package/vue/chunks/UiInput.js +2 -2
- package/vue/chunks/UiInputGroup.js +2 -2
- package/vue/chunks/UiLightEditor.js +1 -1
- package/vue/chunks/UiList.js +1 -1
- package/vue/chunks/UiListItem.js +1 -1
- package/vue/chunks/UiListbox.js +1 -1
- package/vue/chunks/UiMenu.js +2 -2
- package/vue/chunks/UiMenuGroup.js +1 -1
- package/vue/chunks/UiMenuItem.js +1 -1
- package/vue/chunks/UiMeter.js +1 -1
- package/vue/chunks/UiNavItem.js +1 -1
- package/vue/chunks/UiNumberInput.js +1 -1
- package/vue/chunks/UiPageHeader.js +1 -1
- package/vue/chunks/UiPopover.js +2 -2
- package/vue/chunks/UiRadio.js +2 -2
- package/vue/chunks/UiRadioGroup.js +1 -1
- package/vue/chunks/UiReel.js +1 -1
- package/vue/chunks/UiScrollArea.js +1 -1
- package/vue/chunks/UiSearchResultRow.js +1 -1
- package/vue/chunks/UiSearchShell.js +1 -1
- package/vue/chunks/UiSection.js +1 -1
- package/vue/chunks/UiSelect.js +2 -2
- package/vue/chunks/UiSeparator.js +1 -1
- package/vue/chunks/UiSidebar.js +1 -1
- package/vue/chunks/UiSlider.js +1 -1
- package/vue/chunks/UiSpinner.js +1 -1
- package/vue/chunks/UiStack.js +1 -1
- package/vue/chunks/UiStatusMessage.js +1 -1
- package/vue/chunks/UiSwatch.js +1 -1
- package/vue/chunks/UiSwitch.js +2 -2
- package/vue/chunks/UiSwitcher.js +1 -1
- package/vue/chunks/UiTable.js +1 -1
- package/vue/chunks/UiTabs.js +1 -1
- package/vue/chunks/UiText.js +1 -1
- package/vue/chunks/UiTextarea.js +1 -1
- package/vue/chunks/UiToast.js +1 -1
- package/vue/chunks/UiToastRegion.js +1 -1
- package/vue/chunks/UiTooltip.js +2 -2
- package/vue/chunks/UiTree.js +1 -1
- package/vue/chunks/UiTreeItem.js +1 -1
- package/vue/chunks/props.js +12 -1
- package/vue/components.css +76 -181
- package/vue/editor/index.js +68 -0
- package/vue/index.d.ts +1 -0
- package/vue/index.js +2 -1
package/docs/README.md
CHANGED
|
@@ -17,7 +17,7 @@ pnpm exec looma-docs init --title "The Fellowship"
|
|
|
17
17
|
pnpm exec looma-docs dev
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Use the tool versions accepted by Looma's optional peer dependencies (Markupress 0.8.
|
|
20
|
+
Use the tool versions accepted by Looma's optional peer dependencies (Markupress 0.8.7 or newer on the supported 0.8 line). Regular component imports do not load the documentation server. Vue and Tiptap remain optional; install them when your own authored documentation mounts the Vue editor.
|
|
21
21
|
|
|
22
22
|
Initialization creates three project-owned files:
|
|
23
23
|
|
|
@@ -38,11 +38,43 @@ pnpm exec looma-docs preview
|
|
|
38
38
|
|
|
39
39
|
`build` produces a static HTMLKit site in the configured output directory. `preview` serves that output without a repository writer. All commands accept `--root`; `dev` and `preview` also accept `--port`.
|
|
40
40
|
|
|
41
|
+
## Name your local design system
|
|
42
|
+
|
|
43
|
+
`looma-docs init --title "Fellowship UI"` sets your site's name. To rename an
|
|
44
|
+
existing local documentation site, edit `title` in `looma.docs.json`; the local
|
|
45
|
+
server rebuilds the header, generated landing page and page titles with that
|
|
46
|
+
name. You do not need to fork Looma or change component imports.
|
|
47
|
+
|
|
48
|
+
You can also supply your logo and navigation:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"title": "Fellowship UI",
|
|
53
|
+
"logo": {
|
|
54
|
+
"light": "/assets/fellowship-light.svg",
|
|
55
|
+
"dark": "/assets/fellowship-dark.svg"
|
|
56
|
+
},
|
|
57
|
+
"nav": [{ "label": "Our application", "href": "https://example.com" }]
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Merge these fields into your existing configuration. Serve the logo URLs from
|
|
62
|
+
your application's public assets, such as `public/assets/`. Leave `logo` unset
|
|
63
|
+
for a text-only brand. To author your own introduction, set `content` to your
|
|
64
|
+
Markdown directory and add its `index.md`; it replaces the generated landing
|
|
65
|
+
page without replacing component reference pages.
|
|
66
|
+
|
|
67
|
+
The site name is yours. Component ownership stays accurate: built-in cards
|
|
68
|
+
still identify `@threadlabs/looma`, while your discovered components identify
|
|
69
|
+
the `packageName` you configure below. That is package attribution, not the
|
|
70
|
+
name of your design system. Shared CSS and recipe filenames are configured
|
|
71
|
+
under `theme`; changing a site title does not require renaming those files.
|
|
72
|
+
|
|
41
73
|
## Change the rule, keep the family consistent
|
|
42
74
|
|
|
43
75
|
The authoring model groups shared decisions as Colour, Type, Size & spacing, Material and Motion. The controls expose shared intent: control roominess relative to text, spacing, corners, inner and outer depth, and response pace.
|
|
44
76
|
|
|
45
|
-
The generated values follow rules. The medium control height is base text size times control roominess; small and large heights follow the size ratio.
|
|
77
|
+
The generated values follow rules. The medium control height is base text size times control roominess; small and large heights follow the size ratio. Touch does not inflate the visible size ladder. Hit-area guidance is contextual and adjustable; 44px is a comfort preference for expanded targets, not a mandatory visible height. Invisible targets must not steal neighbouring controls. Spacing derives from base text independently of control roominess and follows its own curve: linear at 1, increasingly curved toward 2, with stable endpoints so the largest gaps do not grow without bound. Depth generates families of shadows; it does not add motion amplitude. Fields and buttons with the same size setting use the same box height, while content can still grow when it needs more room.
|
|
46
78
|
|
|
47
79
|
Choose a coordinated palette, then refine surface warmth, color intensity and palette relationship. Warmth runs from cool to warm paper and ink, with 0.5 neutral; intensity runs from quiet to vivid, with 0.5 retaining original seed intensity. Tonal keeps seed hues; neighboring and complementary relate quiet hues to the action hue. These decisions regenerate paired light/dark colors through Oklab/OKLCH operations, gamut repair and readability checks. They do not transform existing CSS colors live. Four color seeds remain available for precise edits; the light/dark range previews and resolved values explain adjustments.
|
|
48
80
|
|
|
@@ -56,7 +88,7 @@ Number controls accept arithmetic such as `1rem / 1.2` or `150ms * 2`, calculate
|
|
|
56
88
|
|
|
57
89
|
Lengths retain their CSS units, such as `rem`; times retain `ms` or `s`. The downloaded CSS includes the canonical shared CSS derivation rules as well as resolved theme values. Download JSON separately to retain editable decisions and font/preset provenance. Import a downloaded JSON recipe to continue editing it. Keep hand-written CSS in a separate overrides file so regenerating the theme does not replace it.
|
|
58
90
|
|
|
59
|
-
Undo and Redo move through accepted recipe changes.
|
|
91
|
+
Undo and Redo move through accepted recipe changes. There is no page-entry comparison state: reopening the customizer does not create a hidden before/after reference. **Explore nearby styles** previews Warmer, Quieter, More expressive or More compact before you apply it. Palette, Material and Type & spacing locks preserve those families during variations. Cancel preview returns to the current recipe.
|
|
60
92
|
|
|
61
93
|
Changes apply throughout the documentation and remain in this browser across navigation and reload until reset. Repository files change only when you save locally. Starting points update the shell and all selected cards. Reset returns to the repository baseline. Invalid input keeps the last valid preview and explains which decision needs attention.
|
|
62
94
|
|
|
@@ -76,9 +108,9 @@ The [public token reference](https://github.com/threadlabs-studio/looma/blob/mai
|
|
|
76
108
|
| Finish and illumination | `finish` → `--ui-finish`; `edge-light` → `--ui-edge-light`; `glow` → `--ui-glow`; `light-x` → `--ui-light-x`; `light-y` → `--ui-light-y`; `light-spread` → `--ui-light-spread`; `light-strength` → `--ui-light-strength` |
|
|
77
109
|
| Motion | `response-time` → `--ui-motion-fast`; `response-curve` → `--ui-motion-ease` |
|
|
78
110
|
|
|
79
|
-
Palette generation decisions exist only in the JSON recipe; edit it and regenerate to change resolved colors. Geometry, material and motion properties feed the included CSS recipe. `--ui-control-size` remains a derived public height role: author numeric roominess (default 2.5, range 2–4) instead of an absolute control size. Spacing (default 1, range 0.75–1.5) changes space without changing heights. Base text defaults to `1rem
|
|
111
|
+
Palette generation decisions exist only in the JSON recipe; edit it and regenerate to change resolved colors. Geometry, material and motion properties feed the included CSS recipe. `--ui-control-size` remains a derived public height role: author numeric roominess (default 2.5, range 2–4) instead of an absolute control size. Spacing (default 1, range 0.75–1.5) changes space without changing heights. Base text defaults to `16px` and sets the document root. Type and geometry derive from `1rem` once; the base editor accepts only px. Other relative length inputs preserve their units; editor ranges convert through the chosen root, and generated guards keep the documented pixel bounds. Visible size samples report actual rem/px heights. Set the base on `:root`; opposite-mode boundaries retain that same rem root.
|
|
80
112
|
|
|
81
|
-
Before 1.0 there are no compatibility aliases. Migrate recipe `density` to `spacing` and CSS `--ui-density` to `--ui-spacing`. Replace length-valued recipe `control-size` with numeric `control-roominess` by dividing the desired medium height by base text size: `40px / 16px` becomes `2.5`.
|
|
113
|
+
Before 1.0 there are no compatibility aliases. Migrate recipe `density` to `spacing` and CSS `--ui-density` to `--ui-spacing`. Replace length-valued recipe `control-size` with numeric `control-roominess` by dividing the desired medium height by base text size: `40px / 16px` becomes `2.5`. Base `text-size` is now px-only and sets the document root. Replace older relative base values with an explicit px value using their original root; no compatibility conversion guesses it.
|
|
82
114
|
|
|
83
115
|
## Choose fonts
|
|
84
116
|
|
|
@@ -90,7 +122,7 @@ An optional recipe `fonts` mapping records Google family names by `body-font` an
|
|
|
90
122
|
|
|
91
123
|
Light position is relative to each surface: horizontal and vertical positions run from 0 to 1, with 0.5, 0 at top centre. Drag the source, use its arrow keys (Shift moves faster), or enter exact percentages. Home returns it to top centre. Spread runs from a concentrated spot to broad illumination; strength controls its intensity. The source influences reflections, illuminated edges and the direction of depth shadows throughout the theme.
|
|
92
124
|
|
|
93
|
-
Depth controls elevation and recession independently from finish, transmission and motion. Finish controls how strongly a material catches a reflection, from matte to polished; it needs nonzero light strength. Light spread shapes that reflection, while position also directs shadows. A light strength of zero does not remove depth shadows. Edge light catches its boundary; glow spills
|
|
125
|
+
Depth controls elevation and recession independently from finish, transmission and motion. Finish controls how strongly a material catches a reflection, from matte to polished; it needs nonzero light strength. Light spread shapes that reflection, while position also directs shadows. A light strength of zero does not remove depth shadows. Edge light catches its boundary; glow spills beyond it. Glassiness and glow use a gently increasing lower range and an expressive upper response (`g + 2g⁴`), so the maximum can be exuberant without raising restrained defaults. Glassiness and surface separation govern the decorative material around floating content, scaled by popup purpose and rendered size. The content plane stays opaque. Overlay translucency changes the shared overlay fill and decorative glass; it does not turn material content transparent. Separation can create a rim even with glassiness at zero. Reflection peaks are bounded for readable text, and reduced transparency disables the ornamental reflection and glow as well as backdrop blur.
|
|
94
126
|
|
|
95
127
|
Card keeps surface structure and decorative treatment independent:
|
|
96
128
|
|
|
@@ -128,9 +160,16 @@ Use the public semantic color properties inside those regions. A floating surfac
|
|
|
128
160
|
|
|
129
161
|
## Add your components
|
|
130
162
|
|
|
131
|
-
Build your design-system components in HTML Next. Their definitions, description attributes,
|
|
163
|
+
Build your design-system components in HTML Next. Their definitions, description attributes, modules and HTML examples are the source for the generated documentation and customizer cards. Use Looma’s public semantic properties to make your components respond to the same theme.
|
|
164
|
+
|
|
165
|
+
1. Create a directory for your HTML Next component resources, such as `app/components`.
|
|
166
|
+
2. Opt that directory into `components` in `looma.docs.json`, with your package's name.
|
|
167
|
+
3. Put `docs.json` and an `examples/` directory beside each resource, as shown below.
|
|
168
|
+
4. Run `looma-docs dev`. Your components appear beside Looma's in the reference,
|
|
169
|
+
search and customizer example picker. Resources under registered directories
|
|
170
|
+
are rediscovered when the local server rebuilds.
|
|
132
171
|
|
|
133
|
-
|
|
172
|
+
The configuration can combine your name, authored guides and discovery roots:
|
|
134
173
|
|
|
135
174
|
```json
|
|
136
175
|
{
|
package/docs/card.html
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
<prop name="title" type="string" default="Example">The documented component name.</prop>
|
|
9
9
|
<prop name="description" type="string" default="">The component's authored description.</prop>
|
|
10
10
|
<prop name="exampleTitle" type="string" default="">The selected authored example.</prop>
|
|
11
|
+
<prop name="previewOnly" type="boolean" default="false">Show only the live example, for compact theme samplers whose host supplies the heading.</prop>
|
|
11
12
|
<prop name="reference" type="boolean" default="false">Use the spacious full-reference example presentation.</prop>
|
|
12
13
|
<prop name="src" type="string" default="">The compiled isolated example page.</prop>
|
|
13
14
|
<prop name="resizable" type="boolean" default="false">Expose a width control for responsive examples.</prop>
|
|
@@ -24,7 +25,7 @@
|
|
|
24
25
|
<div class="preview"><iframe $ref="frame" from:title="$title" from:src="$src" sandbox="allow-scripts" from:loading="$loading" width="100%" height="208"></iframe></div>
|
|
25
26
|
<section $if="$reference" class="example-code"><h4>Code</h4><slot name="code"></slot></section>
|
|
26
27
|
<div $if="$resizable" class="preview-width"> <ui-form-field><label slot="label">Preview width</label><span slot="help">Explore the example at a narrower width.</span><ui-input $ref="width" type="number" min="240" max="1600" value="720" aria-label="Preview width in pixels" size="sm"></ui-input></ui-form-field></div>
|
|
27
|
-
<div $if="not $reference" class="body"><ui-stack gap="xs">
|
|
28
|
+
<div $if="not $reference and not $previewOnly" class="body"><ui-stack gap="xs">
|
|
28
29
|
<div class="meta"><span>{$category}</span><code>{$nativeRoot}</code></div>
|
|
29
30
|
<h3><a from:href="$href">{$title}</a></h3>
|
|
30
31
|
<p class="description">{$description}</p>
|
package/docs/catalog.json
CHANGED
|
@@ -90,6 +90,11 @@
|
|
|
90
90
|
"package": "@threadlabs/looma",
|
|
91
91
|
"resource": "@threadlabs/looma/components/ui-curve-editor/ui-curve-editor.html"
|
|
92
92
|
},
|
|
93
|
+
{
|
|
94
|
+
"tag": "ui-cycle-button",
|
|
95
|
+
"package": "@threadlabs/looma",
|
|
96
|
+
"resource": "@threadlabs/looma/components/ui-cycle-button/ui-cycle-button.html"
|
|
97
|
+
},
|
|
93
98
|
{
|
|
94
99
|
"tag": "ui-description-item",
|
|
95
100
|
"package": "@threadlabs/looma",
|
|
@@ -443,7 +448,7 @@
|
|
|
443
448
|
],
|
|
444
449
|
"schemaVersion": 1,
|
|
445
450
|
"package": "@threadlabs/looma",
|
|
446
|
-
"version": "0.
|
|
451
|
+
"version": "0.37.1",
|
|
447
452
|
"groups": [
|
|
448
453
|
{
|
|
449
454
|
"id": "layout",
|
|
@@ -729,7 +734,7 @@
|
|
|
729
734
|
"name": "--ui-border-width"
|
|
730
735
|
},
|
|
731
736
|
{
|
|
732
|
-
"name": "--ui-font-size"
|
|
737
|
+
"name": "--ui-font-size-md"
|
|
733
738
|
},
|
|
734
739
|
{
|
|
735
740
|
"name": "--ui-font-size-sm"
|
|
@@ -975,7 +980,7 @@
|
|
|
975
980
|
"name": "--ui-border-width"
|
|
976
981
|
},
|
|
977
982
|
{
|
|
978
|
-
"name": "--ui-font-size"
|
|
983
|
+
"name": "--ui-font-size-md"
|
|
979
984
|
},
|
|
980
985
|
{
|
|
981
986
|
"name": "--ui-font-size-xs"
|
|
@@ -2529,7 +2534,7 @@
|
|
|
2529
2534
|
{
|
|
2530
2535
|
"name": "size",
|
|
2531
2536
|
"property": "size",
|
|
2532
|
-
"description": "Height, padding, and type size. xs is 1.5rem with the smallest text, for a control inside a line of small text; sm is the small control height (2rem by default) with tighter padding and smaller text, md is the standard control height (2.5rem), and lg is taller (3rem) with roomier padding.
|
|
2537
|
+
"description": "Height, padding, and type size. xs is 1.5rem with the smallest text, for a control inside a line of small text; sm is the small control height (2rem by default) with tighter padding and smaller text, md is the standard control height (2.5rem), and lg is taller (3rem) with roomier padding. Visible sizes stay the same on touch. Inline xs and link actions can gain an adjustable invisible hit area.",
|
|
2533
2538
|
"type": "keyword",
|
|
2534
2539
|
"default": "md",
|
|
2535
2540
|
"options": [
|
|
@@ -2670,7 +2675,7 @@
|
|
|
2670
2675
|
},
|
|
2671
2676
|
{
|
|
2672
2677
|
"name": "size",
|
|
2673
|
-
"description": "Height, padding, and type size. xs is 1.5rem with the smallest text, for a control inside a line of small text; sm is the small control height (2rem by default) with tighter padding and smaller text, md is the standard control height (2.5rem), and lg is taller (3rem) with roomier padding.
|
|
2678
|
+
"description": "Height, padding, and type size. xs is 1.5rem with the smallest text, for a control inside a line of small text; sm is the small control height (2rem by default) with tighter padding and smaller text, md is the standard control height (2.5rem), and lg is taller (3rem) with roomier padding. Visible sizes stay the same on touch. Inline xs and link actions can gain an adjustable invisible hit area.",
|
|
2674
2679
|
"type": "\"xs\" | \"sm\" | \"md\" | \"lg\"",
|
|
2675
2680
|
"default": "md",
|
|
2676
2681
|
"options": [
|
|
@@ -3543,9 +3548,6 @@
|
|
|
3543
3548
|
{
|
|
3544
3549
|
"name": "--ui-control-inset"
|
|
3545
3550
|
},
|
|
3546
|
-
{
|
|
3547
|
-
"name": "--ui-control-min-block-size"
|
|
3548
|
-
},
|
|
3549
3551
|
{
|
|
3550
3552
|
"name": "--ui-control-size-lg"
|
|
3551
3553
|
},
|
|
@@ -4167,6 +4169,16 @@
|
|
|
4167
4169
|
"resizable": false,
|
|
4168
4170
|
"bindings": "",
|
|
4169
4171
|
"frameworks": {}
|
|
4172
|
+
},
|
|
4173
|
+
{
|
|
4174
|
+
"id": "@threadlabs/looma/ui-cluster/99-theme-sampler",
|
|
4175
|
+
"name": "99-theme-sampler",
|
|
4176
|
+
"title": "Theme sampler",
|
|
4177
|
+
"description": "A compact collection of real controls and a surface for judging a shared theme together.",
|
|
4178
|
+
"markup": "<ui-card treatment=\"expressive\" padding=\"sm\"><ui-stack gap=\"xs\">\n <ui-cluster gap=\"xs\" justify=\"between\"><ui-text variant=\"eyebrow\">Fellowship office</ui-text><ui-badge tone=\"success\">Ready</ui-badge></ui-cluster>\n <ui-cluster gap=\"xs\"><ui-button size=\"sm\" preset=\"primary\">Send memo</ui-button><ui-button size=\"sm\" preset=\"standard\">Save draft</ui-button><ui-button\n size=\"sm\"\n variant=\"outline\"\n >Archive</ui-button><ui-cycle-button\n id=\"sampler-availability\"\n size=\"sm\"\n label=\"Availability\"\n items='[{\"value\":\"available\",\"label\":\"Available\",\"icon\":\"circle-check\"},{\"value\":\"busy\",\"label\":\"Busy\",\"icon\":\"circle-dot\"},{\"value\":\"away\",\"label\":\"Away\",\"icon\":\"moon\"}]'\n ></ui-cycle-button></ui-cluster>\n <ui-input-group><ui-icon slot=\"prefix\" name=\"search\"></ui-icon><ui-input\n size=\"sm\"\n aria-label=\"Search office\"\n placeholder=\"Search Fellowship office\"\n ></ui-input></ui-input-group>\n <ui-cluster gap=\"xs\"><ui-checkbox size=\"sm\" checked>Notify Sam</ui-checkbox><ui-switch size=\"sm\" checked>Available</ui-switch><ui-badge tone=\"accent\"\n >Draft</ui-badge></ui-cluster>\n </ui-stack></ui-card>",
|
|
4179
|
+
"resizable": false,
|
|
4180
|
+
"bindings": "items=availabilityStates",
|
|
4181
|
+
"frameworks": {}
|
|
4170
4182
|
}
|
|
4171
4183
|
]
|
|
4172
4184
|
},
|
|
@@ -4217,9 +4229,6 @@
|
|
|
4217
4229
|
"var(--ui-space-1)"
|
|
4218
4230
|
]
|
|
4219
4231
|
},
|
|
4220
|
-
{
|
|
4221
|
-
"name": "--ui-control-min-block-size"
|
|
4222
|
-
},
|
|
4223
4232
|
{
|
|
4224
4233
|
"name": "--ui-control-size-lg"
|
|
4225
4234
|
},
|
|
@@ -4487,9 +4496,7 @@
|
|
|
4487
4496
|
"declarations": [
|
|
4488
4497
|
"var(--ui-control-size-md)",
|
|
4489
4498
|
"var(--ui-control-size-sm)",
|
|
4490
|
-
"var(--ui-control-size-lg)"
|
|
4491
|
-
"max(var(--ui-control-size-md), var(--ui-control-min-block-size))",
|
|
4492
|
-
"max(var(--ui-control-size-sm), var(--ui-control-min-block-size))"
|
|
4499
|
+
"var(--ui-control-size-lg)"
|
|
4493
4500
|
]
|
|
4494
4501
|
},
|
|
4495
4502
|
{
|
|
@@ -4608,9 +4615,6 @@
|
|
|
4608
4615
|
"var(--ui-space-1)"
|
|
4609
4616
|
]
|
|
4610
4617
|
},
|
|
4611
|
-
{
|
|
4612
|
-
"name": "--ui-control-min-block-size"
|
|
4613
|
-
},
|
|
4614
4618
|
{
|
|
4615
4619
|
"name": "--ui-control-size-lg"
|
|
4616
4620
|
},
|
|
@@ -6847,6 +6851,194 @@
|
|
|
6847
6851
|
}
|
|
6848
6852
|
]
|
|
6849
6853
|
},
|
|
6854
|
+
{
|
|
6855
|
+
"tag": "ui-cycle-button",
|
|
6856
|
+
"package": "@threadlabs/looma",
|
|
6857
|
+
"root": "span",
|
|
6858
|
+
"description": "One compact native button that cycles an ordered set of named icon states without moving focus.",
|
|
6859
|
+
"designTokens": {
|
|
6860
|
+
"sources": [
|
|
6861
|
+
"packages/looma/src/components/ui-cycle-button/ui-cycle-button.html"
|
|
6862
|
+
],
|
|
6863
|
+
"component": [],
|
|
6864
|
+
"shared": []
|
|
6865
|
+
},
|
|
6866
|
+
"attributes": [
|
|
6867
|
+
{
|
|
6868
|
+
"name": "disabled",
|
|
6869
|
+
"property": "disabled",
|
|
6870
|
+
"description": "Prevents cycling while keeping the selected state visible.",
|
|
6871
|
+
"type": "boolean",
|
|
6872
|
+
"default": false
|
|
6873
|
+
},
|
|
6874
|
+
{
|
|
6875
|
+
"name": "index",
|
|
6876
|
+
"property": "index",
|
|
6877
|
+
"description": "Initial or externally selected zero-based state. The first state is the default.",
|
|
6878
|
+
"type": "number",
|
|
6879
|
+
"default": 0
|
|
6880
|
+
},
|
|
6881
|
+
{
|
|
6882
|
+
"name": "items",
|
|
6883
|
+
"property": "items",
|
|
6884
|
+
"description": "Ordered states with a value, readable label and Looma icon name. Activation advances to the next state and wraps.",
|
|
6885
|
+
"type": "list(object)",
|
|
6886
|
+
"fields": [
|
|
6887
|
+
{
|
|
6888
|
+
"path": "[].value",
|
|
6889
|
+
"type": "string",
|
|
6890
|
+
"required": true
|
|
6891
|
+
},
|
|
6892
|
+
{
|
|
6893
|
+
"path": "[].label",
|
|
6894
|
+
"type": "string",
|
|
6895
|
+
"required": true
|
|
6896
|
+
},
|
|
6897
|
+
{
|
|
6898
|
+
"path": "[].icon",
|
|
6899
|
+
"type": "string",
|
|
6900
|
+
"required": true
|
|
6901
|
+
}
|
|
6902
|
+
]
|
|
6903
|
+
},
|
|
6904
|
+
{
|
|
6905
|
+
"name": "label",
|
|
6906
|
+
"property": "label",
|
|
6907
|
+
"description": "What the button changes, such as Appearance. The selected state is included in its accessible name.",
|
|
6908
|
+
"type": "string",
|
|
6909
|
+
"default": "State"
|
|
6910
|
+
},
|
|
6911
|
+
{
|
|
6912
|
+
"name": "size",
|
|
6913
|
+
"property": "size",
|
|
6914
|
+
"description": "Uses IconButton's compact visible sizes and adjustable invisible touch area.",
|
|
6915
|
+
"type": "keyword",
|
|
6916
|
+
"default": "md",
|
|
6917
|
+
"options": [
|
|
6918
|
+
"sm",
|
|
6919
|
+
"md",
|
|
6920
|
+
"lg"
|
|
6921
|
+
]
|
|
6922
|
+
},
|
|
6923
|
+
{
|
|
6924
|
+
"name": "variant",
|
|
6925
|
+
"property": "variant",
|
|
6926
|
+
"description": "Uses IconButton's standard emphasis.",
|
|
6927
|
+
"type": "keyword",
|
|
6928
|
+
"default": "outline",
|
|
6929
|
+
"options": [
|
|
6930
|
+
"ghost",
|
|
6931
|
+
"outline",
|
|
6932
|
+
"solid"
|
|
6933
|
+
]
|
|
6934
|
+
}
|
|
6935
|
+
],
|
|
6936
|
+
"properties": [
|
|
6937
|
+
{
|
|
6938
|
+
"name": "disabled",
|
|
6939
|
+
"description": "Prevents cycling while keeping the selected state visible.",
|
|
6940
|
+
"type": "boolean",
|
|
6941
|
+
"default": false
|
|
6942
|
+
},
|
|
6943
|
+
{
|
|
6944
|
+
"name": "index",
|
|
6945
|
+
"description": "Initial or externally selected zero-based state. The first state is the default.",
|
|
6946
|
+
"type": "number",
|
|
6947
|
+
"default": 0
|
|
6948
|
+
},
|
|
6949
|
+
{
|
|
6950
|
+
"name": "items",
|
|
6951
|
+
"description": "Ordered states with a value, readable label and Looma icon name. Activation advances to the next state and wraps.",
|
|
6952
|
+
"type": "readonly ({ readonly value: string; readonly label: string; readonly icon: string })[]",
|
|
6953
|
+
"fields": [
|
|
6954
|
+
{
|
|
6955
|
+
"path": "[].value",
|
|
6956
|
+
"type": "string",
|
|
6957
|
+
"required": true
|
|
6958
|
+
},
|
|
6959
|
+
{
|
|
6960
|
+
"path": "[].label",
|
|
6961
|
+
"type": "string",
|
|
6962
|
+
"required": true
|
|
6963
|
+
},
|
|
6964
|
+
{
|
|
6965
|
+
"path": "[].icon",
|
|
6966
|
+
"type": "string",
|
|
6967
|
+
"required": true
|
|
6968
|
+
}
|
|
6969
|
+
]
|
|
6970
|
+
},
|
|
6971
|
+
{
|
|
6972
|
+
"name": "label",
|
|
6973
|
+
"description": "What the button changes, such as Appearance. The selected state is included in its accessible name.",
|
|
6974
|
+
"type": "string",
|
|
6975
|
+
"default": "State"
|
|
6976
|
+
},
|
|
6977
|
+
{
|
|
6978
|
+
"name": "size",
|
|
6979
|
+
"description": "Uses IconButton's compact visible sizes and adjustable invisible touch area.",
|
|
6980
|
+
"type": "\"sm\" | \"md\" | \"lg\"",
|
|
6981
|
+
"default": "md",
|
|
6982
|
+
"options": [
|
|
6983
|
+
"sm",
|
|
6984
|
+
"md",
|
|
6985
|
+
"lg"
|
|
6986
|
+
]
|
|
6987
|
+
},
|
|
6988
|
+
{
|
|
6989
|
+
"name": "variant",
|
|
6990
|
+
"description": "Uses IconButton's standard emphasis.",
|
|
6991
|
+
"type": "\"ghost\" | \"outline\" | \"solid\"",
|
|
6992
|
+
"default": "outline",
|
|
6993
|
+
"options": [
|
|
6994
|
+
"ghost",
|
|
6995
|
+
"outline",
|
|
6996
|
+
"solid"
|
|
6997
|
+
]
|
|
6998
|
+
}
|
|
6999
|
+
],
|
|
7000
|
+
"events": [
|
|
7001
|
+
{
|
|
7002
|
+
"name": "change",
|
|
7003
|
+
"detailType": "{ readonly value: string; readonly index: number }",
|
|
7004
|
+
"detailSchema": "object",
|
|
7005
|
+
"fields": [
|
|
7006
|
+
{
|
|
7007
|
+
"path": "value",
|
|
7008
|
+
"type": "string",
|
|
7009
|
+
"required": true
|
|
7010
|
+
},
|
|
7011
|
+
{
|
|
7012
|
+
"path": "index",
|
|
7013
|
+
"type": "number",
|
|
7014
|
+
"required": true
|
|
7015
|
+
}
|
|
7016
|
+
],
|
|
7017
|
+
"detailDocs": "Emitted when a toggleable control changes checked state."
|
|
7018
|
+
}
|
|
7019
|
+
],
|
|
7020
|
+
"slots": [],
|
|
7021
|
+
"group": "forms",
|
|
7022
|
+
"id": "@threadlabs/looma/ui-cycle-button",
|
|
7023
|
+
"title": "Cycle Button",
|
|
7024
|
+
"resource": "@threadlabs/looma/components/ui-cycle-button/ui-cycle-button.html",
|
|
7025
|
+
"targets": [
|
|
7026
|
+
"html-next",
|
|
7027
|
+
"vue"
|
|
7028
|
+
],
|
|
7029
|
+
"examples": [
|
|
7030
|
+
{
|
|
7031
|
+
"id": "@threadlabs/looma/ui-cycle-button/01-appearance",
|
|
7032
|
+
"name": "01-appearance",
|
|
7033
|
+
"title": "Cycling appearance",
|
|
7034
|
+
"description": "One native button cycles Automatic, Light and Dark while preserving keyboard focus.",
|
|
7035
|
+
"markup": "<ui-cluster gap=\"s\"><ui-text>Appearance</ui-text><ui-cycle-button\n id=\"appearance-cycle\"\n label=\"Appearance\"\n items='[{\"value\":\"automatic\",\"label\":\"Automatic\",\"icon\":\"monitor\"},{\"value\":\"light\",\"label\":\"Light\",\"icon\":\"sun\"},{\"value\":\"dark\",\"label\":\"Dark\",\"icon\":\"moon\"}]'\n ></ui-cycle-button></ui-cluster>",
|
|
7036
|
+
"resizable": false,
|
|
7037
|
+
"bindings": "items=appearanceStates",
|
|
7038
|
+
"frameworks": {}
|
|
7039
|
+
}
|
|
7040
|
+
]
|
|
7041
|
+
},
|
|
6850
7042
|
{
|
|
6851
7043
|
"tag": "ui-description-item",
|
|
6852
7044
|
"package": "@threadlabs/looma",
|
|
@@ -12790,7 +12982,7 @@
|
|
|
12790
12982
|
{
|
|
12791
12983
|
"name": "match-button",
|
|
12792
12984
|
"property": "matchButton",
|
|
12793
|
-
"description": "Matches a boxed Button of the same size when the two share a flex row. Uses the control-size theme tokens and stretches to the row's height,
|
|
12985
|
+
"description": "Matches a boxed Button of the same size when the two share a flex row. Uses the control-size theme tokens and stretches to the row's height, on mouse and touch alike. Leave it off for compact toolbar and inline icon buttons.",
|
|
12794
12986
|
"type": "boolean",
|
|
12795
12987
|
"default": false
|
|
12796
12988
|
},
|
|
@@ -12832,7 +13024,7 @@
|
|
|
12832
13024
|
{
|
|
12833
13025
|
"name": "size",
|
|
12834
13026
|
"property": "size",
|
|
12835
|
-
"description": "Button and icon size together: sm is 1.75rem with a small icon, md is 2rem, and lg is 2.5rem with a large icon.
|
|
13027
|
+
"description": "Button and icon size together: sm is 1.75rem with a small icon, md is 2rem, and lg is 2.5rem with a large icon. Touch can use an invisible hit area sized by the adjustable control target preference.",
|
|
12836
13028
|
"type": "keyword",
|
|
12837
13029
|
"default": "md",
|
|
12838
13030
|
"options": [
|
|
@@ -12906,7 +13098,7 @@
|
|
|
12906
13098
|
},
|
|
12907
13099
|
{
|
|
12908
13100
|
"name": "matchButton",
|
|
12909
|
-
"description": "Matches a boxed Button of the same size when the two share a flex row. Uses the control-size theme tokens and stretches to the row's height,
|
|
13101
|
+
"description": "Matches a boxed Button of the same size when the two share a flex row. Uses the control-size theme tokens and stretches to the row's height, on mouse and touch alike. Leave it off for compact toolbar and inline icon buttons.",
|
|
12910
13102
|
"type": "boolean",
|
|
12911
13103
|
"default": false
|
|
12912
13104
|
},
|
|
@@ -12943,7 +13135,7 @@
|
|
|
12943
13135
|
},
|
|
12944
13136
|
{
|
|
12945
13137
|
"name": "size",
|
|
12946
|
-
"description": "Button and icon size together: sm is 1.75rem with a small icon, md is 2rem, and lg is 2.5rem with a large icon.
|
|
13138
|
+
"description": "Button and icon size together: sm is 1.75rem with a small icon, md is 2rem, and lg is 2.5rem with a large icon. Touch can use an invisible hit area sized by the adjustable control target preference.",
|
|
12947
13139
|
"type": "\"sm\" | \"md\" | \"lg\"",
|
|
12948
13140
|
"default": "md",
|
|
12949
13141
|
"options": [
|
|
@@ -13376,9 +13568,7 @@
|
|
|
13376
13568
|
"fallbacks": [
|
|
13377
13569
|
"var(--ui-control-size-md)",
|
|
13378
13570
|
"var(--ui-control-size-sm)",
|
|
13379
|
-
"var(--ui-control-size-lg)"
|
|
13380
|
-
"max(var(--ui-control-size-md), var(--ui-control-min-block-size))",
|
|
13381
|
-
"max(var(--ui-control-size-sm), var(--ui-control-min-block-size))"
|
|
13571
|
+
"var(--ui-control-size-lg)"
|
|
13382
13572
|
]
|
|
13383
13573
|
},
|
|
13384
13574
|
{
|
|
@@ -13452,9 +13642,6 @@
|
|
|
13452
13642
|
"var(--ui-space-1)"
|
|
13453
13643
|
]
|
|
13454
13644
|
},
|
|
13455
|
-
{
|
|
13456
|
-
"name": "--ui-control-min-block-size"
|
|
13457
|
-
},
|
|
13458
13645
|
{
|
|
13459
13646
|
"name": "--ui-control-placeholder",
|
|
13460
13647
|
"fallbacks": [
|
|
@@ -13822,9 +14009,6 @@
|
|
|
13822
14009
|
{
|
|
13823
14010
|
"name": "--ui-control-inset"
|
|
13824
14011
|
},
|
|
13825
|
-
{
|
|
13826
|
-
"name": "--ui-control-min-block-size"
|
|
13827
|
-
},
|
|
13828
14012
|
{
|
|
13829
14013
|
"name": "--ui-control-size-lg"
|
|
13830
14014
|
},
|
|
@@ -17415,9 +17599,6 @@
|
|
|
17415
17599
|
{
|
|
17416
17600
|
"name": "--ui-choice-mark-size"
|
|
17417
17601
|
},
|
|
17418
|
-
{
|
|
17419
|
-
"name": "--ui-control-min-block-size"
|
|
17420
|
-
},
|
|
17421
17602
|
{
|
|
17422
17603
|
"name": "--ui-control-size-lg"
|
|
17423
17604
|
},
|
|
@@ -19139,9 +19320,6 @@
|
|
|
19139
19320
|
"var(--ui-space-1)"
|
|
19140
19321
|
]
|
|
19141
19322
|
},
|
|
19142
|
-
{
|
|
19143
|
-
"name": "--ui-control-min-block-size"
|
|
19144
|
-
},
|
|
19145
19323
|
{
|
|
19146
19324
|
"name": "--ui-control-size-lg"
|
|
19147
19325
|
},
|
|
@@ -20767,9 +20945,6 @@
|
|
|
20767
20945
|
{
|
|
20768
20946
|
"name": "--ui-control-inset"
|
|
20769
20947
|
},
|
|
20770
|
-
{
|
|
20771
|
-
"name": "--ui-control-min-block-size"
|
|
20772
|
-
},
|
|
20773
20948
|
{
|
|
20774
20949
|
"name": "--ui-control-size-lg"
|
|
20775
20950
|
},
|
|
@@ -11,12 +11,12 @@ export function customizerResource(site, input = defaultRecipe()) {
|
|
|
11
11
|
const toCard = example => Object.fromEntries(cardFields.map(key => [key, example[key]]));
|
|
12
12
|
const initial = ['ui-button', 'ui-input', 'ui-color-picker', 'ui-checkbox', 'ui-card', 'ui-switch', 'ui-text', 'ui-dialog', 'ui-popover'].map(tag => examples.find(example => example.tag === tag && (tag !== 'ui-button' || example.id.endsWith('/02-variant')) && (tag !== 'ui-text' || example.id.endsWith('/02-variants')) && (tag !== 'ui-card' || example.id.endsWith('/04-expressive-surface'))) ?? examples.find(example => example.tag === tag)).filter(Boolean).map(toCard);
|
|
13
13
|
if (!initial.length && examples.length) initial.push(toCard(examples[0]));
|
|
14
|
-
const documentationCard = (tag, suffix) => {
|
|
14
|
+
const documentationCard = (tag, suffix, previewOnly = false) => {
|
|
15
15
|
const example = examples.find(item => item.tag === tag && (!suffix || item.id.endsWith(suffix))) ?? examples.find(item => item.tag === tag);
|
|
16
|
-
return example ? `<looma-example-card ${cardFields.filter(key => key !== 'id').map(key => `${key.replace(/[A-Z]/g, letter => '-' + letter.toLowerCase())}="${escape(String(example[key]))}"`).join(' ')} identity="${escape(example.id)}" loading="lazy"></looma-example-card>` : '';
|
|
16
|
+
return example ? `<looma-example-card ${previewOnly ? 'preview-only' : ''} ${cardFields.filter(key => key !== 'id').map(key => `${key.replace(/[A-Z]/g, letter => '-' + letter.toLowerCase())}="${escape(String(example[key]))}"`).join(' ')} identity="${escape(example.id)}" loading="lazy"></looma-example-card>` : '';
|
|
17
17
|
};
|
|
18
18
|
const renderField = field => {
|
|
19
|
-
const value = recipe.values[field.id], editor = valueEditor(field, value);
|
|
19
|
+
const value = recipe.values[field.id], editor = valueEditor(field, value, { remPixels: parseFloat(recipe.values['text-size']) });
|
|
20
20
|
const common = `size="sm" data-token="${field.id}" label="${escape(field.label)}"`;
|
|
21
21
|
let control;
|
|
22
22
|
if (field.type === 'font') {
|
|
@@ -45,7 +45,7 @@ export function customizerResource(site, input = defaultRecipe()) {
|
|
|
45
45
|
'Colour': `${renderPreset('palette', 'overview')}<ui-text variant="caption">Coordinated light and dark ranges.</ui-text><ui-button data-action="refine-palette">Refine palette</ui-button>`,
|
|
46
46
|
'Material': `${renderPreset('material', 'overview')}<ui-text variant="caption">Material and light, shared everywhere.</ui-text><ui-button data-action="refine-material">Refine material & light</ui-button>`,
|
|
47
47
|
'Motion': `<ui-text variant="caption">Open and close this real documentation example to feel the response pace and curve. Reduced motion follows your system preference.</ui-text>${documentationCard('ui-popover')}`,
|
|
48
|
-
'Size & spacing': `<ui-text variant="caption">Shared size ladder: buttons, fields and swatches align at each step
|
|
48
|
+
'Size & spacing': `<ui-text variant="caption">Shared size ladder: buttons, fields and swatches align at each step.</ui-text><ui-stack>${['sm','md','lg'].map((size,index) => `<ui-stack gap="xs" data-size-sample="${size}"><ui-text variant="caption">${['Small','Medium','Large'][index]}<span data-size-readout></span></ui-text><ui-cluster><ui-button size="${size}">Action</ui-button><ui-input size="${size}" style="--ui-input-inline-size: 10ch" label="${size} size sample" value="Frodo"></ui-input><ui-color-picker size="${size}" label="${size} swatch sample"></ui-color-picker></ui-cluster></ui-stack>`).join('')}</ui-stack><div class="spacing-samples" data-spacing-samples role="img" aria-label="Spacing progression"><span></span><span></span><span></span><span></span></div><ui-disclosure summary="How the scale grows"><ui-stack><p>Control roominess relates every field and button to base text. Size ratio separates small from large. Visible proportions stay the same on touch; hit areas are a separate design choice. Spacing and its curve shape page rhythm independently.</p>${themeFields.filter(item => ['scale-contrast','space-curve'].includes(item.id)).map(renderField).join('')}</ui-stack></ui-disclosure>`,
|
|
49
49
|
};
|
|
50
50
|
const families = [...new Set(themeFields.map(field => field.family))].filter(family => !['Colour', 'Material'].includes(family)).map(family => `<ui-disclosure summary="${family}"><ui-stack>${themeFields.filter(item => item.family === family && !['scale-contrast', 'space-curve'].includes(item.id)).map(renderField).join('')}${supplements[family] ?? ''}</ui-stack></ui-disclosure>`).join('');
|
|
51
51
|
const refinement = (family, content) => `<section data-refinement-view="${family}" hidden tabindex="-1" aria-label="${family === 'material' ? 'Material and light refinement' : 'Palette refinement'}"><ui-stack gap="xl"><ui-cluster justify="between"><ui-button data-action="back">Back to customization</ui-button><ui-button data-action="restore-${family}">Restore ${family} preset</ui-button></ui-cluster><ui-text variant="heading" as="h2">${family === 'material' ? 'Refine material & light' : 'Refine your palette'}</ui-text><p>These are advanced refinements of the same persistent theme. Every change applies throughout your documentation.</p>${renderPreset(family, 'refinement')}${content}</ui-stack></section>`;
|
|
@@ -59,7 +59,7 @@ export function customizerResource(site, input = defaultRecipe()) {
|
|
|
59
59
|
<div data-looma-customizer data-recipe="${escape(JSON.stringify(recipe))}" data-base="${escape(site.base)}" data-mode="${site.config.local ? 'local' : 'public'}" data-revision="${escape(site.config.revision ?? '')}">
|
|
60
60
|
<ui-stack gap="l"><ui-text>Choose a starting point, refine shared decisions, and see them on real documentation examples.</ui-text>
|
|
61
61
|
<ui-text variant="caption" role="status" aria-live="polite" data-message>Changes are remembered across the documentation.</ui-text>
|
|
62
|
-
<ui-cluster><ui-text variant="label" data-theme-origin></ui-text><ui-button size="sm" data-action="undo" disabled>Undo</ui-button><ui-button size="sm" data-action="redo" disabled>Redo</ui-button
|
|
62
|
+
<ui-cluster><ui-text variant="label" data-theme-origin></ui-text><ui-button size="sm" data-action="undo" disabled>Undo</ui-button><ui-button size="sm" data-action="redo" disabled>Redo</ui-button></ui-cluster>
|
|
63
63
|
<ui-disclosure summary="Explore nearby styles"><ui-stack><ui-text variant="caption">Preview a small change before applying it. Locks preserve your selected families.</ui-text><ui-cluster>${[['palette','Palette'],['material','Material'],['type','Type & spacing']].map(([id,label]) => `<ui-checkbox size="sm" data-family-lock="${id}">Lock ${label}</ui-checkbox>`).join('')}</ui-cluster><ui-form-field><label slot="label" for="nearby-style">Nearby style</label><ui-select id="nearby-style" data-variation-choice>${Object.entries(themeVariations).map(([id,label]) => `<option value="${id}">${label}</option>`).join('')}</ui-select></ui-form-field><ui-button data-action="preview-variation">Preview variation</ui-button><div data-variation-confirm hidden><ui-stack><ui-text data-variation-description role="status"></ui-text><ui-cluster><ui-button preset="primary" data-action="apply-variation">Apply variation</ui-button><ui-button data-action="cancel-variation">Cancel preview</ui-button></ui-cluster></ui-stack></div></ui-stack></ui-disclosure>
|
|
64
64
|
${materialView}${paletteView}
|
|
65
65
|
<div class="customizer-layout" data-customizer-overview>
|
|
@@ -73,6 +73,7 @@ export function customizerResource(site, input = defaultRecipe()) {
|
|
|
73
73
|
<ui-disclosure summary="Use your theme"><p>Every export includes light and dark. Leave data-theme off the page to follow system preference, or set it to light or dark on the page or a section. <a href="${escape(site.base)}design-system/">Installation and mode guidance</a></p></ui-disclosure>
|
|
74
74
|
<ui-disclosure summary="Theme CSS"><ui-textarea data-css readonly rows="12" aria-label="Generated theme CSS" value="${escape(themeCSS(recipe))}"></ui-textarea></ui-disclosure></ui-stack></ui-disclosure>
|
|
75
75
|
</ui-stack></aside>
|
|
76
|
+
<section data-theme-sampler><ui-stack gap="xs"><ui-text variant="heading" as="h2">Theme sampler</ui-text>${documentationCard('ui-cluster', '/99-theme-sampler', true)}</ui-stack></section>
|
|
76
77
|
<section class="examples"><ui-stack><ui-form-field><label slot="label" for="example-query">Filter previews</label><ui-input id="example-query" type="search" data-example-query placeholder="Name, tag or purpose"></ui-input></ui-form-field><ui-text variant="caption" role="status" aria-live="polite" data-example-count></ui-text><ui-disclosure summary="Add an example"><ui-stack><ui-combobox id="example-choice" data-add-example label="Choose a component example" placeholder="Search buttons, fields, dialogs…" disclosure clearable>${options}</ui-combobox><ui-button data-action="add" disabled>Add to preview</ui-button></ui-stack></ui-disclosure>
|
|
77
78
|
<ui-grid columns="2" min="sm"><section $each="card of $cards" $key="$card.id"><looma-example-card ${cardFields.filter(name => name !== 'id').map(name => `from:${name.replace(/[A-Z]/g, letter => '-' + letter.toLowerCase())}="$card.${name}"`).join(' ')} from:identity="$card.id" loading="eager" removable></looma-example-card></section></ui-grid>
|
|
78
79
|
<noscript>Enable JavaScript to edit the theme. The component reference and example previews remain available.</noscript>
|
|
@@ -80,7 +81,7 @@ export function customizerResource(site, input = defaultRecipe()) {
|
|
|
80
81
|
<style>
|
|
81
82
|
[data-customizer-overview][hidden], [data-refinement-view][hidden], [data-variation-confirm][hidden] { display: none !important; }
|
|
82
83
|
.customizer-layout { display: grid !important; grid-template-columns: minmax(16rem, 20rem) minmax(0, 1fr); gap: var(--ui-space-6) !important; align-items: start !important; }
|
|
83
|
-
aside { position: sticky; inset-block-start: 5rem; max-block-size: calc(100dvh - 6rem); overflow: auto; padding
|
|
84
|
+
aside { grid-row: 1 / span 2; position: sticky; inset-block-start: 5rem; max-block-size: calc(100dvh - 6rem); overflow: auto; padding: max(var(--ui-space-2), calc(var(--ui-focus-width) * 2)) !important; scroll-padding: max(var(--ui-space-2), calc(var(--ui-focus-width) * 2)); }
|
|
84
85
|
.examples { min-inline-size: 0; }
|
|
85
86
|
.refinement-layout { display: grid !important; grid-template-columns: minmax(0, 1.2fr) minmax(16rem, 1fr); gap: var(--ui-space-6) !important; align-items: start !important; }
|
|
86
87
|
[data-refinement-view] { scroll-margin-block-start: 5rem; }
|
|
@@ -94,6 +95,6 @@ export function customizerResource(site, input = defaultRecipe()) {
|
|
|
94
95
|
.palette-canvas { background: var(--ui-surface); }
|
|
95
96
|
.palette-content { background: var(--ui-surface-raised); }
|
|
96
97
|
.palette-action { background: var(--ui-accent); }
|
|
97
|
-
@media (max-width: 64rem) { .customizer-layout, .refinement-layout { grid-template-columns: minmax(0, 1fr); } aside { position: static; max-block-size: none; } }
|
|
98
|
+
@media (max-width: 64rem) { .customizer-layout, .refinement-layout { grid-template-columns: minmax(0, 1fr); } aside { grid-row: auto; order: 2; position: static; max-block-size: none; } [data-theme-sampler] { order: 1; } .examples { order: 3; } }
|
|
98
99
|
</style></template>`;
|
|
99
100
|
}
|