@mystravil/hardpoint 0.2.0 → 0.3.0
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/CHANGELOG.md +51 -38
- package/LICENSE +25 -25
- package/README.md +67 -64
- package/dist/base.css +625 -625
- package/dist/components/AppShell.svelte +698 -698
- package/dist/components/Button.svelte +221 -174
- package/dist/components/Button.svelte.d.ts +18 -2
- package/dist/components/Checkbox.svelte +235 -235
- package/dist/components/CheckboxGroup.svelte +207 -207
- package/dist/components/Combobox.svelte +901 -901
- package/dist/components/Dialog.svelte +359 -359
- package/dist/components/Disclosure.svelte +201 -201
- package/dist/components/EmptyState.svelte +88 -88
- package/dist/components/ErrorState.svelte +135 -135
- package/dist/components/ImageViewer.svelte +764 -764
- package/dist/components/KeyValueList.svelte +114 -114
- package/dist/components/ListDetail.svelte +218 -218
- package/dist/components/LoadRegion.svelte +219 -219
- package/dist/components/MediaFrame.svelte +110 -110
- package/dist/components/MediaImage.svelte +256 -256
- package/dist/components/Menu.svelte +275 -258
- package/dist/components/MenuCheckboxItem.svelte +119 -119
- package/dist/components/MenuGroup.svelte +50 -50
- package/dist/components/MenuItem.svelte +94 -94
- package/dist/components/MenuRadioGroup.svelte +62 -62
- package/dist/components/MenuRadioItem.svelte +110 -110
- package/dist/components/MenuSeparator.svelte +28 -28
- package/dist/components/Meter.svelte +283 -283
- package/dist/components/NativeSelect.svelte +135 -135
- package/dist/components/Notice.svelte +262 -262
- package/dist/components/Popover.svelte +222 -222
- package/dist/components/Progress.svelte +157 -157
- package/dist/components/RadioGroup.svelte +440 -440
- package/dist/components/Select.svelte +471 -471
- package/dist/components/Skeleton.svelte +149 -149
- package/dist/components/Spinner.svelte +118 -118
- package/dist/components/Stat.svelte +253 -253
- package/dist/components/Steps.svelte +189 -189
- package/dist/components/Switch.svelte +222 -222
- package/dist/components/Table.svelte +504 -504
- package/dist/components/Tabs.svelte +246 -246
- package/dist/components/Tag.svelte +40 -40
- package/dist/components/TextArea.svelte +272 -272
- package/dist/components/TextField.svelte +396 -256
- package/dist/components/TextField.svelte.d.ts +16 -1
- package/dist/components/Timeline.svelte +156 -156
- package/dist/components/Toaster.svelte +411 -411
- package/dist/components/Tooltip.svelte +200 -200
- package/dist/components/TooltipGroup.svelte +46 -46
- package/dist/components/internal/Scrim.svelte +52 -52
- package/dist/components/internal/Sheet.svelte +263 -263
- package/dist/fonts.css +71 -71
- package/dist/tokens.css +283 -283
- package/package.json +81 -76
|
@@ -1,258 +1,275 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import type { DropdownMenu as BitsDropdownMenu } from 'bits-ui';
|
|
4
|
-
|
|
5
|
-
export type MenuTriggerSnippetProps = {
|
|
6
|
-
/** Spread onto the button that opens the menu. */
|
|
7
|
-
props: Record<string, unknown>;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Attributes and handlers not listed here go to the menu element (Bits UI
|
|
12
|
-
* `DropdownMenu.Content`), among them `side` (default `bottom`), `align`
|
|
13
|
-
* (default `start`), `sideOffset` (default 8), `collisionPadding`
|
|
14
|
-
* (default 8), `loop`, `onCloseAutoFocus`, `onEscapeKeydown` and
|
|
15
|
-
* `onInteractOutside`. The placement props apply from 600px only; below it
|
|
16
|
-
* the menu is a bottom sheet.
|
|
17
|
-
*/
|
|
18
|
-
export type MenuProps = Omit<BitsDropdownMenu.ContentProps, 'child' | 'children' | 'forceMount' | 'ref'> & {
|
|
19
|
-
open?: boolean;
|
|
20
|
-
/**
|
|
21
|
-
* The menu's accessible name, and the sheet's title below 600px. Use the
|
|
22
|
-
* trigger's accessible name: its text, or an icon button's `aria-label`.
|
|
23
|
-
* A fixed string the app defines, set in caps as the sheet's title, so it
|
|
24
|
-
* never carries user data; name a row's item through the trigger's
|
|
25
|
-
* `aria-describedby`.
|
|
26
|
-
*/
|
|
27
|
-
label: string;
|
|
28
|
-
/** The button the menu opens from: spread `props` onto it. */
|
|
29
|
-
trigger: Snippet<[MenuTriggerSnippetProps]>;
|
|
30
|
-
/** The items: MenuItem, MenuCheckboxItem, MenuRadioGroup, MenuGroup and MenuSeparator. */
|
|
31
|
-
children: Snippet;
|
|
32
|
-
/** The sheet's close button's accessible name (below 600px). */
|
|
33
|
-
closeLabel?: string;
|
|
34
|
-
/** The menu element, `role="menu"`. */
|
|
35
|
-
ref?: HTMLElement | null;
|
|
36
|
-
};
|
|
37
|
-
</script>
|
|
38
|
-
|
|
39
|
-
<script lang="ts">
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
43
|
-
import
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
let
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { DropdownMenu as BitsDropdownMenu } from 'bits-ui';
|
|
4
|
+
|
|
5
|
+
export type MenuTriggerSnippetProps = {
|
|
6
|
+
/** Spread onto the button that opens the menu. */
|
|
7
|
+
props: Record<string, unknown>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Attributes and handlers not listed here go to the menu element (Bits UI
|
|
12
|
+
* `DropdownMenu.Content`), among them `side` (default `bottom`), `align`
|
|
13
|
+
* (default `start`), `sideOffset` (default 8), `collisionPadding`
|
|
14
|
+
* (default 8), `loop`, `onCloseAutoFocus`, `onEscapeKeydown` and
|
|
15
|
+
* `onInteractOutside`. The placement props apply from 600px only; below it
|
|
16
|
+
* the menu is a bottom sheet.
|
|
17
|
+
*/
|
|
18
|
+
export type MenuProps = Omit<BitsDropdownMenu.ContentProps, 'child' | 'children' | 'forceMount' | 'ref'> & {
|
|
19
|
+
open?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* The menu's accessible name, and the sheet's title below 600px. Use the
|
|
22
|
+
* trigger's accessible name: its text, or an icon button's `aria-label`.
|
|
23
|
+
* A fixed string the app defines, set in caps as the sheet's title, so it
|
|
24
|
+
* never carries user data; name a row's item through the trigger's
|
|
25
|
+
* `aria-describedby`.
|
|
26
|
+
*/
|
|
27
|
+
label: string;
|
|
28
|
+
/** The button the menu opens from: spread `props` onto it. */
|
|
29
|
+
trigger: Snippet<[MenuTriggerSnippetProps]>;
|
|
30
|
+
/** The items: MenuItem, MenuCheckboxItem, MenuRadioGroup, MenuGroup and MenuSeparator. */
|
|
31
|
+
children: Snippet;
|
|
32
|
+
/** The sheet's close button's accessible name (below 600px). */
|
|
33
|
+
closeLabel?: string;
|
|
34
|
+
/** The menu element, `role="menu"`. */
|
|
35
|
+
ref?: HTMLElement | null;
|
|
36
|
+
};
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<script lang="ts">
|
|
40
|
+
import { tick } from 'svelte';
|
|
41
|
+
import { DropdownMenu } from 'bits-ui';
|
|
42
|
+
import { MediaQuery } from 'svelte/reactivity';
|
|
43
|
+
import { pop } from '../motion/index.js';
|
|
44
|
+
import Sheet from './internal/Sheet.svelte';
|
|
45
|
+
|
|
46
|
+
let {
|
|
47
|
+
open = $bindable(false),
|
|
48
|
+
label,
|
|
49
|
+
trigger,
|
|
50
|
+
children,
|
|
51
|
+
closeLabel = 'Close',
|
|
52
|
+
ref = $bindable(null),
|
|
53
|
+
class: className,
|
|
54
|
+
onInteractOutside,
|
|
55
|
+
onCloseAutoFocus,
|
|
56
|
+
side = 'bottom',
|
|
57
|
+
align = 'start',
|
|
58
|
+
sideOffset = 8,
|
|
59
|
+
collisionPadding = 8,
|
|
60
|
+
alignOffset,
|
|
61
|
+
arrowPadding,
|
|
62
|
+
avoidCollisions,
|
|
63
|
+
collisionBoundary,
|
|
64
|
+
sticky,
|
|
65
|
+
hideWhenDetached,
|
|
66
|
+
updatePositionStrategy,
|
|
67
|
+
strategy,
|
|
68
|
+
customAnchor,
|
|
69
|
+
...rest
|
|
70
|
+
}: MenuProps = $props();
|
|
71
|
+
|
|
72
|
+
// Placement belongs to the menu under the trigger; the sheet always sits
|
|
73
|
+
// at the bottom edge, so ContentStatic never receives these.
|
|
74
|
+
const placement = $derived({
|
|
75
|
+
side,
|
|
76
|
+
align,
|
|
77
|
+
sideOffset,
|
|
78
|
+
collisionPadding,
|
|
79
|
+
alignOffset,
|
|
80
|
+
arrowPadding,
|
|
81
|
+
avoidCollisions,
|
|
82
|
+
collisionBoundary,
|
|
83
|
+
sticky,
|
|
84
|
+
hideWhenDetached,
|
|
85
|
+
updatePositionStrategy,
|
|
86
|
+
strategy,
|
|
87
|
+
customAnchor
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// The form follows the width (BRIEF, Apps and phones: Overlays): a menu
|
|
91
|
+
// under its trigger from 600px, the shared bottom sheet below it.
|
|
92
|
+
const wide = new MediaQuery('min-width: 600px', true);
|
|
93
|
+
|
|
94
|
+
// Bits UI moves real focus to the highlighted item, whether keys or a
|
|
95
|
+
// pointer moved it. Only a highlight the keys moved draws the focus
|
|
96
|
+
// contour; a pointer's draws the tint alone. The items read the contour
|
|
97
|
+
// from --menu-contour, which .hp-menu[data-keyboard] sets.
|
|
98
|
+
let keyboard = $state(false);
|
|
99
|
+
|
|
100
|
+
let sheetNode = $state<HTMLElement | null>(null);
|
|
101
|
+
let triggerNode = $state<HTMLElement | null>(null);
|
|
102
|
+
|
|
103
|
+
// Bits UI's content layers (the portal, positioning, focus and dismiss
|
|
104
|
+
// handling) cost about 0.3 ms a menu, and an app may draw several closed
|
|
105
|
+
// menus per view, so they mount on the first open, not with the
|
|
106
|
+
// trigger. Until then only the trigger and its ARIA exist. They mount
|
|
107
|
+
// closed, and Bits UI sees the menu open one update later, so the first
|
|
108
|
+
// entrance plays as every later one does. They stay mounted after that.
|
|
109
|
+
let layers = $state(false);
|
|
110
|
+
let ready = $state(false);
|
|
111
|
+
$effect(() => {
|
|
112
|
+
if (!open || layers) return;
|
|
113
|
+
layers = true;
|
|
114
|
+
tick().then(() => (ready = true));
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
function close() {
|
|
118
|
+
open = false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// The sheet's title row and handle sit outside the menu element; pressing
|
|
122
|
+
// them is not an outside press.
|
|
123
|
+
function insideSheet(e: PointerEvent) {
|
|
124
|
+
if (sheetNode && e.target instanceof Node && sheetNode.contains(e.target)) {
|
|
125
|
+
e.preventDefault();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
onInteractOutside?.(e);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Bits UI leaves focus where an outside press put it, so a click on
|
|
132
|
+
// another control keeps it. Below 600px the only thing outside is the
|
|
133
|
+
// scrim, and a press there is a dismiss like the close button, so focus
|
|
134
|
+
// returns to the trigger as it does after the close button.
|
|
135
|
+
function returnFocus(e: Event) {
|
|
136
|
+
onCloseAutoFocus?.(e);
|
|
137
|
+
if (e.defaultPrevented) return;
|
|
138
|
+
e.preventDefault();
|
|
139
|
+
triggerNode?.focus();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Listens on the menu element without replacing Bits UI's own handlers
|
|
143
|
+
// in `props`.
|
|
144
|
+
function trackInput(node: HTMLElement) {
|
|
145
|
+
const keys = () => (keyboard = true);
|
|
146
|
+
const pointer = () => (keyboard = false);
|
|
147
|
+
node.addEventListener('keydown', keys, true);
|
|
148
|
+
node.addEventListener('pointerdown', pointer, true);
|
|
149
|
+
node.addEventListener('pointermove', pointer, true);
|
|
150
|
+
return () => {
|
|
151
|
+
node.removeEventListener('keydown', keys, true);
|
|
152
|
+
node.removeEventListener('pointerdown', pointer, true);
|
|
153
|
+
node.removeEventListener('pointermove', pointer, true);
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
</script>
|
|
157
|
+
|
|
158
|
+
<!--
|
|
159
|
+
Bits UI gives the trigger aria-haspopup="menu", aria-expanded and
|
|
160
|
+
aria-controls; the menu element takes role="menu" and `label` as its
|
|
161
|
+
name. Opened by keys, focus moves to the first item; opened by a pointer,
|
|
162
|
+
to the menu itself. Arrow keys move the highlight and loop, letters jump
|
|
163
|
+
by typeahead, Enter or Space runs the item. Escape, choosing an item and,
|
|
164
|
+
below 600px, the close button, a swipe down or a press on the scrim close
|
|
165
|
+
it and return focus to the trigger. From 600px a press outside closes it
|
|
166
|
+
and leaves focus where the press put it; Tab closes it and moves on.
|
|
167
|
+
-->
|
|
168
|
+
<DropdownMenu.Root bind:open={() => open && ready, (value) => (open = value)}>
|
|
169
|
+
<DropdownMenu.Trigger
|
|
170
|
+
bind:ref={triggerNode}
|
|
171
|
+
onkeydowncapture={() => (keyboard = true)}
|
|
172
|
+
onpointerdowncapture={() => (keyboard = false)}
|
|
173
|
+
>
|
|
174
|
+
{#snippet child({ props })}
|
|
175
|
+
{@render trigger({ props })}
|
|
176
|
+
{/snippet}
|
|
177
|
+
</DropdownMenu.Trigger>
|
|
178
|
+
|
|
179
|
+
{#if layers}
|
|
180
|
+
<DropdownMenu.Portal>
|
|
181
|
+
{#if wide.current}
|
|
182
|
+
<DropdownMenu.Content forceMount bind:ref {...placement} {onInteractOutside} {onCloseAutoFocus} {...rest}>
|
|
183
|
+
{#snippet child({ wrapperProps, props, open: shown })}
|
|
184
|
+
{#if shown}
|
|
185
|
+
<div {...wrapperProps}>
|
|
186
|
+
<div
|
|
187
|
+
{...props}
|
|
188
|
+
class={['hp-menu', className]}
|
|
189
|
+
data-form="popover"
|
|
190
|
+
data-keyboard={keyboard || undefined}
|
|
191
|
+
aria-label={label}
|
|
192
|
+
transition:pop
|
|
193
|
+
{@attach trackInput}
|
|
194
|
+
>
|
|
195
|
+
{@render children()}
|
|
196
|
+
</div>
|
|
197
|
+
</div>
|
|
198
|
+
{/if}
|
|
199
|
+
{/snippet}
|
|
200
|
+
</DropdownMenu.Content>
|
|
201
|
+
{:else}
|
|
202
|
+
<DropdownMenu.ContentStatic
|
|
203
|
+
forceMount
|
|
204
|
+
bind:ref
|
|
205
|
+
{...rest}
|
|
206
|
+
preventScroll
|
|
207
|
+
onInteractOutside={insideSheet}
|
|
208
|
+
onCloseAutoFocus={returnFocus}
|
|
209
|
+
>
|
|
210
|
+
{#snippet child({ props, open: shown })}
|
|
211
|
+
<Sheet open={shown} layer="popover" title={label} {closeLabel} onclose={close} bind:ref={sheetNode}>
|
|
212
|
+
<div
|
|
213
|
+
{...props}
|
|
214
|
+
class={['hp-menu', className]}
|
|
215
|
+
data-form="sheet"
|
|
216
|
+
data-keyboard={keyboard || undefined}
|
|
217
|
+
aria-label={label}
|
|
218
|
+
{@attach trackInput}
|
|
219
|
+
>
|
|
220
|
+
{@render children()}
|
|
221
|
+
</div>
|
|
222
|
+
</Sheet>
|
|
223
|
+
{/snippet}
|
|
224
|
+
</DropdownMenu.ContentStatic>
|
|
225
|
+
{/if}
|
|
226
|
+
</DropdownMenu.Portal>
|
|
227
|
+
{/if}
|
|
228
|
+
</DropdownMenu.Root>
|
|
229
|
+
|
|
230
|
+
<style>
|
|
231
|
+
/* The list in both forms. Items read two inherited properties:
|
|
232
|
+
--menu-inset, the row's side padding, so item text lines up with the
|
|
233
|
+
menu's edge here and with the sheet's title there; and --menu-contour,
|
|
234
|
+
the outline a highlighted row draws, which only keys turn on. The menu
|
|
235
|
+
element takes focus when a pointer opens it; the rows show where focus
|
|
236
|
+
is, so the menu itself draws no contour. */
|
|
237
|
+
.hp-menu {
|
|
238
|
+
--menu-inset: var(--space-3);
|
|
239
|
+
--menu-contour: none;
|
|
240
|
+
|
|
241
|
+
box-sizing: border-box;
|
|
242
|
+
padding-block: var(--space-1);
|
|
243
|
+
background: var(--canvas);
|
|
244
|
+
color: var(--text);
|
|
245
|
+
font-family: var(--sans);
|
|
246
|
+
outline: none;
|
|
247
|
+
}
|
|
248
|
+
.hp-menu[data-keyboard] {
|
|
249
|
+
--menu-contour: 2px solid var(--focus);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/* ---- Popover (600px and up): a black panel under its trigger --------- */
|
|
253
|
+
|
|
254
|
+
/* On the popover layer (tokens.css), over the shell and over an open
|
|
255
|
+
dialog; Bits UI copies the z-index to the positioned wrapper. At least
|
|
256
|
+
as wide as the trigger and 192px, at most 320px, and as tall as the
|
|
257
|
+
space beside the trigger; a longer list scrolls inside. */
|
|
258
|
+
.hp-menu[data-form='popover'] {
|
|
259
|
+
position: relative;
|
|
260
|
+
z-index: var(--layer-popover);
|
|
261
|
+
width: max-content;
|
|
262
|
+
min-width: max(var(--bits-dropdown-menu-anchor-width), 192px);
|
|
263
|
+
max-width: min(320px, var(--bits-dropdown-menu-content-available-width));
|
|
264
|
+
max-height: var(--bits-dropdown-menu-content-available-height);
|
|
265
|
+
overflow-y: auto;
|
|
266
|
+
overscroll-behavior: contain;
|
|
267
|
+
border: 1px solid var(--border-control);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/* ---- Sheet (compact): the list is the sheet's body, which scrolls ---- */
|
|
271
|
+
|
|
272
|
+
.hp-menu[data-form='sheet'] {
|
|
273
|
+
--menu-inset: var(--gutter);
|
|
274
|
+
}
|
|
275
|
+
</style>
|