@threadlabs/looma 0.17.0 → 0.17.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/ui-avatar-group/ui-avatar-group.html +8 -5
- package/components/ui-avatar-group/ui-avatar-group.js +3 -3
- package/components/ui-badge/ui-badge.html +10 -5
- package/components/ui-breadcrumb-item/ui-breadcrumb-item.html +2 -1
- package/components/ui-button/ui-button.html +33 -26
- package/components/ui-button/ui-button.js +2 -2
- package/components/ui-callout/ui-callout.html +3 -1
- package/components/ui-card/ui-card.html +5 -3
- package/components/ui-checkbox/ui-checkbox.html +36 -8
- package/components/ui-combobox/ui-combobox.html +72 -45
- package/components/ui-combobox/ui-combobox.js +7 -2
- package/components/ui-context-menu/ui-context-menu.html +2 -2
- package/components/ui-description-item/ui-description-item.html +1 -1
- package/components/ui-description-list/ui-description-list.html +2 -0
- package/components/ui-dialog/ui-dialog.html +3 -23
- package/components/ui-disclosure/ui-disclosure.html +2 -2
- package/components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.html +2 -2
- package/components/ui-editor-mention-menu/ui-editor-mention-menu.html +3 -3
- package/components/ui-editor-slash-menu/ui-editor-slash-menu.html +4 -4
- package/components/ui-editor-slash-menu-item/ui-editor-slash-menu-item.html +6 -1
- package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +2 -2
- package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +4 -4
- package/components/ui-editor-toolbar/ui-editor-toolbar.html +5 -5
- package/components/ui-floating-action-button/ui-floating-action-button.html +4 -2
- package/components/ui-icon-button/ui-icon-button.html +57 -17
- package/components/ui-icon-button/ui-icon-button.js +1 -1
- package/components/ui-list/ui-list.html +46 -6
- package/components/ui-list-item/ui-list-item.html +1 -1
- package/components/ui-menu/ui-menu.html +4 -3
- package/components/ui-menu/ui-menu.js +9 -3
- package/components/ui-menu-item/ui-menu-item.html +43 -6
- package/components/ui-meter/ui-meter.html +4 -1
- package/components/ui-nav-item/ui-nav-item.html +0 -1
- package/components/ui-page-header/ui-page-header.html +1 -0
- package/components/ui-popover/ui-popover.html +1 -1
- package/components/ui-radio/ui-radio.html +5 -2
- package/components/ui-scroll-area/ui-scroll-area.html +9 -14
- package/components/ui-scroll-area/ui-scroll-area.js +32 -0
- package/components/ui-search-result-row/ui-search-result-row.html +5 -3
- package/components/ui-search-shell/ui-search-shell.html +8 -8
- package/components/ui-section/ui-section.html +5 -3
- package/components/ui-separator/ui-separator.html +2 -2
- package/components/ui-sidebar/ui-sidebar.html +2 -2
- package/components/ui-spinner/ui-spinner.html +28 -8
- package/components/ui-status-message/ui-status-message.html +1 -1
- package/components/ui-switch/ui-switch.html +17 -8
- package/components/ui-table/ui-table.html +1 -1
- package/components/ui-tabs/ui-tabs.html +21 -12
- package/components/ui-toast/ui-toast.html +1 -1
- package/components/ui-toast-region/ui-toast-region.html +1 -1
- package/components/ui-tooltip/ui-tooltip.html +12 -12
- package/components/ui-tooltip/ui-tooltip.js +1 -1
- package/components/ui-top-bar/ui-top-bar.html +1 -1
- package/components/ui-tree/ui-tree.js +4 -1
- package/components/ui-tree-item/ui-tree-item.html +2 -1
- package/dist/index.js +15 -14
- package/package.json +1 -1
- package/styles/ui-avatar-group.css +8 -5
- package/styles/ui-badge.css +10 -5
- package/styles/ui-breadcrumb-item.css +2 -1
- package/styles/ui-button.css +19 -25
- package/styles/ui-callout.css +3 -1
- package/styles/ui-card.css +4 -2
- package/styles/ui-checkbox.css +38 -8
- package/styles/ui-combobox.css +27 -8
- package/styles/ui-context-menu.css +2 -2
- package/styles/ui-description-item.css +1 -1
- package/styles/ui-description-list.css +2 -0
- package/styles/ui-dialog.css +1 -22
- package/styles/ui-disclosure.css +2 -2
- package/styles/ui-editor-insert-table-grid.css +2 -2
- package/styles/ui-editor-mention-menu.css +3 -3
- package/styles/ui-editor-slash-menu-item.css +6 -1
- package/styles/ui-editor-slash-menu.css +4 -4
- package/styles/ui-editor-table-context-menu.css +2 -2
- package/styles/ui-editor-table-toolbar.css +4 -4
- package/styles/ui-editor-toolbar.css +5 -5
- package/styles/ui-floating-action-button.css +3 -1
- package/styles/ui-icon-button.css +53 -18
- package/styles/ui-list-item.css +1 -1
- package/styles/ui-list.css +41 -6
- package/styles/ui-menu-item.css +43 -5
- package/styles/ui-menu.css +3 -3
- package/styles/ui-meter.css +4 -1
- package/styles/ui-nav-item.css +0 -1
- package/styles/ui-page-header.css +1 -0
- package/styles/ui-popover.css +1 -1
- package/styles/ui-radio.css +5 -2
- package/styles/ui-scroll-area.css +10 -16
- package/styles/ui-search-result-row.css +3 -2
- package/styles/ui-search-shell.css +7 -7
- package/styles/ui-section.css +5 -3
- package/styles/ui-separator.css +2 -2
- package/styles/ui-sidebar.css +2 -2
- package/styles/ui-spinner.css +27 -6
- package/styles/ui-status-message.css +1 -1
- package/styles/ui-switch.css +17 -8
- package/styles/ui-table.css +1 -1
- package/styles/ui-tabs.css +60 -51
- package/styles/ui-toast-region.css +1 -1
- package/styles/ui-toast.css +1 -1
- package/styles/ui-tooltip.css +12 -12
- package/styles/ui-top-bar.css +1 -1
- package/styles/ui-tree-item.css +2 -1
- package/theme-dark.css +4 -4
- package/theme-light.css +3 -3
- package/tokens.css +9 -6
- package/vanilla/UiButton.d.ts +1 -0
- package/vanilla/UiButton.js +17 -19
- package/vanilla/UiCombobox.js +162 -159
- package/vanilla/UiDialog.js +2 -2
- package/vanilla/UiIconButton.d.ts +1 -0
- package/vanilla/UiIconButton.js +1 -4
- package/vanilla/UiList.d.ts +3 -1
- package/vanilla/UiList.js +36 -19
- package/vanilla/UiMenu.d.ts +1 -0
- package/vanilla/UiMenu.js +1 -1
- package/vanilla/UiMenuItem.js +10 -13
- package/vanilla/UiScrollArea.js +11 -6
- package/vanilla/UiSearchShell.js +2 -2
- package/vanilla/UiSpinner.js +2 -4
- package/vue/UiAvatarGroup.vue +8 -5
- package/vue/UiBadge.vue +10 -5
- package/vue/UiBreadcrumbItem.vue +2 -1
- package/vue/UiButton.d.ts +2 -0
- package/vue/UiButton.vue +31 -28
- package/vue/UiCallout.vue +3 -2
- package/vue/UiCard.vue +4 -2
- package/vue/UiCheckbox.vue +36 -8
- package/vue/UiCombobox.d.ts +1 -1
- package/vue/UiCombobox.vue +55 -35
- package/vue/UiContextMenu.vue +2 -2
- package/vue/UiDescriptionItem.vue +1 -1
- package/vue/UiDescriptionList.vue +2 -0
- package/vue/UiDialog.d.ts +3 -3
- package/vue/UiDialog.vue +3 -27
- package/vue/UiDisclosure.vue +2 -2
- package/vue/UiEditorInsertTableGrid.vue +2 -2
- package/vue/UiEditorMentionMenu.d.ts +1 -1
- package/vue/UiEditorMentionMenu.vue +4 -3
- package/vue/UiEditorSlashMenu.vue +6 -4
- package/vue/UiEditorSlashMenuItem.vue +6 -1
- package/vue/UiEditorTableContextMenu.vue +2 -2
- package/vue/UiEditorTableToolbar.vue +4 -4
- package/vue/UiEditorToolbar.vue +5 -5
- package/vue/UiFloatingActionButton.vue +3 -1
- package/vue/UiIconButton.d.ts +2 -0
- package/vue/UiIconButton.vue +61 -19
- package/vue/UiList.d.ts +7 -1
- package/vue/UiList.vue +57 -6
- package/vue/UiListItem.vue +1 -1
- package/vue/UiMenu.d.ts +2 -0
- package/vue/UiMenu.vue +6 -3
- package/vue/UiMenuItem.d.ts +3 -3
- package/vue/UiMenuItem.vue +47 -7
- package/vue/UiMeter.vue +4 -1
- package/vue/UiNavItem.vue +0 -1
- package/vue/UiPageHeader.vue +1 -0
- package/vue/UiPopover.vue +1 -1
- package/vue/UiRadio.vue +5 -2
- package/vue/UiScrollArea.vue +24 -18
- package/vue/UiSearchResultRow.vue +3 -2
- package/vue/UiSearchShell.vue +8 -8
- package/vue/UiSection.vue +5 -3
- package/vue/UiSeparator.vue +2 -2
- package/vue/UiSidebar.vue +2 -2
- package/vue/UiSpinner.vue +28 -7
- package/vue/UiStatusMessage.vue +1 -1
- package/vue/UiSwitch.vue +20 -9
- package/vue/UiTable.vue +1 -1
- package/vue/UiTabs.vue +25 -12
- package/vue/UiToast.vue +1 -1
- package/vue/UiToastRegion.vue +1 -1
- package/vue/UiTooltip.vue +12 -12
- package/vue/UiTopBar.vue +1 -1
- package/vue/UiTreeItem.vue +2 -1
- package/vue/chunks/UiAvatarGroup.js +1 -1
- package/vue/chunks/UiBadge.js +1 -1
- package/vue/chunks/UiBreadcrumbItem.js +1 -1
- package/vue/chunks/UiButton.js +28 -23
- package/vue/chunks/UiCallout.js +1 -1
- package/vue/chunks/UiCard.js +1 -1
- package/vue/chunks/UiCheckbox.js +1 -1
- package/vue/chunks/UiCombobox.js +80 -77
- package/vue/chunks/UiContextMenu.js +1 -1
- package/vue/chunks/UiDescriptionItem.js +1 -1
- package/vue/chunks/UiDescriptionList.js +1 -1
- package/vue/chunks/UiDialog.js +7 -4
- package/vue/chunks/UiDisclosure.js +1 -1
- package/vue/chunks/UiEditorInsertTableGrid.js +1 -1
- package/vue/chunks/UiEditorMentionMenu.js +1 -1
- package/vue/chunks/UiEditorSlashMenu.js +1 -1
- package/vue/chunks/UiEditorSlashMenuItem.js +1 -1
- package/vue/chunks/UiEditorTableContextMenu.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/UiIconButton.js +13 -8
- package/vue/chunks/UiList.js +17 -5
- package/vue/chunks/UiListItem.js +1 -1
- package/vue/chunks/UiMenu.js +10 -2
- package/vue/chunks/UiMenuItem.js +1 -4
- package/vue/chunks/UiMeter.js +1 -1
- package/vue/chunks/UiNavItem.js +1 -1
- package/vue/chunks/UiPageHeader.js +1 -1
- package/vue/chunks/UiPopover.js +1 -1
- package/vue/chunks/UiRadio.js +1 -1
- package/vue/chunks/UiScrollArea.js +22 -3
- package/vue/chunks/UiSearchResultRow.js +1 -1
- package/vue/chunks/UiSearchShell.js +2 -2
- package/vue/chunks/UiSection.js +1 -1
- package/vue/chunks/UiSeparator.js +1 -1
- package/vue/chunks/UiSidebar.js +1 -1
- package/vue/chunks/UiSpinner.js +7 -5
- package/vue/chunks/UiStatusMessage.js +1 -1
- package/vue/chunks/UiSwitch.js +1 -1
- package/vue/chunks/UiTable.js +1 -1
- package/vue/chunks/UiTabs.js +1 -1
- package/vue/chunks/UiToast.js +1 -1
- package/vue/chunks/UiToastRegion.js +1 -1
- package/vue/chunks/UiTooltip.js +1 -1
- package/vue/chunks/UiTopBar.js +1 -1
- package/vue/chunks/UiTreeItem.js +1 -1
- package/vue/components.css +1217 -1032
- package/vue/index.js +1 -1
|
@@ -37,10 +37,9 @@
|
|
|
37
37
|
--_ui-avatar-group-overlap-shadow: var(--ui-avatar-group-overlap-shadow);
|
|
38
38
|
--_ui-avatar-group-edge-ring: var(--ui-avatar-group-edge-ring);
|
|
39
39
|
|
|
40
|
-
/*
|
|
41
|
-
*
|
|
42
|
-
--_overlap-shadow: 0 0 0 0
|
|
43
|
-
--_edge-ring: 0 0 0 2px var(--ui-surface);
|
|
40
|
+
/* A one-pixel shadow on the leading edge separates overlapping circles without cutting
|
|
41
|
+
* a white gap out of the avatar underneath. */
|
|
42
|
+
--_overlap-shadow: -1px 0 0 0 rgb(0 0 0 / 0.22);
|
|
44
43
|
|
|
45
44
|
display: flex;
|
|
46
45
|
align-items: center;
|
|
@@ -59,6 +58,10 @@
|
|
|
59
58
|
margin-inline-start: 0;
|
|
60
59
|
}
|
|
61
60
|
|
|
61
|
+
:host:dir(rtl) {
|
|
62
|
+
--_overlap-shadow: 1px 0 0 0 rgb(0 0 0 / 0.22);
|
|
63
|
+
}
|
|
64
|
+
|
|
62
65
|
.overflow {
|
|
63
66
|
margin-inline-start: -0.5rem;
|
|
64
67
|
display: inline-flex;
|
|
@@ -72,7 +75,7 @@
|
|
|
72
75
|
color: var(--ui-text-primary);
|
|
73
76
|
box-shadow:
|
|
74
77
|
var(--_ui-avatar-group-overlap-shadow, var(--_overlap-shadow)),
|
|
75
|
-
var(--_ui-avatar-group-edge-ring,
|
|
78
|
+
var(--_ui-avatar-group-edge-ring, 0 0 0 0 transparent);
|
|
76
79
|
font: inherit;
|
|
77
80
|
font-size: var(--ui-font-size-xs);
|
|
78
81
|
font-weight: 600;
|
|
@@ -11,10 +11,10 @@ export default function controller(host) {
|
|
|
11
11
|
avatars.forEach((avatar, index) => {
|
|
12
12
|
avatar.style.display = index >= visible ? "none" : "";
|
|
13
13
|
avatar.style.marginInlineStart = index === 0 ? "0px" : overlap;
|
|
14
|
-
// Later avatars
|
|
14
|
+
// Later avatars darken only their leading edge; the first overlaps nothing.
|
|
15
15
|
avatar.style.boxShadow = index === 0
|
|
16
|
-
? "var(--ui-avatar-group-edge-ring,
|
|
17
|
-
: "var(--ui-avatar-group-overlap-shadow, var(--_overlap-shadow)), var(--ui-avatar-group-edge-ring,
|
|
16
|
+
? "var(--ui-avatar-group-edge-ring, none)"
|
|
17
|
+
: "var(--ui-avatar-group-overlap-shadow, var(--_overlap-shadow)), var(--ui-avatar-group-edge-ring, 0 0 0 0 transparent)";
|
|
18
18
|
});
|
|
19
19
|
const authoredVisible = Math.min(avatars.length, visible);
|
|
20
20
|
const suppliedTotal = Number(host.state.total);
|
|
@@ -135,27 +135,32 @@
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
:host-state([variant="subtle"][tone="accent"]) {
|
|
138
|
-
--_badge-surface: var(--ui-accent-
|
|
138
|
+
--_badge-surface: color-mix(in srgb, var(--ui-accent-solid) 22%, var(--ui-surface-default));
|
|
139
|
+
--_badge-border: color-mix(in srgb, var(--ui-accent-solid) 28%, var(--ui-surface-default));
|
|
139
140
|
--_badge-text: var(--ui-accent-subtle-text, var(--ui-accent-solid));
|
|
140
141
|
}
|
|
141
142
|
|
|
142
143
|
:host-state([variant="subtle"][tone="danger"]) {
|
|
143
|
-
--_badge-surface: var(--ui-danger-
|
|
144
|
+
--_badge-surface: color-mix(in srgb, var(--ui-danger-solid) 22%, var(--ui-surface-default));
|
|
145
|
+
--_badge-border: color-mix(in srgb, var(--ui-danger-solid) 28%, var(--ui-surface-default));
|
|
144
146
|
--_badge-text: var(--ui-danger-subtle-text, var(--ui-danger-solid));
|
|
145
147
|
}
|
|
146
148
|
|
|
147
149
|
:host-state([variant="subtle"][tone="success"]) {
|
|
148
|
-
--_badge-surface: var(--ui-success-
|
|
150
|
+
--_badge-surface: color-mix(in srgb, var(--ui-success-solid) 22%, var(--ui-surface-default));
|
|
151
|
+
--_badge-border: color-mix(in srgb, var(--ui-success-solid) 28%, var(--ui-surface-default));
|
|
149
152
|
--_badge-text: var(--ui-success-subtle-text, var(--ui-success-solid));
|
|
150
153
|
}
|
|
151
154
|
|
|
152
155
|
:host-state([variant="subtle"][tone="warning"]) {
|
|
153
|
-
--_badge-surface: var(--ui-warning-
|
|
156
|
+
--_badge-surface: color-mix(in srgb, var(--ui-warning-solid) 22%, var(--ui-surface-default));
|
|
157
|
+
--_badge-border: color-mix(in srgb, var(--ui-warning-solid) 28%, var(--ui-surface-default));
|
|
154
158
|
--_badge-text: var(--ui-warning-subtle-text, var(--ui-warning-solid));
|
|
155
159
|
}
|
|
156
160
|
|
|
157
161
|
:host-state([variant="subtle"][tone="info"]) {
|
|
158
|
-
--_badge-surface: var(--ui-info-
|
|
162
|
+
--_badge-surface: color-mix(in srgb, var(--ui-info-solid) 22%, var(--ui-surface-default));
|
|
163
|
+
--_badge-border: color-mix(in srgb, var(--ui-info-solid) 28%, var(--ui-surface-default));
|
|
159
164
|
--_badge-text: var(--ui-info-subtle-text, var(--ui-info-solid));
|
|
160
165
|
}
|
|
161
166
|
|
|
@@ -15,12 +15,13 @@
|
|
|
15
15
|
align-items: center;
|
|
16
16
|
gap: var(--ui-space-2);
|
|
17
17
|
min-inline-size: 0;
|
|
18
|
+
margin: 0;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
.separator {
|
|
21
22
|
display: inline-flex;
|
|
22
23
|
color: var(--ui-text-muted);
|
|
23
|
-
font-size: var(--ui-font-size-
|
|
24
|
+
font-size: var(--ui-font-size-sm);
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
:host:first-child .separator {
|
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
>Which colour the button speaks in. It applies to every variant, so an outline, a ghost, and a solid in the same tone are the same action at three volumes:
|
|
12
12
|
tone="danger" variant="outline" is a destructive secondary action. neutral is the quiet one, for a button that should not claim a colour.</prop>
|
|
13
13
|
<prop name="disabled" type="boolean" default="false"
|
|
14
|
-
>Makes the button unavailable: it cannot be pressed,
|
|
15
|
-
states aria-disabled="true" instead, because a link has no native disabled state.</prop>
|
|
16
|
-
<prop name="
|
|
14
|
+
>Makes the button unavailable: it cannot be pressed, uses a flat neutral palette, and loses its raised look. A disabled link (as="a" with href) drops its
|
|
15
|
+
href and states aria-disabled="true" instead, because a link has no native disabled state.</prop>
|
|
16
|
+
<prop name="loading" type="boolean" default="false"
|
|
17
17
|
>Keeps the action focusable and its label visible while work is in progress. It shows a decorative spinner, states aria-disabled and aria-busy, and prevents
|
|
18
18
|
activation or form submission until cleared.</prop>
|
|
19
|
+
<prop name="pending" type="boolean" default="false">Deprecated alias for loading.</prop>
|
|
19
20
|
<prop name="align" type="center | start" default="center"
|
|
20
21
|
>Content alignment. start lays the content out like a list option: from the start edge, with start-aligned text.</prop>
|
|
21
22
|
<prop name="stretch" type="boolean" default="false">Fills the inline size of its container.</prop>
|
|
@@ -34,18 +35,24 @@
|
|
|
34
35
|
<template $match>
|
|
35
36
|
<a
|
|
36
37
|
$when="as = 'a'"
|
|
37
|
-
:href="{ true: null, false: href }[format('%s', disabled or pending)]"
|
|
38
|
+
:href="{ true: null, false: href }[format('%s', disabled or loading or pending)]"
|
|
38
39
|
:target="target"
|
|
39
40
|
:rel="rel"
|
|
40
|
-
:aria-disabled="{ true: 'true', false: null }[format('%s', disabled or pending)]"
|
|
41
|
-
:aria-busy="pending"
|
|
42
|
-
:tabindex="{ true: '0', false: null }[format('%s', pending and not disabled)]"
|
|
41
|
+
:aria-disabled="{ true: 'true', false: null }[format('%s', disabled or loading or pending)]"
|
|
42
|
+
:aria-busy="loading or pending"
|
|
43
|
+
:tabindex="{ true: '0', false: null }[format('%s', (loading or pending) and not disabled)]"
|
|
43
44
|
>
|
|
44
|
-
<
|
|
45
|
+
<span $if="loading or pending" class="spinner-wrap"><ui-spinner size="sm"></ui-spinner></span>
|
|
45
46
|
<slot></slot>
|
|
46
47
|
</a>
|
|
47
|
-
<button
|
|
48
|
-
|
|
48
|
+
<button
|
|
49
|
+
$else
|
|
50
|
+
:type="type"
|
|
51
|
+
:disabled="disabled"
|
|
52
|
+
:aria-disabled="{ true: 'true', false: null }[format('%s', loading or pending)]"
|
|
53
|
+
:aria-busy="loading or pending"
|
|
54
|
+
>
|
|
55
|
+
<span $if="loading or pending" class="spinner-wrap"><ui-spinner size="sm"></ui-spinner></span>
|
|
49
56
|
<slot></slot>
|
|
50
57
|
</button>
|
|
51
58
|
</template>
|
|
@@ -177,12 +184,15 @@
|
|
|
177
184
|
background-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
178
185
|
border-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
179
186
|
color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
180
|
-
box-shadow var(--ui-motion-
|
|
187
|
+
box-shadow var(--ui-motion-base) var(--ui-motion-ease);
|
|
181
188
|
margin: 0;
|
|
182
189
|
}
|
|
183
190
|
|
|
184
|
-
.
|
|
191
|
+
.spinner-wrap {
|
|
192
|
+
display: inline-flex;
|
|
193
|
+
flex: none;
|
|
185
194
|
margin-inline-end: var(--ui-space-2);
|
|
195
|
+
vertical-align: middle;
|
|
186
196
|
}
|
|
187
197
|
|
|
188
198
|
@supports (text-box-trim: trim-both) {
|
|
@@ -312,12 +322,12 @@
|
|
|
312
322
|
var(--ui-focus-halo);
|
|
313
323
|
}
|
|
314
324
|
|
|
315
|
-
/*
|
|
316
|
-
disabled
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
325
|
+
/* A loading action stays visually active; only an explicitly disabled action takes the
|
|
326
|
+
neutral disabled palette. Its flat surface and muted ink make the state unambiguous. */
|
|
327
|
+
:host:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])) {
|
|
328
|
+
border-color: var(--ui-disabled-border);
|
|
329
|
+
background-color: var(--ui-disabled-surface);
|
|
330
|
+
color: var(--ui-disabled-text);
|
|
321
331
|
filter: var(--ui-button-disabled-filter, var(--ui-disabled-filter));
|
|
322
332
|
opacity: var(--ui-button-disabled-opacity, 1);
|
|
323
333
|
cursor: not-allowed;
|
|
@@ -325,16 +335,13 @@
|
|
|
325
335
|
box-shadow: none;
|
|
326
336
|
}
|
|
327
337
|
|
|
328
|
-
:host-state([pending]):focus-visible {
|
|
338
|
+
:is(:host-state([loading]), :host-state([pending])):focus-visible {
|
|
329
339
|
box-shadow: var(--ui-focus-halo);
|
|
330
340
|
}
|
|
331
341
|
|
|
332
|
-
/* Ghost
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
hue came out a mid-grey slab for neutral, whose hue is the ink: louder than the enabled button. */
|
|
336
|
-
:host-state([variant="ghost"]):is(:disabled, [aria-disabled="true"]) {
|
|
337
|
-
background-color: oklch(from var(--_tone) l c h / 14%);
|
|
342
|
+
/* Ghost keeps no border, but gains the same neutral surface as other disabled buttons. */
|
|
343
|
+
:host-state([variant="ghost"]):is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])) {
|
|
344
|
+
background-color: var(--ui-disabled-surface);
|
|
338
345
|
border-color: transparent;
|
|
339
346
|
}
|
|
340
347
|
|
|
@@ -393,7 +400,7 @@
|
|
|
393
400
|
transform: none;
|
|
394
401
|
}
|
|
395
402
|
|
|
396
|
-
:host-state([variant="link"]):is(:disabled, [aria-disabled="true"]) {
|
|
403
|
+
:host-state([variant="link"]):is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])) {
|
|
397
404
|
background: none;
|
|
398
405
|
border-color: transparent;
|
|
399
406
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Loading actions retain focus but cannot activate, navigate, submit, or notify click consumers.
|
|
2
2
|
export default function controller(host) {
|
|
3
3
|
const onClick = (event) => {
|
|
4
|
-
if (!host.state.pending) return;
|
|
4
|
+
if (!host.state.loading && !host.state.pending) return;
|
|
5
5
|
event.preventDefault();
|
|
6
6
|
event.stopImmediatePropagation();
|
|
7
7
|
};
|
|
@@ -103,7 +103,9 @@
|
|
|
103
103
|
gap: var(--ui-callout-gap, calc(var(--ui-space-2) * 0.75));
|
|
104
104
|
align-items: start;
|
|
105
105
|
max-width: 100%;
|
|
106
|
-
padding: var(--ui-callout-padding-block, var(--ui-space-2))
|
|
106
|
+
padding-block: var(--ui-callout-padding-block, var(--ui-space-2));
|
|
107
|
+
padding-inline-start: var(--ui-callout-padding-inline, var(--ui-space-2));
|
|
108
|
+
padding-inline-end: var(--ui-callout-padding-inline, var(--ui-space-3));
|
|
107
109
|
border: var(--ui-callout-border-width, 1px) solid color-mix(in srgb, var(--ui-callout-border, var(--_callout-border)) 35%, transparent);
|
|
108
110
|
border-inline-start: var(--ui-callout-leading-border-width, 4px) solid var(--ui-callout-border, var(--_callout-border));
|
|
109
111
|
border-radius: var(--ui-radius-md);
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
elevated floats above the page with a shadow, for a view's one card, such as sign-in.</prop>
|
|
6
6
|
<prop name="padding" type="sm | md | lg" default="md"
|
|
7
7
|
>The space inside the card: sm is snug (0.75rem), md is the default (1.5rem), and lg is roomy (2rem).</prop>
|
|
8
|
-
<prop name="tone" type="neutral | danger" default="neutral">danger
|
|
8
|
+
<prop name="tone" type="neutral | danger" default="neutral">danger adds a soft danger surface and a strong leading edge for consequential content.</prop>
|
|
9
9
|
<prop name="as" type="div | section | article | aside" default="div"
|
|
10
10
|
>The native element the card renders. Choose the one that names the content: a section of a page, a self-contained article, or an aside.</prop>
|
|
11
11
|
</defs>
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
box-sizing: border-box;
|
|
26
26
|
min-inline-size: 0;
|
|
27
27
|
padding: var(--ui-space-5);
|
|
28
|
-
border: 1px solid var(--ui-border-
|
|
28
|
+
border: 1px solid var(--ui-border-strong);
|
|
29
29
|
border-radius: var(--ui-radius-lg);
|
|
30
30
|
background: var(--ui-surface-raised);
|
|
31
31
|
color: var(--ui-text-primary);
|
|
@@ -51,7 +51,9 @@
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
:host-state([tone="danger"]) {
|
|
54
|
-
border-color: var(--ui-danger);
|
|
54
|
+
border-color: color-mix(in srgb, var(--ui-danger) 45%, var(--ui-border-default));
|
|
55
|
+
border-inline-start: 4px solid var(--ui-danger);
|
|
56
|
+
background: var(--ui-danger-soft);
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
@@ -98,10 +98,10 @@
|
|
|
98
98
|
inline-size: var(--_ui-checkbox-size, 1.125rem);
|
|
99
99
|
block-size: var(--_ui-checkbox-size, 1.125rem);
|
|
100
100
|
margin: 0.125em 0 0;
|
|
101
|
-
border: 1px solid var(--ui-control-border
|
|
101
|
+
border: 1px solid var(--ui-control-border, var(--ui-border-strong));
|
|
102
102
|
border-radius: var(--ui-radius-sm);
|
|
103
103
|
background: var(--ui-control-surface, var(--ui-surface-default));
|
|
104
|
-
box-shadow:
|
|
104
|
+
box-shadow: var(--ui-control-inset);
|
|
105
105
|
cursor: pointer;
|
|
106
106
|
transition:
|
|
107
107
|
background-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
@@ -113,28 +113,30 @@
|
|
|
113
113
|
content: "";
|
|
114
114
|
position: absolute;
|
|
115
115
|
opacity: 0;
|
|
116
|
+
transition: opacity 120ms var(--ui-motion-ease);
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
input:checked,
|
|
119
120
|
input:indeterminate {
|
|
120
121
|
border-color: var(--ui-accent-solid);
|
|
121
122
|
background: var(--ui-accent-solid);
|
|
122
|
-
box-shadow: inset
|
|
123
|
+
box-shadow: var(--ui-control-inset);
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
/* Centre the tick's box, then lift it: a rotated L's ink sits ~0.11rem below its box centre. */
|
|
126
127
|
input:checked::after {
|
|
127
128
|
inset: 0;
|
|
128
129
|
margin: auto;
|
|
129
|
-
inline-size: 0.
|
|
130
|
-
block-size: 0.
|
|
130
|
+
inline-size: 0.28rem;
|
|
131
|
+
block-size: 0.5rem;
|
|
131
132
|
/* Longhands, not `border: solid var(...)`: lowering drops a shorthand that omits a
|
|
132
133
|
component, which left the tick with no style and no colour. */
|
|
133
134
|
border-style: solid;
|
|
134
135
|
border-color: var(--ui-text-on-accent);
|
|
135
136
|
border-width: 0 0.125rem 0.125rem 0;
|
|
136
137
|
opacity: 1;
|
|
137
|
-
transform:
|
|
138
|
+
transform: translate(0.07rem, -0.09rem) rotate(45deg);
|
|
139
|
+
animation: ui-checkbox-check 180ms var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1)) both;
|
|
138
140
|
}
|
|
139
141
|
|
|
140
142
|
input:indeterminate::after {
|
|
@@ -146,6 +148,28 @@
|
|
|
146
148
|
transform: translateY(-50%);
|
|
147
149
|
}
|
|
148
150
|
|
|
151
|
+
@keyframes ui-checkbox-check {
|
|
152
|
+
from {
|
|
153
|
+
opacity: 0;
|
|
154
|
+
transform: translate(0.07rem, -0.09rem) rotate(45deg) scale(0.55);
|
|
155
|
+
}
|
|
156
|
+
65% {
|
|
157
|
+
opacity: 1;
|
|
158
|
+
transform: translate(0.07rem, -0.09rem) rotate(45deg) scale(1.12);
|
|
159
|
+
}
|
|
160
|
+
to {
|
|
161
|
+
opacity: 1;
|
|
162
|
+
transform: translate(0.07rem, -0.09rem) rotate(45deg) scale(1);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@media (prefers-reduced-motion: reduce) {
|
|
167
|
+
input::after {
|
|
168
|
+
transition: none;
|
|
169
|
+
animation: none;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
149
173
|
input:hover:enabled {
|
|
150
174
|
border-color: var(--ui-accent-solid);
|
|
151
175
|
}
|
|
@@ -163,9 +187,13 @@
|
|
|
163
187
|
color: var(--ui-disabled-text);
|
|
164
188
|
cursor: not-allowed;
|
|
165
189
|
}
|
|
190
|
+
:host-state([disabled]) .description {
|
|
191
|
+
color: var(--ui-disabled-text);
|
|
192
|
+
}
|
|
166
193
|
:host-state([disabled]) input {
|
|
167
|
-
border-color: var(--ui-border
|
|
168
|
-
background: var(--ui-
|
|
194
|
+
border-color: var(--ui-disabled-border);
|
|
195
|
+
background: var(--ui-disabled-surface);
|
|
196
|
+
box-shadow: none;
|
|
169
197
|
cursor: not-allowed;
|
|
170
198
|
}
|
|
171
199
|
|
|
@@ -13,16 +13,17 @@
|
|
|
13
13
|
when none is chosen. A disabled combobox sends nothing.</prop>
|
|
14
14
|
<prop name="value" type="string | null"
|
|
15
15
|
>The selected value in single mode, which a named combobox submits with its form. The field shows the matching option's label, and a form reset returns to
|
|
16
|
-
this value.</prop>
|
|
16
|
+
this value. If omitted, the first authored option with selected sets the initial value.</prop>
|
|
17
17
|
<prop
|
|
18
18
|
name="items"
|
|
19
19
|
type="list(object({ id: string, value: string, label: string, group?: string, disabled?: boolean, description?: string, tag?: object({ label: string, tone?: neutral | accent | info | success | warning | danger, color?: string }) }))"
|
|
20
|
-
>The selected items in multiple mode, as JSON; a named combobox submits each one's value. A form reset returns to these items, or to
|
|
20
|
+
>The selected items in multiple mode, as JSON; a named combobox submits each one's value. A form reset returns to these items, or to authored selected
|
|
21
|
+
options when unset.</prop>
|
|
21
22
|
<prop name="selectedValues" type="list(string)"
|
|
22
|
-
>The selected option values in multiple mode, when the consumer controls the selection.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
selection.</prop>
|
|
23
|
+
>The selected option values in multiple mode, when the consumer controls the selection. Without it or items, authored options with selected set the initial
|
|
24
|
+
selection. Once set, the consumer owns it: each value shows as a badge with its authored option's label, adding or removing one reports
|
|
25
|
+
selected-values-change with the new list, and the badges follow selectedValues, not the user, unless it is updated to match. Setting it reports nothing.
|
|
26
|
+
It takes precedence over items; leave it unset to let the combobox keep its own selection.</prop>
|
|
26
27
|
<prop name="multiple" type="boolean" default="false"
|
|
27
28
|
>Lets the user choose several options. Each choice becomes a removable badge before the input, the list stays open between picks, and choosing a checked
|
|
28
29
|
option removes it. value-change then reports the whole list of items, and selected-values-change the list of their values; use selectedValues or items,
|
|
@@ -66,8 +67,8 @@
|
|
|
66
67
|
>Adds a chevron button that opens and closes the full, unfiltered list of options, for users who would rather browse than type. ArrowDown opens the same
|
|
67
68
|
list with or without it.</prop>
|
|
68
69
|
<prop name="clearable" type="boolean" default="false"
|
|
69
|
-
>Adds a clear button to the field that empties the input and clears the selection, reported as value-change with kind "clear".
|
|
70
|
-
only the typed text; chosen items stay.</prop>
|
|
70
|
+
>Adds a clear button to the field that empties the input and clears the selection, reported as value-change with kind "clear". It is disabled when there is
|
|
71
|
+
nothing to clear. In multiple mode it clears only the typed text; chosen items stay.</prop>
|
|
71
72
|
<prop name="help" type="string" default=""
|
|
72
73
|
>Help text for the field. When set, a help button appears beside the field and opens a tooltip with this text; while it is open, the input is described by
|
|
73
74
|
it.</prop>
|
|
@@ -144,42 +145,50 @@
|
|
|
144
145
|
*</template></label>
|
|
145
146
|
<div class="control">
|
|
146
147
|
<div class="field" $ref="field">
|
|
147
|
-
<
|
|
148
|
-
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
148
|
+
<div class="entry">
|
|
149
|
+
<slot name="start"></slot>
|
|
150
|
+
<template $if="multiple">
|
|
151
|
+
<button
|
|
152
|
+
$each="item, index of internalItems"
|
|
153
|
+
$key="item.id"
|
|
154
|
+
class="item"
|
|
155
|
+
type="button"
|
|
156
|
+
tabindex="-1"
|
|
157
|
+
:data-index="index"
|
|
158
|
+
:disabled="disabled or readonly or item.disabled"
|
|
159
|
+
:aria-label="format('%s, press Delete or Backspace to remove', item.label)"
|
|
160
|
+
>
|
|
161
|
+
<slot :name="format('item-%s', item.id)"><ui-badge $value="item.label"></ui-badge></slot>
|
|
162
|
+
</button>
|
|
163
|
+
</template>
|
|
164
|
+
<input
|
|
165
|
+
$ref="input"
|
|
166
|
+
:id="format('%s-input', uid)"
|
|
167
|
+
role="combobox"
|
|
168
|
+
aria-autocomplete="list"
|
|
169
|
+
autocomplete="off"
|
|
170
|
+
:aria-controls="format('%s-listbox', uid)"
|
|
171
|
+
:aria-expanded="expanded"
|
|
172
|
+
:aria-invalid="invalid or validationStatus = 'error'"
|
|
173
|
+
:aria-busy="loading or validationStatus = 'pending'"
|
|
174
|
+
.value="display"
|
|
175
|
+
:placeholder="placeholder"
|
|
176
|
+
:disabled="disabled"
|
|
177
|
+
:readonly="readonly"
|
|
178
|
+
:required="required and not (multiple and internalItems[0])"
|
|
158
179
|
>
|
|
159
|
-
|
|
160
|
-
</button>
|
|
161
|
-
</template>
|
|
162
|
-
<input
|
|
163
|
-
$ref="input"
|
|
164
|
-
:id="format('%s-input', uid)"
|
|
165
|
-
role="combobox"
|
|
166
|
-
aria-autocomplete="list"
|
|
167
|
-
autocomplete="off"
|
|
168
|
-
:aria-controls="format('%s-listbox', uid)"
|
|
169
|
-
:aria-expanded="expanded"
|
|
170
|
-
:aria-invalid="invalid or validationStatus = 'error'"
|
|
171
|
-
:aria-busy="loading or validationStatus = 'pending'"
|
|
172
|
-
.value="display"
|
|
173
|
-
:placeholder="placeholder"
|
|
174
|
-
:disabled="disabled"
|
|
175
|
-
:readonly="readonly"
|
|
176
|
-
:required="required and not (multiple and internalItems[0])"
|
|
177
|
-
>
|
|
180
|
+
</div>
|
|
178
181
|
<input $if="name and not multiple" type="hidden" :name="name" :value="submitted" :disabled="disabled">
|
|
179
182
|
<template $if="name and multiple">
|
|
180
183
|
<input $each="item of internalItems" $key="item.id" type="hidden" :name="name" :value="item.value" :disabled="disabled">
|
|
181
184
|
</template>
|
|
182
|
-
<button
|
|
185
|
+
<button
|
|
186
|
+
$if="clearable"
|
|
187
|
+
type="button"
|
|
188
|
+
data-combobox-action="clear"
|
|
189
|
+
aria-label="Clear"
|
|
190
|
+
:disabled="disabled or readonly or (not raw and (multiple or selected = null))"
|
|
191
|
+
>
|
|
183
192
|
<svg class="affordance-icon" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
|
184
193
|
<path d="M7 7l10 10M17 7 7 17"></path>
|
|
185
194
|
</svg>
|
|
@@ -401,6 +410,11 @@
|
|
|
401
410
|
var(--ui-control-inset),
|
|
402
411
|
var(--ui-control-focus-halo-shadow);
|
|
403
412
|
}
|
|
413
|
+
.entry {
|
|
414
|
+
display: flex;
|
|
415
|
+
flex: 1 1 auto;
|
|
416
|
+
min-inline-size: 0;
|
|
417
|
+
}
|
|
404
418
|
/* A ghost icon button: the affordance is the mark, not a box around it. */
|
|
405
419
|
.help {
|
|
406
420
|
flex: none;
|
|
@@ -520,7 +534,7 @@
|
|
|
520
534
|
overflow: auto;
|
|
521
535
|
margin: 0;
|
|
522
536
|
padding: var(--ui-space-1);
|
|
523
|
-
border: 1px solid var(--_ui-combobox-popup-border, var(--ui-overlay-border, var(--ui-border-
|
|
537
|
+
border: 1px solid var(--_ui-combobox-popup-border, var(--ui-overlay-border, var(--ui-border-strong)));
|
|
524
538
|
border-radius: var(--_ui-combobox-popup-radius, var(--ui-overlay-radius, var(--ui-radius-md)));
|
|
525
539
|
background: var(--_ui-combobox-popup-surface, var(--ui-overlay-surface, var(--ui-surface-elevated)));
|
|
526
540
|
color: var(--ui-text-primary);
|
|
@@ -544,6 +558,10 @@
|
|
|
544
558
|
color: var(--ui-disabled-text);
|
|
545
559
|
cursor: not-allowed;
|
|
546
560
|
}
|
|
561
|
+
.option[aria-disabled="true"] .primary,
|
|
562
|
+
.option[aria-disabled="true"] .secondary {
|
|
563
|
+
color: var(--ui-disabled-text);
|
|
564
|
+
}
|
|
547
565
|
.primary {
|
|
548
566
|
display: block;
|
|
549
567
|
color: var(--_ui-combobox-option-text, var(--ui-text-primary));
|
|
@@ -640,21 +658,29 @@
|
|
|
640
658
|
);
|
|
641
659
|
}
|
|
642
660
|
|
|
643
|
-
/* Multiple mode
|
|
661
|
+
/* Multiple mode keeps one control height. Chips and the input scroll within the entry,
|
|
662
|
+
while the clear and disclosure controls remain fixed at the end of the field. */
|
|
644
663
|
:host-state([multiple]) .field {
|
|
645
|
-
flex-wrap: wrap;
|
|
646
664
|
align-items: center;
|
|
647
|
-
gap: var(--ui-space-1);
|
|
648
665
|
min-block-size: var(--_ui-combobox-item-min-block-size, 2.5rem);
|
|
649
666
|
padding: var(--ui-space-1);
|
|
650
667
|
}
|
|
668
|
+
:host-state([multiple]) .entry {
|
|
669
|
+
align-items: center;
|
|
670
|
+
gap: var(--ui-space-1);
|
|
671
|
+
overflow-x: auto;
|
|
672
|
+
scrollbar-width: none;
|
|
673
|
+
}
|
|
674
|
+
:host-state([multiple]) .entry::-webkit-scrollbar {
|
|
675
|
+
display: none;
|
|
676
|
+
}
|
|
651
677
|
:host-state([multiple]) input {
|
|
652
678
|
flex: 1 0 var(--_ui-combobox-item-input-min-inline-size, 5rem);
|
|
653
679
|
width: auto;
|
|
654
680
|
min-block-size: 1.75rem;
|
|
655
681
|
padding: var(--ui-space-0-5) var(--ui-space-1);
|
|
656
682
|
}
|
|
657
|
-
/*
|
|
683
|
+
/* Size variants keep their control height as selections are added. */
|
|
658
684
|
:host-state([multiple]):host-state([size="sm"]) .field {
|
|
659
685
|
min-block-size: 0;
|
|
660
686
|
padding: var(--ui-space-0-5);
|
|
@@ -673,6 +699,7 @@
|
|
|
673
699
|
.item {
|
|
674
700
|
appearance: none;
|
|
675
701
|
display: inline-flex;
|
|
702
|
+
flex: none;
|
|
676
703
|
min-inline-size: 0;
|
|
677
704
|
max-inline-size: min(100%, var(--_ui-combobox-item-item-max-inline-size, 12rem));
|
|
678
705
|
overflow: hidden;
|
|
@@ -689,7 +716,7 @@
|
|
|
689
716
|
outline-offset: 1px;
|
|
690
717
|
}
|
|
691
718
|
.item:disabled {
|
|
692
|
-
|
|
719
|
+
color: var(--ui-disabled-text);
|
|
693
720
|
}
|
|
694
721
|
|
|
695
722
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
@@ -58,6 +58,10 @@ export default function controller(host) {
|
|
|
58
58
|
// "none": the consumer already narrowed the options (a server search), so every one is listed.
|
|
59
59
|
filterByLabel: host.state.filter !== "none",
|
|
60
60
|
});
|
|
61
|
+
const authoredDefaults = () => {
|
|
62
|
+
const values = new Set(Array.from(authored.querySelectorAll("option[selected]"), (option) => option.value));
|
|
63
|
+
return config().options.filter((option) => values.has(option.value));
|
|
64
|
+
};
|
|
61
65
|
// Selected items work uncontrolled: the component keeps them and reports every change. A consumer
|
|
62
66
|
// that owns `items` stays in charge, because the prop resyncs whatever it sets. A consumer that sets
|
|
63
67
|
// `selectedValues` controls the selection: the chips follow it, and a user's change is only reported.
|
|
@@ -466,7 +470,7 @@ export default function controller(host) {
|
|
|
466
470
|
host.state.selected = null;
|
|
467
471
|
host.state.raw = host.state.query ?? "";
|
|
468
472
|
} else {
|
|
469
|
-
host.state.selected = host.state.value ?? null;
|
|
473
|
+
host.state.selected = host.state.value !== undefined ? host.state.value : authoredDefaults()[0]?.value ?? null;
|
|
470
474
|
host.state.raw = host.state.query ?? "";
|
|
471
475
|
if (host.state.query === undefined && !host.state.raw && host.state.selected !== null) {
|
|
472
476
|
host.state.raw = config().options?.find((row) => row.value === host.state.selected)?.label ?? host.state.selected;
|
|
@@ -499,7 +503,7 @@ export default function controller(host) {
|
|
|
499
503
|
const stopReset = afterFormReset(input, () => {
|
|
500
504
|
close();
|
|
501
505
|
lastSelection = null;
|
|
502
|
-
host.state.internalItems = controlledValues() ? itemsForValues() : Array.isArray(host.state.items) ? host.state.items :
|
|
506
|
+
host.state.internalItems = controlledValues() ? itemsForValues() : Array.isArray(host.state.items) ? host.state.items : authoredDefaults();
|
|
503
507
|
applyDefaults();
|
|
504
508
|
input.value = host.state.display;
|
|
505
509
|
resetValidation();
|
|
@@ -522,6 +526,7 @@ export default function controller(host) {
|
|
|
522
526
|
let lastSelectedValues = host.state.selectedValues;
|
|
523
527
|
if (controlledValues()) host.state.internalItems = itemsForValues();
|
|
524
528
|
else if (Array.isArray(lastItems)) host.state.internalItems = lastItems;
|
|
529
|
+
else host.state.internalItems = authoredDefaults();
|
|
525
530
|
const stop = host.effect(() => {
|
|
526
531
|
// A consumer that sets `items` owns them; otherwise the component keeps its own. selectedValues wins.
|
|
527
532
|
if (host.state.items !== lastItems) {
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
box-sizing: border-box;
|
|
58
58
|
padding: var(--ui-space-1);
|
|
59
59
|
background: var(--_ui-context-menu-surface, var(--ui-overlay-surface, var(--ui-surface-elevated)));
|
|
60
|
-
border: 1px solid var(--_ui-context-menu-border, var(--ui-overlay-border, var(--ui-border-
|
|
60
|
+
border: 1px solid var(--_ui-context-menu-border, var(--ui-overlay-border, var(--ui-border-strong)));
|
|
61
61
|
border-radius: var(--_ui-context-menu-radius, var(--ui-overlay-radius, var(--ui-radius-lg)));
|
|
62
62
|
box-shadow: var(--_ui-context-menu-shadow, var(--ui-overlay-shadow, var(--ui-elevation-overlay, var(--ui-shadow-lg))));
|
|
63
63
|
outline: 0;
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
block-size: 0;
|
|
79
79
|
margin: var(--ui-space-1) 0;
|
|
80
80
|
border: 0;
|
|
81
|
-
border-block-start: 1px solid var(--ui-border-
|
|
81
|
+
border-block-start: 1px solid var(--ui-border-divider);
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
.menu:popover-open {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
padding: var(--_ui-description-padding, 0);
|
|
20
20
|
border-width: var(--_ui-description-border-width, 0);
|
|
21
21
|
border-style: solid;
|
|
22
|
-
border-color: var(--ui-border-default);
|
|
22
|
+
border-color: var(--_ui-description-border-color, var(--ui-border-default));
|
|
23
23
|
border-radius: var(--ui-radius-md);
|
|
24
24
|
font-size: var(--ui-font-size-sm);
|
|
25
25
|
}
|