fluentui-svelte 0.6.0 → 0.7.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/dist/components/app-surface/app-surface.svelte +96 -0
- package/dist/components/app-surface/app-surface.svelte.d.ts +22 -0
- package/dist/components/app-surface/docs/llms.md +73 -0
- package/dist/components/app-surface/types.d.ts +19 -0
- package/dist/components/app-surface/types.js +1 -0
- package/dist/components/app-window/app-window.d.ts +3 -0
- package/dist/components/app-window/app-window.js +3 -0
- package/dist/components/app-window/app-window.svelte +193 -0
- package/dist/components/app-window/app-window.svelte.d.ts +25 -0
- package/dist/components/app-window/docs/llms.md +119 -0
- package/dist/components/app-window/types.d.ts +66 -0
- package/dist/components/app-window/types.js +1 -0
- package/dist/components/auto-suggest-box/auto-suggest-box.svelte +47 -31
- package/dist/components/auto-suggest-box/auto-suggest-box.svelte.d.ts +2 -2
- package/dist/components/auto-suggest-box/docs/llms.md +34 -33
- package/dist/components/auto-suggest-box/option.svelte +6 -4
- package/dist/components/auto-suggest-box/types.d.ts +13 -16
- package/dist/components/avatar/avatar.svelte +4 -3
- package/dist/components/avatar/docs/llms.md +1 -1
- package/dist/components/avatar/type.d.ts +1 -1
- package/dist/components/badge/badge-icon.svelte +2 -2
- package/dist/components/badge/badge.svelte +2 -2
- package/dist/components/badge/docs/llms.md +2 -2
- package/dist/components/badge/types.d.ts +2 -2
- package/dist/components/breadcrumb/breadcrumb-button.svelte +2 -2
- package/dist/components/breadcrumb/breadcrumb-divider.svelte +2 -2
- package/dist/components/breadcrumb/breadcrumb-item.svelte +2 -2
- package/dist/components/breadcrumb/breadcrumb.svelte +10 -5
- package/dist/components/breadcrumb/docs/llms.md +11 -11
- package/dist/components/breadcrumb/types.d.ts +7 -7
- package/dist/components/button/button.svelte +2 -2
- package/dist/components/button/docs/llms.md +17 -17
- package/dist/components/button/split-button.svelte +7 -7
- package/dist/components/button/types.d.ts +5 -5
- package/dist/components/calendar-date-picker/calendar-date-picker.svelte +98 -10
- package/dist/components/calendar-date-picker/calendar-date-picker.svelte.d.ts +1 -1
- package/dist/components/calendar-date-picker/docs/llms.md +19 -14
- package/dist/components/calendar-date-picker/types.d.ts +22 -8
- package/dist/components/calendar-view/calendar-view-days.svelte +3 -2
- package/dist/components/calendar-view/calendar-view-grid.js +8 -3
- package/dist/components/calendar-view/calendar-view-item.svelte +10 -4
- package/dist/components/calendar-view/calendar-view-months.svelte +3 -2
- package/dist/components/calendar-view/calendar-view-years.svelte +3 -2
- package/dist/components/calendar-view/calendar-view.svelte +11 -4
- package/dist/components/calendar-view/calendar-view.svelte.js +5 -0
- package/dist/components/calendar-view/docs/llms.md +20 -19
- package/dist/components/calendar-view/types.d.ts +6 -1
- package/dist/components/card/card-footer.svelte +2 -2
- package/dist/components/card/card-header.svelte +5 -4
- package/dist/components/card/card-preview.svelte +13 -2
- package/dist/components/card/card.svelte +5 -5
- package/dist/components/card/docs/llms.md +22 -21
- package/dist/components/card/types.d.ts +8 -4
- package/dist/components/checkbox/checkbox.svelte +47 -26
- package/dist/components/checkbox/checkbox.svelte.d.ts +3 -24
- package/dist/components/checkbox/docs/llms.md +24 -23
- package/dist/components/checkbox/types.d.ts +10 -23
- package/dist/components/date-picker/date-picker.svelte +98 -27
- package/dist/components/date-picker/date-picker.svelte.d.ts +1 -1
- package/dist/components/date-picker/docs/llms.md +23 -20
- package/dist/components/date-picker/types.d.ts +24 -15
- package/dist/components/dialog/dialog-actions.svelte +2 -2
- package/dist/components/dialog/dialog-content.svelte +2 -2
- package/dist/components/dialog/dialog-surface.svelte +102 -9
- package/dist/components/dialog/dialog-title.svelte +2 -2
- package/dist/components/dialog/dialog-trigger.svelte +2 -2
- package/dist/components/dialog/dialog.svelte +22 -11
- package/dist/components/dialog/docs/llms.md +56 -19
- package/dist/components/dialog/types.d.ts +25 -7
- package/dist/components/divider/divider.svelte +6 -4
- package/dist/components/divider/types.d.ts +1 -1
- package/dist/components/dropdown/docs/llms.md +30 -28
- package/dist/components/dropdown/dropdown-option.svelte +17 -5
- package/dist/components/dropdown/dropdown.svelte +182 -84
- package/dist/components/dropdown/dropdown.svelte.d.ts +1 -1
- package/dist/components/dropdown/types.d.ts +26 -20
- package/dist/components/dropdown-select/docs/llms.md +24 -22
- package/dist/components/dropdown-select/dropdown-select-option.svelte +2 -2
- package/dist/components/dropdown-select/dropdown-select.svelte +42 -7
- package/dist/components/dropdown-select/types.d.ts +4 -4
- package/dist/components/expander/docs/llms.md +3 -3
- package/dist/components/expander/expander.svelte +13 -8
- package/dist/components/expander/types.d.ts +5 -5
- package/dist/components/flyout/docs/llms.md +1 -1
- package/dist/components/flyout/flyout.svelte +17 -6
- package/dist/components/flyout/types.d.ts +1 -1
- package/dist/components/hyperlink/docs/llms.md +6 -6
- package/dist/components/hyperlink/hyperlink.svelte +13 -4
- package/dist/components/hyperlink/types.d.ts +1 -1
- package/dist/components/info-bar/docs/llms.md +11 -10
- package/dist/components/info-bar/info-bar.svelte +3 -2
- package/dist/components/info-bar/types.d.ts +4 -0
- package/dist/components/label/docs/llms.md +75 -22
- package/dist/components/label/label-context.d.ts +14 -0
- package/dist/components/label/label-context.js +10 -0
- package/dist/components/label/label.svelte +153 -30
- package/dist/components/label/label.svelte.d.ts +1 -1
- package/dist/components/label/types.d.ts +48 -4
- package/dist/components/list-view/docs/llms.md +103 -33
- package/dist/components/list-view/list-view-item-branch.svelte +257 -0
- package/dist/components/list-view/list-view-item-branch.svelte.d.ts +4 -0
- package/dist/components/list-view/list-view-item.svelte +164 -46
- package/dist/components/list-view/list-view-item.svelte.d.ts +5 -5
- package/dist/components/list-view/list-view.svelte +73 -25
- package/dist/components/list-view/types.d.ts +71 -8
- package/dist/components/list-view/utils.d.ts +10 -0
- package/dist/components/list-view/utils.js +17 -1
- package/dist/components/menu/docs/llms.md +98 -15
- package/dist/components/menu/menu-command-bar-item.svelte +61 -0
- package/dist/components/menu/menu-command-bar-item.svelte.d.ts +14 -0
- package/dist/components/menu/menu-command-bar.svelte +218 -0
- package/dist/components/menu/menu-command-bar.svelte.d.ts +21 -0
- package/dist/components/menu/menu-group.svelte +6 -3
- package/dist/components/menu/menu-item-checkbox.svelte +5 -4
- package/dist/components/menu/menu-item-radio.svelte +5 -4
- package/dist/components/menu/menu-item-switch.svelte +5 -4
- package/dist/components/menu/menu-item.svelte +5 -5
- package/dist/components/menu/menu-item.svelte.d.ts +2 -3
- package/dist/components/menu/menu-list.svelte +10 -1
- package/dist/components/menu/menu-popover.svelte +9 -5
- package/dist/components/menu/menu-trigger.svelte +2 -1
- package/dist/components/menu/menu.svelte.js +1 -0
- package/dist/components/menu/types.d.ts +62 -7
- package/dist/components/number-box/docs/llms.md +6 -4
- package/dist/components/number-box/number-box.svelte +35 -29
- package/dist/components/number-box/number-box.svelte.d.ts +1 -1
- package/dist/components/number-box/types.d.ts +1 -1
- package/dist/components/persona/docs/llms.md +29 -25
- package/dist/components/persona/persona.svelte +8 -6
- package/dist/components/persona/types.d.ts +4 -3
- package/dist/components/progress-bar/docs/llms.md +13 -13
- package/dist/components/progress-bar/progress-bar.svelte +6 -6
- package/dist/components/progress-bar/types.d.ts +4 -4
- package/dist/components/progress-ring/docs/llms.md +14 -14
- package/dist/components/progress-ring/progress-ring.svelte +5 -5
- package/dist/components/progress-ring/types.d.ts +3 -3
- package/dist/components/radio-button/docs/llms.md +11 -8
- package/dist/components/radio-button/radio-button.svelte +38 -12
- package/dist/components/radio-button/radio-button.svelte.d.ts +1 -1
- package/dist/components/radio-button/types.d.ts +11 -8
- package/dist/components/rating/docs/llms.md +15 -14
- package/dist/components/rating/rating.svelte +66 -29
- package/dist/components/rating/rating.svelte.d.ts +1 -1
- package/dist/components/rating/types.d.ts +8 -8
- package/dist/components/side-nav/docs/llms.md +110 -0
- package/dist/components/side-nav/side-nav-branch.svelte +43 -0
- package/dist/components/side-nav/side-nav-branch.svelte.d.ts +4 -0
- package/dist/components/side-nav/side-nav-item.svelte +75 -0
- package/dist/components/side-nav/side-nav-item.svelte.d.ts +25 -0
- package/dist/components/side-nav/side-nav-list.svelte +32 -0
- package/dist/components/side-nav/side-nav-list.svelte.d.ts +7 -0
- package/dist/components/side-nav/side-nav.d.ts +2 -0
- package/dist/components/side-nav/side-nav.js +2 -0
- package/dist/components/side-nav/side-nav.svelte +355 -0
- package/dist/components/side-nav/side-nav.svelte.d.ts +24 -0
- package/dist/components/side-nav/types.d.ts +149 -0
- package/dist/components/side-nav/types.js +1 -0
- package/dist/components/skeleton/docs/llms.md +1 -1
- package/dist/components/skeleton/skeleton.svelte +2 -2
- package/dist/components/skeleton/types.d.ts +1 -1
- package/dist/components/slider/docs/llms.md +31 -28
- package/dist/components/slider/slider.svelte +126 -61
- package/dist/components/slider/slider.svelte.d.ts +1 -3
- package/dist/components/slider/types.d.ts +21 -14
- package/dist/components/tab-view/docs/llms.md +7 -7
- package/dist/components/tab-view/tab-view-tab.svelte +16 -14
- package/dist/components/tab-view/tab-view.svelte +16 -9
- package/dist/components/tab-view/types.d.ts +6 -6
- package/dist/components/table/docs/llms.md +38 -33
- package/dist/components/table/table-body.svelte +2 -2
- package/dist/components/table/table-cell-actions.svelte +8 -2
- package/dist/components/table/table-cell-layout.svelte +2 -2
- package/dist/components/table/table-cell.svelte +2 -2
- package/dist/components/table/table-header-cell.svelte +2 -2
- package/dist/components/table/table-header.svelte +2 -2
- package/dist/components/table/table-row.svelte +2 -2
- package/dist/components/table/table-selection-cell.svelte +6 -6
- package/dist/components/table/table.svelte +2 -2
- package/dist/components/table/types.d.ts +11 -11
- package/dist/components/tag/docs/llms.md +26 -26
- package/dist/components/tag/tag-group.svelte +2 -2
- package/dist/components/tag/tag.svelte +13 -12
- package/dist/components/tag/types.d.ts +6 -4
- package/dist/components/tag-picker/docs/llms.md +61 -55
- package/dist/components/tag-picker/option-group.svelte +17 -4
- package/dist/components/tag-picker/option-group.svelte.d.ts +1 -1
- package/dist/components/tag-picker/option.svelte +15 -4
- package/dist/components/tag-picker/tag-picker.svelte +137 -65
- package/dist/components/tag-picker/tag-picker.svelte.d.ts +2 -2
- package/dist/components/tag-picker/types.d.ts +36 -16
- package/dist/components/text-box/docs/llms.md +31 -4
- package/dist/components/text-box/text-box-button.svelte +3 -3
- package/dist/components/text-box/text-box-button.svelte.d.ts +1 -1
- package/dist/components/text-box/text-box.svelte +41 -14
- package/dist/components/text-box/types.d.ts +5 -5
- package/dist/components/textarea/docs/llms.md +4 -3
- package/dist/components/textarea/textarea.svelte +14 -6
- package/dist/components/textarea/types.d.ts +2 -4
- package/dist/components/time-picker/docs/llms.md +18 -15
- package/dist/components/time-picker/time-picker.svelte +133 -33
- package/dist/components/time-picker/time-picker.svelte.d.ts +1 -1
- package/dist/components/time-picker/types.d.ts +23 -13
- package/dist/components/title-bar/docs/llms.md +382 -0
- package/dist/components/title-bar/title-bar-left-controls.svelte +215 -0
- package/dist/components/title-bar/title-bar-left-controls.svelte.d.ts +22 -0
- package/dist/components/title-bar/title-bar-right-controls.svelte +190 -0
- package/dist/components/title-bar/title-bar-right-controls.svelte.d.ts +27 -0
- package/dist/components/title-bar/title-bar.d.ts +3 -0
- package/dist/components/title-bar/title-bar.js +4 -0
- package/dist/components/title-bar/title-bar.svelte +224 -0
- package/dist/components/title-bar/title-bar.svelte.d.ts +26 -0
- package/dist/components/title-bar/types.d.ts +165 -0
- package/dist/components/title-bar/types.js +1 -0
- package/dist/components/toggle-switch/docs/llms.md +11 -9
- package/dist/components/toggle-switch/toggle-switch.svelte +23 -14
- package/dist/components/toggle-switch/toggle-switch.svelte.d.ts +1 -1
- package/dist/components/toggle-switch/types.d.ts +12 -10
- package/dist/components/tooltip/docs/llms.md +1 -1
- package/dist/components/tooltip/tooltip.svelte +5 -4
- package/dist/components/tooltip/types.d.ts +1 -1
- package/dist/components/top-nav/docs/llms.md +1 -1
- package/dist/components/top-nav/top-nav-item.svelte +2 -2
- package/dist/components/top-nav/top-nav.svelte +2 -2
- package/dist/components/top-nav/types.d.ts +2 -2
- package/dist/components/tree-view/docs/llms.md +11 -11
- package/dist/components/tree-view/tree-view-item-content.svelte +3 -3
- package/dist/components/tree-view/tree-view-item.svelte +13 -5
- package/dist/components/tree-view/tree-view.svelte +20 -5
- package/dist/components/tree-view/tree-view.svelte.d.ts +1 -1
- package/dist/components/tree-view/tree-view.svelte.js +31 -3
- package/dist/components/tree-view/types.d.ts +7 -3
- package/dist/index.d.ts +18 -0
- package/dist/index.js +20 -0
- package/dist/internal/components/dynamic-carousel/dynamic-carousel.svelte +26 -5
- package/dist/internal/components/dynamic-carousel/dynamic-carousel.svelte.d.ts +2 -0
- package/dist/internal/index.d.ts +1 -0
- package/dist/internal/index.js +1 -0
- package/dist/internal/native-field.svelte.d.ts +44 -0
- package/dist/internal/native-field.svelte.js +85 -0
- package/dist/internal/utils.d.ts +16 -2
- package/dist/internal/utils.js +25 -3
- package/dist/types/index.d.ts +3 -3
- package/package.json +50 -36
|
@@ -20,7 +20,14 @@ The ListView is a component for rendering a set of vertically stacked items. The
|
|
|
20
20
|
|
|
21
21
|
## ListView API
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
### Best practices
|
|
24
|
+
|
|
25
|
+
- Keep lists that only display text out of the Tab sequence. Configure `navigationMode` on the outer ListView: use `items` for native link navigation and `composite` for selectable cards with secondary controls. Let the component manage item and control tabindex unless you opt out with `disableTabspot`.
|
|
26
|
+
- With the default grid roles in selectable composite lists, the component wraps each row's content in one `gridcell` and manages navigation to its controls. No manual `gridcell` wrappers are needed.
|
|
27
|
+
- Use `onAction` for an item's primary action and native buttons or links with `onclick` for secondary actions. Enter and Space both activate non-native actionable items; links retain native keyboard behavior. In composite selection rows, the checkmark changes selection independently, and secondary buttons and links do not trigger the row's action or selection.
|
|
28
|
+
- Keep the default roles for flat selection widgets; they depend on both `selectionMode` and `navigationMode`. Match the HTML tags: `ul`/`ol` with `li` items, or `as="div"` on both a card list and its items.
|
|
29
|
+
- Use ListViewItemBranch for expandable sublists. Branches are never selectable and manage their disclosure attributes and focus. Each nested list owns its selection. Set `role="list"` on each selectable list containing branches to preserve native list semantics.
|
|
30
|
+
- Give selectable ListView widgets an accessible name with `aria-label` or `aria-labelledby`. Give navigation a named `nav` landmark and mark the current link with `aria-current="page"`. Use meaningful visible text or `aria-label` for controls, a descriptive branch `label`, and stable item `value` strings when using selection.
|
|
24
31
|
|
|
25
32
|
### As
|
|
26
33
|
|
|
@@ -32,10 +39,50 @@ Instead of setting this on every ListViewItem, you can set it here and every ite
|
|
|
32
39
|
|
|
33
40
|
### Navigation Mode
|
|
34
41
|
|
|
35
|
-
|
|
42
|
+
`items` keeps each item in the Tab order; `composite` gives the entire list one tab stop and lets Right enter an item's secondary controls. Selection uses listbox/option roles in items mode, or grid/row/gridcell roles in composite mode. Set `role="list"` on each selectable navigation list with sublists to preserve native list semantics; use `aria-current` on links to announce the current page.
|
|
43
|
+
|
|
44
|
+
### Keyboard navigation
|
|
45
|
+
|
|
46
|
+
Up/Down move between siblings and Home/End reach the ends of the current level. Right opens a collapsed branch; Right on an expanded branch enters its sublist. Left closes an expanded branch; Left on a collapsed branch or child returns to its parent. Escape closes the nearest branch and restores focus to its button. Right also enters a composite item's controls; Left/Right move between them, and Left from the first control returns to the row. Enter activates links; Enter and Space activate buttons and selectable items. `disableTabspot` opts out of arrow-key focus management. Each nested ListView owns its selection state, so selecting a child does not select its parent.
|
|
36
47
|
|
|
37
48
|
## Examples
|
|
38
49
|
|
|
50
|
+
### Simple navigation
|
|
51
|
+
|
|
52
|
+
Use native anchors inside a named navigation landmark. Under `ul` or `ol`, ListViewItem wraps anchors and buttons in `li` elements.
|
|
53
|
+
|
|
54
|
+
```svelte
|
|
55
|
+
<nav aria-label="Main navigation">
|
|
56
|
+
<ListView>
|
|
57
|
+
<ListViewItem as="a" href="/">Home</ListViewItem>
|
|
58
|
+
<ListViewItem as="a" href="/docs">Documentation</ListViewItem>
|
|
59
|
+
<ListViewItem as="a" href="/docs/components/list-view" aria-current="page">ListView</ListViewItem>
|
|
60
|
+
</ListView>
|
|
61
|
+
</nav>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Navigation with sublists
|
|
65
|
+
|
|
66
|
+
Nest a ListView inside ListViewItemBranch. Branches are focusable disclosure buttons and never participate in selection. The component manages expanded state, aria-expanded, aria-controls, hidden content and focus restoration. Nested lists remain mounted when collapsed, preserving their selection. Hierarchy, indentation and keyboard groups are detected automatically; every nested list owns its selection. Use native list semantics: when selection is enabled, set `role="list"` on lists containing branches. Branches cannot be placed in listbox or grid lists. See the [WAI-ARIA disclosure pattern](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/).
|
|
67
|
+
|
|
68
|
+
```svelte
|
|
69
|
+
<script lang="ts">
|
|
70
|
+
import { ListView, ListViewItem, ListViewItemBranch } from 'fluentui-svelte';
|
|
71
|
+
</script>
|
|
72
|
+
|
|
73
|
+
<nav aria-label="Component navigation">
|
|
74
|
+
<ListView>
|
|
75
|
+
<ListViewItem as="a" href="/">Home</ListViewItem>
|
|
76
|
+
<ListViewItemBranch label="Components" expanded>
|
|
77
|
+
<ListView>
|
|
78
|
+
<ListViewItem as="a" href="/docs/components/button">Button</ListViewItem>
|
|
79
|
+
<ListViewItem as="a" href="/docs/components/checkbox">Checkbox</ListViewItem>
|
|
80
|
+
</ListView>
|
|
81
|
+
</ListViewItemBranch>
|
|
82
|
+
</ListView>
|
|
83
|
+
</nav>
|
|
84
|
+
```
|
|
85
|
+
|
|
39
86
|
### Value
|
|
40
87
|
|
|
41
88
|
Sets the value of the current item. You must set this when using the ListView selection system or if items change dynamically.
|
|
@@ -49,7 +96,7 @@ This event is triggered when clicking or tapping the element. It executes the pr
|
|
|
49
96
|
Use `selectionMode` (`single`, `multiselect`, or `extended`) to control how items are selected.
|
|
50
97
|
|
|
51
98
|
```svelte
|
|
52
|
-
<ListView selectionMode="multiselect" selectedItems={['Apple']}>
|
|
99
|
+
<ListView aria-label="Fruits" selectionMode="multiselect" selectedItems={['Apple']}>
|
|
53
100
|
{#each ['Apple', 'Banana', 'Cherry'] as item (item)}
|
|
54
101
|
<ListViewItem value={item}>{item}</ListViewItem>
|
|
55
102
|
{/each}
|
|
@@ -61,7 +108,7 @@ Use `selectionMode` (`single`, `multiselect`, or `extended`) to control how item
|
|
|
61
108
|
In a multiselect list, a plain click selects only that item and Ctrl/Cmd + click toggles it. Set `toggleOnClick` to make a plain click toggle the item directly.
|
|
62
109
|
|
|
63
110
|
```svelte
|
|
64
|
-
<ListView selectionMode="multiselect" toggleOnClick>
|
|
111
|
+
<ListView aria-label="Fruits" selectionMode="multiselect" toggleOnClick>
|
|
65
112
|
{#each ['Apple', 'Banana', 'Cherry'] as item (item)}
|
|
66
113
|
<ListViewItem value={item}>{item}</ListViewItem>
|
|
67
114
|
{/each}
|
|
@@ -77,7 +124,7 @@ Add and configure a checkbox for the element. You can use the same props for the
|
|
|
77
124
|
let selected = $state(['Apple']);
|
|
78
125
|
</script>
|
|
79
126
|
|
|
80
|
-
<ListView selectionMode="multiselect" bind:selectedItems={selected}>
|
|
127
|
+
<ListView aria-label="Fruits" selectionMode="multiselect" bind:selectedItems={selected}>
|
|
81
128
|
{#each ['Apple', 'Banana', 'Cherry'] as item (item)}
|
|
82
129
|
<ListViewItem value={item} checkmark={{}}>{item}</ListViewItem>
|
|
83
130
|
{/each}
|
|
@@ -88,7 +135,7 @@ Add and configure a checkbox for the element. You can use the same props for the
|
|
|
88
135
|
|
|
89
136
|
### Cards with a primary action
|
|
90
137
|
|
|
91
|
-
With `navigationMode` set to `composite` and a `selectionMode`, every item is a row. Clicking
|
|
138
|
+
With `navigationMode` set to `composite` and a `selectionMode`, every item is a row. Use `as="div"` for both the list and its card items to keep the HTML structure valid. Clicking a row runs its primary action (`onAction`), the checkbox toggles its selection, and any button inside is a secondary action. Use `checkmark.wrapperAttributes.style` to place the checkbox where you need it, like the top-right corner of the card. Secondary controls run their own actions without selecting the item or triggering its primary action.
|
|
92
139
|
|
|
93
140
|
```svelte
|
|
94
141
|
<script>
|
|
@@ -106,13 +153,13 @@ With `navigationMode` set to `composite` and a `selectionMode`, every item is a
|
|
|
106
153
|
{#each cards as card (card.name)}
|
|
107
154
|
{#snippet install()}
|
|
108
155
|
<Button
|
|
109
|
-
onclick={(
|
|
110
|
-
e.stopPropagation();
|
|
156
|
+
onclick={() => {
|
|
111
157
|
lastAction = 'Installed ' + card.name;
|
|
112
158
|
}}>Install</Button
|
|
113
159
|
>
|
|
114
160
|
{/snippet}
|
|
115
161
|
<ListViewItem
|
|
162
|
+
as="div"
|
|
116
163
|
value={card.name}
|
|
117
164
|
checkmark={{ wrapperAttributes: { style: 'position: absolute; top: 0.5rem; right: 0.5rem; z-index: 2;' } }}
|
|
118
165
|
style="padding: 0"
|
|
@@ -135,18 +182,20 @@ With `navigationMode` set to `composite` and a `selectionMode`, every item is a
|
|
|
135
182
|
<!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
|
|
136
183
|
<!-- props:ListViewProps -->
|
|
137
184
|
|
|
138
|
-
| Name | Type | Default | Description
|
|
139
|
-
| -------------------------- | --------------------------------------------------------------------- | ----------- |
|
|
140
|
-
| `
|
|
141
|
-
| `
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
149
|
-
|
|
|
185
|
+
| Name | Type | Default | Description |
|
|
186
|
+
| -------------------------- | --------------------------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
187
|
+
| `role` | `AriaRole` | | Overrides the list role and the roles derived for its items. Use `list` for nested navigation with independent selection. |
|
|
188
|
+
| `selectionMode` | `'none'` | `'single'` | `'multiselect'` | `'extended'` | `'none'` | How many items can be selected, and how the selection is made. |
|
|
189
|
+
| `navigationMode` | `'items'` | `'composite'` | `'items'` | Whether the list itself takes a single tab stop, or every item takes its own. |
|
|
190
|
+
| `manageSpecialKeys` | `boolean` | `TabspotRootOptions['manageSpecialKeys']` | `true` | Which special keys Tabspot handles at the root. Set individual keys to leave Escape to an enclosing panel. Omitted keys in an object are off. |
|
|
191
|
+
| `selectedItems` _bindable_ | `string[]` | | The values of the selected items. |
|
|
192
|
+
| `shape` | `'circular'` | `'rounded'` | `'square'` | `'rounded'` | The items can have a circular, rounded or square shape. |
|
|
193
|
+
| `onSelectionChange` | `(e: Event, selectedItems: string[]` | `[]) => void` | | Called whenever the selection changes. |
|
|
194
|
+
| `toggleOnClick` | `boolean` | `false` | When `selectionMode` is `'multiselect'`, clicking an item toggles its selection directly instead of requiring Ctrl/Cmd + click. |
|
|
195
|
+
| `as` | `'ul'` | `'ol'` | `'div'` | `'ul'` | The HTML element to render the list as. |
|
|
196
|
+
| `ref` _bindable_ | `HTMLUListElement` | `HTMLOListElement` | `HTMLDivElement` | | The DOM reference of the list element. |
|
|
197
|
+
| `disableTabspot` | `boolean` | `false` | Opts the list out of the tabspot focus management, to wire your own. |
|
|
198
|
+
| HTML Attributes | | | |
|
|
150
199
|
|
|
151
200
|
<!-- /props:ListViewProps -->
|
|
152
201
|
|
|
@@ -155,18 +204,39 @@ With `navigationMode` set to `composite` and a `selectionMode`, every item is a
|
|
|
155
204
|
<!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
|
|
156
205
|
<!-- props:ListViewItemProps -->
|
|
157
206
|
|
|
158
|
-
| Name | Type
|
|
159
|
-
| ---------------- |
|
|
160
|
-
| `as` | `'li'` | `'a'` | `'div'`
|
|
161
|
-
| `shape` | `'circular'` | `'rounded'` | `'square'`
|
|
162
|
-
| `value` | `string`
|
|
163
|
-
| `active` | `boolean`
|
|
164
|
-
| `role` | `'treeitem'` | `'menuitem'` | `'option'` | `'row'`
|
|
165
|
-
| `disabled` | `boolean`
|
|
166
|
-
| `checkmark` | `CheckboxProps`
|
|
167
|
-
| `onAction` | `(e: MouseEvent, value: string) => void`
|
|
168
|
-
| `onfocus` | `(e: Event, value: string) => void`
|
|
169
|
-
| `ref` _bindable_ | `HTMLLIElement` | `HTMLAnchorElement` | `HTMLDivElement` | | The DOM reference of the item element.
|
|
170
|
-
| HTML Attributes |
|
|
207
|
+
| Name | Type | Default | Description |
|
|
208
|
+
| ---------------- | --------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
209
|
+
| `as` | `'li'` | `'a'` | `'button'` | `'div'` | `'li'` | The HTML element to render the item as. Links and buttons are wrapped in a list item when the list renders as `ul` or `ol`. Use `li` or `div` for nested lists and content with multiple controls. Buttons cannot contain checkmarks or composite rows. |
|
|
210
|
+
| `shape` | `'circular'` | `'rounded'` | `'square'` | | The item can have a circular, rounded or square shape. Inherited from the list by default. |
|
|
211
|
+
| `value` | `string` | | The value reported to the list when the item is selected. Falls back to a generated id. |
|
|
212
|
+
| `active` | `boolean` | | Renders the item in its pressed state. |
|
|
213
|
+
| `role` | `'treeitem'` | `'menuitem'` | `'option'` | `'row'` | | The ARIA role of the item. Derived from the list by default. |
|
|
214
|
+
| `disabled` | `boolean` | | Disables the user interaction. |
|
|
215
|
+
| `checkmark` | `CheckboxProps` | | The props to spread on the checkbox rendered when the list is multiselect. |
|
|
216
|
+
| `onAction` | `(e: MouseEvent, value: string) => void` | | Called when the item is clicked or activated with the keyboard. |
|
|
217
|
+
| `onfocus` | `(e: Event, value: string) => void` | | Called when the item receives the focus. |
|
|
218
|
+
| `ref` _bindable_ | `HTMLLIElement` | `HTMLAnchorElement` | `HTMLButtonElement` | `HTMLDivElement` | | The DOM reference of the item element. |
|
|
219
|
+
| HTML Attributes | | | |
|
|
171
220
|
|
|
172
221
|
<!-- /props:ListViewItemProps -->
|
|
222
|
+
|
|
223
|
+
## ListViewItemBranch Props
|
|
224
|
+
|
|
225
|
+
<!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
|
|
226
|
+
<!-- props:ListViewItemBranchProps -->
|
|
227
|
+
|
|
228
|
+
| Name | Type | Default | Description |
|
|
229
|
+
| ---------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
230
|
+
| `label` | `string` | | The accessible label rendered in the disclosure button. |
|
|
231
|
+
| `icon` | `Snippet` | `Component` | | The decorative icon before the label. |
|
|
232
|
+
| `expanded` _bindable_ | `boolean` | `false` | Whether the nested content is visible. Branches only expand or collapse and are never selectable. |
|
|
233
|
+
| `onExpandedChange` | `(e: Event, expanded: boolean) => void` | | Called when a user expands or collapses the branch. |
|
|
234
|
+
| `disabled` | `boolean` | `false` | Disables the disclosure button. |
|
|
235
|
+
| `shape` | `'circular'` | `'rounded'` | `'square'` | | The disclosure button shape. Inherited from the list by default. |
|
|
236
|
+
| `ref` _bindable_ | `HTMLButtonElement` | | The DOM reference of the native disclosure button. Additional HTML attributes, including class and id, also target this button. |
|
|
237
|
+
| `wrapperRef` _bindable_ | `HTMLLIElement` | `HTMLDivElement` | | The DOM reference of the wrapper element, the list item that holds the button and the nested list. |
|
|
238
|
+
| `wrapperAttributes` | `HTMLAttributes` | | The attributes to spread on the wrapper element. |
|
|
239
|
+
| `children` | `Snippet` | | Nested ListView content, kept mounted while collapsed to preserve its selection. |
|
|
240
|
+
| `HTMLButtonAttributes` without `children`, `role`, `type`, `value`, `aria-expanded`, `aria-controls` | | | |
|
|
241
|
+
|
|
242
|
+
<!-- /props:ListViewItemBranchProps -->
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import ChevronDownRegular from 'fluentui-icons-svelte/ChevronDownRegular.svelte';
|
|
3
|
+
import { getTabspotAttributes, type TabspotNavigationEvent, type TabspotNodeOptions } from 'tabspot';
|
|
4
|
+
import { getGlobalFSContext } from '../../providers/fluentui-svelte/fluentui-svelte.js';
|
|
5
|
+
import { invokeHandlers, RenderSoC } from '../../internal/index.js';
|
|
6
|
+
import {
|
|
7
|
+
attachTabspot,
|
|
8
|
+
getListViewContext,
|
|
9
|
+
getListViewItemContext,
|
|
10
|
+
LIST_VIEW_SKIP,
|
|
11
|
+
setListViewItemContext
|
|
12
|
+
} from './utils.js';
|
|
13
|
+
import type { ListViewItemBranchProps } from './types.js';
|
|
14
|
+
|
|
15
|
+
const ID = $props.id();
|
|
16
|
+
const REGION_ID = `fs-list-view-branch-${ID}`;
|
|
17
|
+
const parent = getListViewContext();
|
|
18
|
+
const owner = getListViewItemContext();
|
|
19
|
+
const globalContext = getGlobalFSContext();
|
|
20
|
+
if (!parent) throw new Error('ListViewItemBranch must be used within a ListView');
|
|
21
|
+
const context = parent;
|
|
22
|
+
|
|
23
|
+
let {
|
|
24
|
+
label,
|
|
25
|
+
icon,
|
|
26
|
+
expanded = $bindable(false),
|
|
27
|
+
disabled = false,
|
|
28
|
+
shape,
|
|
29
|
+
ref = $bindable(null),
|
|
30
|
+
wrapperRef = $bindable(null),
|
|
31
|
+
wrapperAttributes,
|
|
32
|
+
class: classes,
|
|
33
|
+
onclick,
|
|
34
|
+
onkeydown,
|
|
35
|
+
onExpandedChange,
|
|
36
|
+
children,
|
|
37
|
+
...attributes
|
|
38
|
+
}: ListViewItemBranchProps = $props();
|
|
39
|
+
|
|
40
|
+
let regionRef: HTMLDivElement | undefined;
|
|
41
|
+
|
|
42
|
+
const wrapperTag = $derived.by(() => {
|
|
43
|
+
if (context.config.role !== undefined && context.config.role !== 'list') {
|
|
44
|
+
throw new Error('ListViewItemBranch requires a native list. Set role="list" on selectable navigation lists.');
|
|
45
|
+
}
|
|
46
|
+
if (owner?.as === 'a' || owner?.as === 'button') {
|
|
47
|
+
throw new Error('ListViewItemBranch must be outside links and buttons.');
|
|
48
|
+
}
|
|
49
|
+
return context.config.as === 'div' ? 'div' : 'li';
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
setListViewItemContext({
|
|
53
|
+
get as() {
|
|
54
|
+
return wrapperTag;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const tabspotConfig: TabspotNodeOptions | undefined = $derived(
|
|
59
|
+
context.config.disableTabspot
|
|
60
|
+
? undefined
|
|
61
|
+
: {
|
|
62
|
+
mover: {
|
|
63
|
+
axis: 'vertical',
|
|
64
|
+
items: '.fs-list-view-item-branch-trigger',
|
|
65
|
+
visibilityAware: 'Visible',
|
|
66
|
+
skip: LIST_VIEW_SKIP,
|
|
67
|
+
ignoreKeys: expanded ? ['ArrowLeft'] : ['ArrowRight']
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const tabspotAttributes = $derived(tabspotConfig && getTabspotAttributes(tabspotConfig));
|
|
73
|
+
|
|
74
|
+
const canceledKeys = new WeakSet<KeyboardEvent>();
|
|
75
|
+
|
|
76
|
+
function changeExpanded(event: Event, next: boolean) {
|
|
77
|
+
if (disabled || expanded === next) return;
|
|
78
|
+
expanded = next;
|
|
79
|
+
onExpandedChange?.(event, expanded);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Tabspot prevents Escape before native handlers. Record further cancellation by the consumer.
|
|
83
|
+
function trackCancellation(event: KeyboardEvent, run: () => void) {
|
|
84
|
+
const preventDefault = event.preventDefault;
|
|
85
|
+
event.preventDefault = () => {
|
|
86
|
+
canceledKeys.add(event);
|
|
87
|
+
preventDefault.call(event);
|
|
88
|
+
};
|
|
89
|
+
try {
|
|
90
|
+
run();
|
|
91
|
+
} finally {
|
|
92
|
+
event.preventDefault = preventDefault;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
97
|
+
if (onkeydown) trackCancellation(event, () => invokeHandlers(event, disabled, [onkeydown]));
|
|
98
|
+
if (event.defaultPrevented || disabled) return;
|
|
99
|
+
if (context.config.disableTabspot && (event.key === 'ArrowRight' || event.key === 'ArrowLeft')) return;
|
|
100
|
+
if ((event.key === 'ArrowRight' && !expanded) || (event.key === 'ArrowLeft' && expanded)) {
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
changeExpanded(event, !expanded);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function handleEscape(event: KeyboardEvent) {
|
|
107
|
+
if (
|
|
108
|
+
!expanded ||
|
|
109
|
+
event.key !== 'Escape' ||
|
|
110
|
+
(event.target as Element).closest('.fs-list-view-item-branch') !== wrapperRef
|
|
111
|
+
)
|
|
112
|
+
return;
|
|
113
|
+
if (disabled || canceledKeys.has(event) || (context.config.disableTabspot && event.defaultPrevented)) return;
|
|
114
|
+
event.preventDefault();
|
|
115
|
+
event.stopPropagation();
|
|
116
|
+
changeExpanded(event, false);
|
|
117
|
+
ref?.focus();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function guardEscape(event: TabspotNavigationEvent) {
|
|
121
|
+
if (expanded && event.direction === 'escape' && event.from?.closest('.fs-list-view-item-branch') === wrapperRef)
|
|
122
|
+
event.preventDefault();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function restoreFocusBeforeCollapse() {
|
|
126
|
+
if (!expanded && regionRef?.contains(document.activeElement)) ref?.focus();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
$effect.pre(restoreFocusBeforeCollapse);
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<svelte:element
|
|
133
|
+
this={wrapperTag}
|
|
134
|
+
role={wrapperTag === 'div' ? 'listitem' : undefined}
|
|
135
|
+
{...wrapperAttributes}
|
|
136
|
+
bind:this={wrapperRef}
|
|
137
|
+
class={['fs-list-view-item-branch', wrapperAttributes?.class]}
|
|
138
|
+
onkeydown={(event: KeyboardEvent) => {
|
|
139
|
+
const wrapperKeydown = wrapperAttributes?.onkeydown;
|
|
140
|
+
if (typeof wrapperKeydown === 'function')
|
|
141
|
+
trackCancellation(event, () => invokeHandlers(event, [], [wrapperKeydown]));
|
|
142
|
+
handleEscape(event);
|
|
143
|
+
}}
|
|
144
|
+
{...tabspotAttributes}
|
|
145
|
+
{@attach attachTabspot(tabspotConfig, guardEscape, globalContext?.state.tabspotInstance)}
|
|
146
|
+
>
|
|
147
|
+
<button
|
|
148
|
+
{...attributes}
|
|
149
|
+
class={['fs-list-view-item-branch-trigger', shape ?? context.config.shape, classes]}
|
|
150
|
+
{@attach (element) => {
|
|
151
|
+
ref = element;
|
|
152
|
+
return () => {
|
|
153
|
+
ref = null;
|
|
154
|
+
};
|
|
155
|
+
}}
|
|
156
|
+
type="button"
|
|
157
|
+
role={undefined}
|
|
158
|
+
{disabled}
|
|
159
|
+
aria-expanded={expanded}
|
|
160
|
+
aria-controls={REGION_ID}
|
|
161
|
+
onclick={(event) => {
|
|
162
|
+
invokeHandlers(event, disabled, [onclick]);
|
|
163
|
+
if (!event.defaultPrevented) changeExpanded(event, !expanded);
|
|
164
|
+
}}
|
|
165
|
+
onkeydown={handleKeydown}
|
|
166
|
+
>
|
|
167
|
+
{#if icon}
|
|
168
|
+
<span class="branch-icon" aria-hidden="true">
|
|
169
|
+
<RenderSoC SoC={icon} />
|
|
170
|
+
</span>
|
|
171
|
+
{/if}
|
|
172
|
+
<span class="fs-list-view-branch-label">{label}</span>
|
|
173
|
+
<ChevronDownRegular aria-hidden="true" width="1rem" height="1rem" class={['branch-chevron', { expanded }]} />
|
|
174
|
+
</button>
|
|
175
|
+
<div
|
|
176
|
+
id={REGION_ID}
|
|
177
|
+
{@attach (element) => {
|
|
178
|
+
regionRef = element;
|
|
179
|
+
return () => {
|
|
180
|
+
regionRef = undefined;
|
|
181
|
+
};
|
|
182
|
+
}}
|
|
183
|
+
class="fs-list-view-item-branch-region"
|
|
184
|
+
hidden={!expanded}
|
|
185
|
+
>
|
|
186
|
+
{@render children?.()}
|
|
187
|
+
</div>
|
|
188
|
+
</svelte:element>
|
|
189
|
+
|
|
190
|
+
<style>
|
|
191
|
+
.fs-list-view-item-branch {
|
|
192
|
+
list-style: none;
|
|
193
|
+
}
|
|
194
|
+
.fs-list-view-item-branch-trigger {
|
|
195
|
+
display: flex;
|
|
196
|
+
align-items: center;
|
|
197
|
+
justify-content: space-between;
|
|
198
|
+
gap: 0.5rem;
|
|
199
|
+
margin: 0.3rem 0;
|
|
200
|
+
width: 100%;
|
|
201
|
+
box-sizing: border-box;
|
|
202
|
+
padding: 0.275rem 0.713rem 0.4rem;
|
|
203
|
+
border: none;
|
|
204
|
+
border-radius: var(--fs-control-border-radius);
|
|
205
|
+
font: inherit;
|
|
206
|
+
font-size: var(--fs-body2-font-size);
|
|
207
|
+
text-align: start;
|
|
208
|
+
color: var(--fs-text-primary);
|
|
209
|
+
background: var(--fs-subtle-fill-transparent);
|
|
210
|
+
cursor: pointer;
|
|
211
|
+
&:hover:not(:disabled) {
|
|
212
|
+
background: var(--fs-subtle-fill-secondary);
|
|
213
|
+
}
|
|
214
|
+
&:active:not(:disabled) {
|
|
215
|
+
background: var(--fs-subtle-fill-tertiary);
|
|
216
|
+
}
|
|
217
|
+
&:focus-visible {
|
|
218
|
+
outline: 0.125rem solid var(--fs-focus-stroke-outer);
|
|
219
|
+
outline-offset: 0.063rem;
|
|
220
|
+
}
|
|
221
|
+
&:disabled {
|
|
222
|
+
color: var(--fs-text-disabled);
|
|
223
|
+
cursor: not-allowed;
|
|
224
|
+
}
|
|
225
|
+
&.square {
|
|
226
|
+
border-radius: 0;
|
|
227
|
+
}
|
|
228
|
+
&.circular {
|
|
229
|
+
border-radius: 50vw;
|
|
230
|
+
}
|
|
231
|
+
& :global(.branch-chevron) {
|
|
232
|
+
flex-shrink: 0;
|
|
233
|
+
margin-inline-start: auto;
|
|
234
|
+
font-size: 1rem;
|
|
235
|
+
}
|
|
236
|
+
& :global(.branch-chevron.expanded) {
|
|
237
|
+
rotate: 180deg;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
.branch-icon {
|
|
241
|
+
display: inline-flex;
|
|
242
|
+
align-items: center;
|
|
243
|
+
justify-content: center;
|
|
244
|
+
flex: none;
|
|
245
|
+
inline-size: 1rem;
|
|
246
|
+
/* As tall as a line of text, so a branch is as tall with its label as without it. */
|
|
247
|
+
block-size: 1lh;
|
|
248
|
+
& :global(svg) {
|
|
249
|
+
inline-size: 1rem;
|
|
250
|
+
block-size: 1rem;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
.fs-list-view-item-branch-region > :global(.fs-list-view) {
|
|
254
|
+
padding-inline-start: 1rem;
|
|
255
|
+
box-sizing: border-box;
|
|
256
|
+
}
|
|
257
|
+
</style>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ListViewItemBranchProps } from './types.ts';
|
|
2
|
+
declare const ListViewItemBranch: import("svelte").Component<ListViewItemBranchProps, {}, "ref" | "wrapperRef" | "expanded">;
|
|
3
|
+
type ListViewItemBranch = ReturnType<typeof ListViewItemBranch>;
|
|
4
|
+
export default ListViewItemBranch;
|