@insymetri/styleguide 0.1.80 → 0.1.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/IIDropdownInput/IIDropdownInput.svelte +2 -1
- package/dist/IIMenu/IIMenu.svelte +108 -16
- package/dist/IIMenu/IIMenu.svelte.d.ts +18 -0
- package/dist/IIMenu/IIMenuStories.svelte +41 -0
- package/dist/IIMenu/IIMenuStories.svelte.d.ts +2 -17
- package/dist/IIMenu/IIMenuTriggerProof.svelte +41 -0
- package/dist/IIMenu/IIMenuTriggerProof.svelte.d.ts +6 -0
- package/dist/IIPopover/IIPopover.svelte +21 -4
- package/dist/IIPopover/IIPopover.svelte.d.ts +11 -1
- package/dist/IIPopover/IIPopoverStories.svelte +21 -0
- package/dist/IIPopover/IIPopoverTriggerProof.svelte +18 -0
- package/dist/IIPopover/IIPopoverTriggerProof.svelte.d.ts +18 -0
- package/package.json +1 -1
|
@@ -188,8 +188,9 @@
|
|
|
188
188
|
clearTimeout(typeaheadTimer)
|
|
189
189
|
typeaheadTimer = setTimeout(() => { typeaheadBuffer = '' }, 500)
|
|
190
190
|
|
|
191
|
+
// Substring match (so "tu" finds "Alan Turing"), not just prefix.
|
|
191
192
|
const matchIndex = items.findIndex(
|
|
192
|
-
i => !i.disabled && i.label.toLowerCase().
|
|
193
|
+
i => !i.disabled && i.label.toLowerCase().includes(typeaheadBuffer)
|
|
193
194
|
)
|
|
194
195
|
if (matchIndex >= 0) {
|
|
195
196
|
const match = items[matchIndex]
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type {Snippet} from 'svelte'
|
|
3
|
+
import {createAttachmentKey} from 'svelte/attachments'
|
|
3
4
|
import {fly} from 'svelte/transition'
|
|
4
5
|
import {cn} from '../utils/cn'
|
|
5
6
|
import {IIIcon} from '../IIIcon'
|
|
6
|
-
import {createMenuSearch, isItem, isGroup, isSub, isSeparator, menuStyles, menuItemClass, type MenuItem, type MenuEntry, type SubEntry} from '../utils/menu'
|
|
7
|
+
import {createMenuSearch, getSelectableItems, isItem, isGroup, isSub, isSeparator, menuStyles, menuItemClass, type MenuItem, type MenuEntry, type SubEntry} from '../utils/menu'
|
|
7
8
|
import {useFloating, portal, clickOutside} from '../utils/menu'
|
|
8
9
|
import MenuItemContent from '../utils/menu/MenuItemContent.svelte'
|
|
9
10
|
import MenuSearchInput from '../utils/menu/MenuSearchInput.svelte'
|
|
@@ -17,6 +18,21 @@
|
|
|
17
18
|
onSelect: (value: string) => void
|
|
18
19
|
open?: boolean
|
|
19
20
|
children?: Snippet
|
|
21
|
+
/**
|
|
22
|
+
* Replace the default trigger button with a custom element. Spread `props`
|
|
23
|
+
* onto a single focusable element — it carries the ref, click/keydown
|
|
24
|
+
* handlers, and menu aria attributes. Unlike `children` (which is wrapped in
|
|
25
|
+
* an extra button), this makes your element THE trigger: one tab stop, and
|
|
26
|
+
* keyboard open/navigation works.
|
|
27
|
+
*/
|
|
28
|
+
trigger?: Snippet<[{props: Record<string, unknown>; open: boolean}]>
|
|
29
|
+
/**
|
|
30
|
+
* Enable select-style typeahead (non-searchable menus). Typing on the closed
|
|
31
|
+
* trigger picks the closest label match and fires `onSelect` (like
|
|
32
|
+
* `IIDropdownInput`); typing while open moves focus to the match. Off by
|
|
33
|
+
* default so action menus don't fire on a keypress.
|
|
34
|
+
*/
|
|
35
|
+
typeahead?: boolean
|
|
20
36
|
renderItem?: Snippet<[MenuItem]>
|
|
21
37
|
side?: 'top' | 'right' | 'bottom' | 'left'
|
|
22
38
|
align?: 'start' | 'center' | 'end'
|
|
@@ -36,6 +52,8 @@
|
|
|
36
52
|
onSelect,
|
|
37
53
|
open = $bindable(false),
|
|
38
54
|
children,
|
|
55
|
+
trigger,
|
|
56
|
+
typeahead = false,
|
|
39
57
|
renderItem,
|
|
40
58
|
side = 'bottom',
|
|
41
59
|
align = 'end',
|
|
@@ -114,6 +132,69 @@
|
|
|
114
132
|
close()
|
|
115
133
|
}
|
|
116
134
|
|
|
135
|
+
// Select-style typeahead (opt-in via `typeahead`, non-searchable only). Buffer
|
|
136
|
+
// keystrokes for 500ms and match on label substring (so "tu" finds "Alan
|
|
137
|
+
// Turing"). Closed → fire onSelect (set the value, like IIDropdownInput); open
|
|
138
|
+
// → move focus to the match.
|
|
139
|
+
let typeaheadBuffer = ''
|
|
140
|
+
let typeaheadTimer: ReturnType<typeof setTimeout> | undefined
|
|
141
|
+
|
|
142
|
+
function handleTypeahead(char: string) {
|
|
143
|
+
if (!typeahead || searchable) return
|
|
144
|
+
const wasOpen = open
|
|
145
|
+
typeaheadBuffer += char.toLowerCase()
|
|
146
|
+
clearTimeout(typeaheadTimer)
|
|
147
|
+
typeaheadTimer = setTimeout(() => {
|
|
148
|
+
typeaheadBuffer = ''
|
|
149
|
+
}, 500)
|
|
150
|
+
|
|
151
|
+
const match = getSelectableItems(items).find(
|
|
152
|
+
i => !i.disabled && i.label.toLowerCase().includes(typeaheadBuffer),
|
|
153
|
+
)
|
|
154
|
+
if (!match) return
|
|
155
|
+
if (wasOpen) {
|
|
156
|
+
floatingEl?.querySelector<HTMLElement>(`[role="menuitem"][data-value="${CSS.escape(match.value)}"]`)?.focus()
|
|
157
|
+
} else {
|
|
158
|
+
onSelect(match.value)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Open the menu from the trigger via keyboard. Enter/Space fire a native click
|
|
163
|
+
// on a <button> trigger (→ toggle); Arrow keys open it too. Once open, focus
|
|
164
|
+
// moves to the first item (effect above) and handleMenuKeydown takes over.
|
|
165
|
+
function handleTriggerKeydown(e: KeyboardEvent) {
|
|
166
|
+
if ((e.key === 'ArrowDown' || e.key === 'ArrowUp') && !open) {
|
|
167
|
+
e.preventDefault()
|
|
168
|
+
openSubIndex = null
|
|
169
|
+
open = true
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
if (typeahead && !open && e.key.length === 1 && e.key !== ' ' && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
173
|
+
e.preventDefault()
|
|
174
|
+
handleTypeahead(e.key)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Props a custom `trigger` snippet spreads onto its single element — carries the
|
|
179
|
+
// ref (via attachment), click/keydown, and menu aria. Stable attachment key so
|
|
180
|
+
// recomputing on `open` change doesn't re-run the ref attachment.
|
|
181
|
+
const attachTrigger = (node: Element) => {
|
|
182
|
+
triggerEl = node as HTMLElement
|
|
183
|
+
return () => {
|
|
184
|
+
if (triggerEl === node) triggerEl = null
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const triggerAttachmentKey = createAttachmentKey()
|
|
188
|
+
const triggerProps = $derived({
|
|
189
|
+
type: 'button',
|
|
190
|
+
'aria-haspopup': 'menu',
|
|
191
|
+
'aria-expanded': open,
|
|
192
|
+
'data-state': open ? 'open' : 'closed',
|
|
193
|
+
onclick: toggle,
|
|
194
|
+
onkeydown: handleTriggerKeydown,
|
|
195
|
+
[triggerAttachmentKey]: attachTrigger,
|
|
196
|
+
})
|
|
197
|
+
|
|
117
198
|
function getMenuItems(): HTMLElement[] {
|
|
118
199
|
if (!floatingEl) return []
|
|
119
200
|
return Array.from(floatingEl.querySelectorAll<HTMLElement>(':scope > [role="menuitem"]:not([data-disabled]), :scope > [role="group"] > [role="menuitem"]:not([data-disabled])'))
|
|
@@ -179,6 +260,11 @@
|
|
|
179
260
|
e.preventDefault()
|
|
180
261
|
close()
|
|
181
262
|
break
|
|
263
|
+
default:
|
|
264
|
+
if (typeahead && e.key.length === 1 && e.key !== ' ' && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
265
|
+
e.preventDefault()
|
|
266
|
+
handleTypeahead(e.key)
|
|
267
|
+
}
|
|
182
268
|
}
|
|
183
269
|
}
|
|
184
270
|
|
|
@@ -213,6 +299,7 @@
|
|
|
213
299
|
<div
|
|
214
300
|
role="menuitem"
|
|
215
301
|
tabindex="-1"
|
|
302
|
+
data-value={item.value}
|
|
216
303
|
data-disabled={item.disabled ? '' : undefined}
|
|
217
304
|
class={menuItemClass({variant: item.variant, searchable, isHighlighted: !item.disabled && index === search.highlightedIndex})}
|
|
218
305
|
data-search-item={searchable ? '' : undefined}
|
|
@@ -331,21 +418,26 @@
|
|
|
331
418
|
{/each}
|
|
332
419
|
{/snippet}
|
|
333
420
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
{
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
421
|
+
{#if trigger}
|
|
422
|
+
{@render trigger({props: triggerProps, open})}
|
|
423
|
+
{:else}
|
|
424
|
+
<button
|
|
425
|
+
bind:this={triggerEl}
|
|
426
|
+
type="button"
|
|
427
|
+
aria-haspopup="menu"
|
|
428
|
+
aria-expanded={open}
|
|
429
|
+
data-state={open ? 'open' : 'closed'}
|
|
430
|
+
class={cn(children ? '[all:unset] cursor-default' : defaultTriggerClass, triggerClass, className)}
|
|
431
|
+
onclick={toggle}
|
|
432
|
+
onkeydown={handleTriggerKeydown}
|
|
433
|
+
>
|
|
434
|
+
{#if children}
|
|
435
|
+
{@render children()}
|
|
436
|
+
{:else}
|
|
437
|
+
<IIIcon iconName="dots-three-vertical" />
|
|
438
|
+
{/if}
|
|
439
|
+
</button>
|
|
440
|
+
{/if}
|
|
349
441
|
|
|
350
442
|
{#if open}
|
|
351
443
|
<div use:portal use:clickOutside={{onClose: close, ignore: () => triggerEl}}>
|
|
@@ -5,6 +5,24 @@ type Props = {
|
|
|
5
5
|
onSelect: (value: string) => void;
|
|
6
6
|
open?: boolean;
|
|
7
7
|
children?: Snippet;
|
|
8
|
+
/**
|
|
9
|
+
* Replace the default trigger button with a custom element. Spread `props`
|
|
10
|
+
* onto a single focusable element — it carries the ref, click/keydown
|
|
11
|
+
* handlers, and menu aria attributes. Unlike `children` (which is wrapped in
|
|
12
|
+
* an extra button), this makes your element THE trigger: one tab stop, and
|
|
13
|
+
* keyboard open/navigation works.
|
|
14
|
+
*/
|
|
15
|
+
trigger?: Snippet<[{
|
|
16
|
+
props: Record<string, unknown>;
|
|
17
|
+
open: boolean;
|
|
18
|
+
}]>;
|
|
19
|
+
/**
|
|
20
|
+
* Enable select-style typeahead (non-searchable menus). Typing on the closed
|
|
21
|
+
* trigger picks the closest label match and fires `onSelect` (like
|
|
22
|
+
* `IIDropdownInput`); typing while open moves focus to the match. Off by
|
|
23
|
+
* default so action menus don't fire on a keypress.
|
|
24
|
+
*/
|
|
25
|
+
typeahead?: boolean;
|
|
8
26
|
renderItem?: Snippet<[MenuItem]>;
|
|
9
27
|
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
10
28
|
align?: 'start' | 'center' | 'end';
|
|
@@ -6,6 +6,16 @@
|
|
|
6
6
|
function handleSelect(value: string) {
|
|
7
7
|
console.log('Selected:', value)
|
|
8
8
|
}
|
|
9
|
+
|
|
10
|
+
// Custom-trigger demo: reflect the selection in the trigger so typeahead is
|
|
11
|
+
// visibly proven (type "al" → the label becomes "Alan Turing").
|
|
12
|
+
const assigneeLabels: Record<string, string> = {
|
|
13
|
+
me: 'Assign to me',
|
|
14
|
+
none: 'Unassigned',
|
|
15
|
+
ada: 'Ada Lovelace',
|
|
16
|
+
alan: 'Alan Turing',
|
|
17
|
+
}
|
|
18
|
+
let assigneeValue = $state('')
|
|
9
19
|
</script>
|
|
10
20
|
|
|
11
21
|
<div class="flex flex-col gap-32">
|
|
@@ -118,4 +128,35 @@
|
|
|
118
128
|
align="start"
|
|
119
129
|
/>
|
|
120
130
|
</section>
|
|
131
|
+
|
|
132
|
+
<!-- Custom Trigger -->
|
|
133
|
+
<section>
|
|
134
|
+
<h2 class="text-default-emphasis text-primary mb-8">Custom Trigger</h2>
|
|
135
|
+
<p class="text-small text-secondary mb-12">
|
|
136
|
+
Use the <code>trigger</code> snippet to make any element the trigger. Spread
|
|
137
|
+
<code>props</code> onto a single focusable element — it carries the ref, click/keyboard
|
|
138
|
+
handling, and menu aria. Unlike <code>children</code> (wrapped in an extra button), this is
|
|
139
|
+
one tab stop and supports keyboard open + arrow navigation. With <code>typeahead</code>,
|
|
140
|
+
typing on the closed trigger picks the closest match and fires <code>onSelect</code> (like
|
|
141
|
+
<code>IIDropdownInput</code>).
|
|
142
|
+
</p>
|
|
143
|
+
<IIMenu
|
|
144
|
+
items={[
|
|
145
|
+
{label: 'Assign to me', value: 'me'},
|
|
146
|
+
{label: 'Unassign', value: 'none'},
|
|
147
|
+
{type: 'separator'},
|
|
148
|
+
{label: 'Ada Lovelace', value: 'ada'},
|
|
149
|
+
{label: 'Alan Turing', value: 'alan'},
|
|
150
|
+
]}
|
|
151
|
+
onSelect={value => (assigneeValue = value)}
|
|
152
|
+
align="start"
|
|
153
|
+
typeahead
|
|
154
|
+
>
|
|
155
|
+
{#snippet trigger({props})}
|
|
156
|
+
<IIButton {...props} variant="ghost" iconName="user">
|
|
157
|
+
{assigneeValue ? assigneeLabels[assigneeValue] : 'Assignee'}
|
|
158
|
+
</IIButton>
|
|
159
|
+
{/snippet}
|
|
160
|
+
</IIMenu>
|
|
161
|
+
</section>
|
|
121
162
|
</div>
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
$$bindings?: Bindings;
|
|
4
|
-
} & Exports;
|
|
5
|
-
(internal: unknown, props: {
|
|
6
|
-
$$events?: Events;
|
|
7
|
-
$$slots?: Slots;
|
|
8
|
-
}): Exports & {
|
|
9
|
-
$set?: any;
|
|
10
|
-
$on?: any;
|
|
11
|
-
};
|
|
12
|
-
z_$$bindings?: Bindings;
|
|
13
|
-
}
|
|
14
|
-
declare const IIMenuStories: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
-
[evt: string]: CustomEvent<any>;
|
|
16
|
-
}, {}, {}, string>;
|
|
17
|
-
type IIMenuStories = InstanceType<typeof IIMenuStories>;
|
|
1
|
+
declare const IIMenuStories: import("svelte").Component<Record<string, never>, {}, "">;
|
|
2
|
+
type IIMenuStories = ReturnType<typeof IIMenuStories>;
|
|
18
3
|
export default IIMenuStories;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import IIMenu from './IIMenu.svelte'
|
|
3
|
+
import {IIButton} from '../IIButton'
|
|
4
|
+
|
|
5
|
+
// Minimal fixture for the keyboard/tab-order/typeahead play tests: a single
|
|
6
|
+
// IIMenu driven by the `trigger` snippet — spread `props` onto one focusable
|
|
7
|
+
// element (here IIButton) so it is THE trigger (one tab stop, keyboard works).
|
|
8
|
+
// The consumer owns the displayed value, so we reflect the selection here.
|
|
9
|
+
let {onSelect}: {onSelect?: (value: string) => void} = $props()
|
|
10
|
+
|
|
11
|
+
const labels: Record<string, string> = {
|
|
12
|
+
me: 'Assign to me',
|
|
13
|
+
none: 'Unassigned',
|
|
14
|
+
ada: 'Ada Lovelace',
|
|
15
|
+
alan: 'Alan Turing',
|
|
16
|
+
}
|
|
17
|
+
let selected = $state('')
|
|
18
|
+
|
|
19
|
+
function handleSelect(value: string) {
|
|
20
|
+
selected = value
|
|
21
|
+
onSelect?.(value)
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<IIMenu
|
|
26
|
+
items={[
|
|
27
|
+
{label: 'Assign to me', value: 'me'},
|
|
28
|
+
{label: 'Unassign', value: 'none'},
|
|
29
|
+
{type: 'separator'},
|
|
30
|
+
{label: 'Ada Lovelace', value: 'ada'},
|
|
31
|
+
{label: 'Alan Turing', value: 'alan'},
|
|
32
|
+
]}
|
|
33
|
+
onSelect={handleSelect}
|
|
34
|
+
typeahead
|
|
35
|
+
>
|
|
36
|
+
{#snippet trigger({props})}
|
|
37
|
+
<IIButton {...props} variant="ghost" iconName="user">
|
|
38
|
+
{selected ? labels[selected] : 'Assignee'}
|
|
39
|
+
</IIButton>
|
|
40
|
+
{/snippet}
|
|
41
|
+
</IIMenu>
|
|
@@ -6,7 +6,15 @@
|
|
|
6
6
|
type Props = {
|
|
7
7
|
open?: boolean
|
|
8
8
|
onOpenChange?: (open: boolean) => void
|
|
9
|
-
|
|
9
|
+
/** Trigger content wrapped in the popover's own button. */
|
|
10
|
+
trigger?: Snippet
|
|
11
|
+
/**
|
|
12
|
+
* Make your own element THE trigger instead of wrapping it in a button.
|
|
13
|
+
* Spread `props` onto a single focusable element — it carries the ref,
|
|
14
|
+
* click/keydown, and popover aria, so there's one tab stop and the element's
|
|
15
|
+
* own focus styling applies. Takes precedence over `trigger`.
|
|
16
|
+
*/
|
|
17
|
+
triggerChild?: Snippet<[{props: Record<string, unknown>}]>
|
|
10
18
|
content: Snippet
|
|
11
19
|
side?: 'top' | 'right' | 'bottom' | 'left'
|
|
12
20
|
align?: 'start' | 'center' | 'end'
|
|
@@ -21,6 +29,7 @@
|
|
|
21
29
|
open = $bindable(false),
|
|
22
30
|
onOpenChange,
|
|
23
31
|
trigger,
|
|
32
|
+
triggerChild,
|
|
24
33
|
content,
|
|
25
34
|
side = 'bottom',
|
|
26
35
|
align = 'start',
|
|
@@ -36,9 +45,17 @@
|
|
|
36
45
|
</script>
|
|
37
46
|
|
|
38
47
|
<Popover.Root bind:open {onOpenChange}>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
48
|
+
{#if triggerChild}
|
|
49
|
+
<Popover.Trigger>
|
|
50
|
+
{#snippet child({props})}
|
|
51
|
+
{@render triggerChild({props})}
|
|
52
|
+
{/snippet}
|
|
53
|
+
</Popover.Trigger>
|
|
54
|
+
{:else}
|
|
55
|
+
<Popover.Trigger class={cn('[all:unset] cursor-default', triggerClass)}>
|
|
56
|
+
{@render trigger?.()}
|
|
57
|
+
</Popover.Trigger>
|
|
58
|
+
{/if}
|
|
42
59
|
<Popover.Portal>
|
|
43
60
|
<Popover.Content
|
|
44
61
|
{side}
|
|
@@ -2,7 +2,17 @@ import type { Snippet } from 'svelte';
|
|
|
2
2
|
type Props = {
|
|
3
3
|
open?: boolean;
|
|
4
4
|
onOpenChange?: (open: boolean) => void;
|
|
5
|
-
|
|
5
|
+
/** Trigger content wrapped in the popover's own button. */
|
|
6
|
+
trigger?: Snippet;
|
|
7
|
+
/**
|
|
8
|
+
* Make your own element THE trigger instead of wrapping it in a button.
|
|
9
|
+
* Spread `props` onto a single focusable element — it carries the ref,
|
|
10
|
+
* click/keydown, and popover aria, so there's one tab stop and the element's
|
|
11
|
+
* own focus styling applies. Takes precedence over `trigger`.
|
|
12
|
+
*/
|
|
13
|
+
triggerChild?: Snippet<[{
|
|
14
|
+
props: Record<string, unknown>;
|
|
15
|
+
}]>;
|
|
6
16
|
content: Snippet;
|
|
7
17
|
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
8
18
|
align?: 'start' | 'center' | 'end';
|
|
@@ -105,4 +105,25 @@
|
|
|
105
105
|
{/snippet}
|
|
106
106
|
</IIPopover>
|
|
107
107
|
</section>
|
|
108
|
+
|
|
109
|
+
<!-- Custom trigger (single tab stop) -->
|
|
110
|
+
<section>
|
|
111
|
+
<h2 class="text-default-emphasis text-primary mb-8">Custom Trigger (single tab stop)</h2>
|
|
112
|
+
<p class="text-small text-secondary mb-12">
|
|
113
|
+
Use <code>triggerChild</code> and spread <code>props</code> onto your own element so it IS the
|
|
114
|
+
trigger — one tab stop, its own focus ring, keyboard opens it. Unlike <code>trigger</code>
|
|
115
|
+
(wrapped in the popover's button), there's no extra focusable wrapper.
|
|
116
|
+
</p>
|
|
117
|
+
<IIPopover>
|
|
118
|
+
{#snippet triggerChild({props})}
|
|
119
|
+
<IIButton {...props} variant="secondary" size="sm">Open Popover</IIButton>
|
|
120
|
+
{/snippet}
|
|
121
|
+
{#snippet content()}
|
|
122
|
+
<div class="flex flex-col gap-8 w-200 p-12">
|
|
123
|
+
<p class="text-small-emphasis text-body">Single-trigger popover</p>
|
|
124
|
+
<p class="text-small text-secondary">The button above is the only tab stop.</p>
|
|
125
|
+
</div>
|
|
126
|
+
{/snippet}
|
|
127
|
+
</IIPopover>
|
|
128
|
+
</section>
|
|
108
129
|
</div>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import IIPopover from './IIPopover.svelte'
|
|
3
|
+
import {IIButton} from '../IIButton'
|
|
4
|
+
|
|
5
|
+
// Fixture for the play test: `triggerChild` spreads `props` onto the IIButton
|
|
6
|
+
// so it IS the trigger (one tab stop, its own focus ring, keyboard opens).
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<IIPopover>
|
|
10
|
+
{#snippet triggerChild({props})}
|
|
11
|
+
<IIButton {...props} variant="secondary">Open</IIButton>
|
|
12
|
+
{/snippet}
|
|
13
|
+
{#snippet content()}
|
|
14
|
+
<div class="p-12 w-200">
|
|
15
|
+
<p class="text-small text-secondary">Inside the popover.</p>
|
|
16
|
+
</div>
|
|
17
|
+
{/snippet}
|
|
18
|
+
</IIPopover>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const IIPopoverTriggerProof: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type IIPopoverTriggerProof = InstanceType<typeof IIPopoverTriggerProof>;
|
|
18
|
+
export default IIPopoverTriggerProof;
|