fluentui-svelte 0.5.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.
Files changed (259) hide show
  1. package/dist/components/app-surface/app-surface.svelte +96 -0
  2. package/dist/components/app-surface/app-surface.svelte.d.ts +22 -0
  3. package/dist/components/app-surface/docs/llms.md +73 -0
  4. package/dist/components/app-surface/types.d.ts +19 -0
  5. package/dist/components/app-surface/types.js +1 -0
  6. package/dist/components/app-window/app-window.d.ts +3 -0
  7. package/dist/components/app-window/app-window.js +3 -0
  8. package/dist/components/app-window/app-window.svelte +193 -0
  9. package/dist/components/app-window/app-window.svelte.d.ts +25 -0
  10. package/dist/components/app-window/docs/llms.md +119 -0
  11. package/dist/components/app-window/types.d.ts +66 -0
  12. package/dist/components/app-window/types.js +1 -0
  13. package/dist/components/auto-suggest-box/auto-suggest-box.svelte +47 -31
  14. package/dist/components/auto-suggest-box/auto-suggest-box.svelte.d.ts +2 -2
  15. package/dist/components/auto-suggest-box/docs/llms.md +34 -33
  16. package/dist/components/auto-suggest-box/option.svelte +6 -4
  17. package/dist/components/auto-suggest-box/types.d.ts +13 -16
  18. package/dist/components/avatar/avatar.svelte +4 -3
  19. package/dist/components/avatar/docs/llms.md +1 -1
  20. package/dist/components/avatar/type.d.ts +1 -1
  21. package/dist/components/badge/badge-icon.svelte +2 -2
  22. package/dist/components/badge/badge.svelte +2 -2
  23. package/dist/components/badge/docs/llms.md +2 -2
  24. package/dist/components/badge/types.d.ts +2 -2
  25. package/dist/components/breadcrumb/breadcrumb-button.svelte +2 -2
  26. package/dist/components/breadcrumb/breadcrumb-divider.svelte +2 -2
  27. package/dist/components/breadcrumb/breadcrumb-item.svelte +2 -2
  28. package/dist/components/breadcrumb/breadcrumb.svelte +10 -5
  29. package/dist/components/breadcrumb/docs/llms.md +11 -11
  30. package/dist/components/breadcrumb/types.d.ts +7 -7
  31. package/dist/components/button/button.svelte +2 -2
  32. package/dist/components/button/docs/llms.md +17 -17
  33. package/dist/components/button/split-button.svelte +7 -7
  34. package/dist/components/button/types.d.ts +5 -5
  35. package/dist/components/calendar-date-picker/calendar-date-picker.svelte +98 -10
  36. package/dist/components/calendar-date-picker/calendar-date-picker.svelte.d.ts +1 -1
  37. package/dist/components/calendar-date-picker/docs/llms.md +19 -14
  38. package/dist/components/calendar-date-picker/types.d.ts +22 -8
  39. package/dist/components/calendar-view/calendar-view-days.svelte +3 -2
  40. package/dist/components/calendar-view/calendar-view-grid.js +8 -3
  41. package/dist/components/calendar-view/calendar-view-item.svelte +10 -4
  42. package/dist/components/calendar-view/calendar-view-months.svelte +3 -2
  43. package/dist/components/calendar-view/calendar-view-years.svelte +3 -2
  44. package/dist/components/calendar-view/calendar-view.svelte +11 -4
  45. package/dist/components/calendar-view/calendar-view.svelte.js +5 -0
  46. package/dist/components/calendar-view/docs/llms.md +20 -19
  47. package/dist/components/calendar-view/types.d.ts +6 -1
  48. package/dist/components/card/card-footer.svelte +2 -2
  49. package/dist/components/card/card-header.svelte +5 -4
  50. package/dist/components/card/card-preview.svelte +13 -2
  51. package/dist/components/card/card.svelte +5 -5
  52. package/dist/components/card/docs/llms.md +22 -21
  53. package/dist/components/card/types.d.ts +8 -4
  54. package/dist/components/checkbox/checkbox.svelte +47 -26
  55. package/dist/components/checkbox/checkbox.svelte.d.ts +3 -24
  56. package/dist/components/checkbox/docs/llms.md +24 -23
  57. package/dist/components/checkbox/types.d.ts +10 -23
  58. package/dist/components/date-picker/date-picker.svelte +98 -27
  59. package/dist/components/date-picker/date-picker.svelte.d.ts +1 -1
  60. package/dist/components/date-picker/docs/llms.md +23 -20
  61. package/dist/components/date-picker/types.d.ts +24 -15
  62. package/dist/components/dialog/dialog-actions.svelte +17 -2
  63. package/dist/components/dialog/dialog-content.svelte +2 -2
  64. package/dist/components/dialog/dialog-content.svelte.d.ts +1 -1
  65. package/dist/components/dialog/dialog-surface.svelte +130 -8
  66. package/dist/components/dialog/dialog-title.svelte +23 -6
  67. package/dist/components/dialog/dialog-trigger.svelte +8 -2
  68. package/dist/components/dialog/dialog-trigger.svelte.d.ts +1 -1
  69. package/dist/components/dialog/dialog.svelte +22 -11
  70. package/dist/components/dialog/docs/llms.md +56 -19
  71. package/dist/components/dialog/types.d.ts +31 -9
  72. package/dist/components/dialog/utils.d.ts +2 -0
  73. package/dist/components/dialog/utils.js +1 -0
  74. package/dist/components/divider/divider.svelte +6 -4
  75. package/dist/components/divider/types.d.ts +1 -1
  76. package/dist/components/dropdown/docs/llms.md +30 -28
  77. package/dist/components/dropdown/dropdown-option.svelte +17 -5
  78. package/dist/components/dropdown/dropdown.svelte +182 -84
  79. package/dist/components/dropdown/dropdown.svelte.d.ts +1 -1
  80. package/dist/components/dropdown/types.d.ts +26 -20
  81. package/dist/components/dropdown-select/docs/llms.md +24 -22
  82. package/dist/components/dropdown-select/dropdown-select-option.svelte +2 -2
  83. package/dist/components/dropdown-select/dropdown-select.svelte +42 -7
  84. package/dist/components/dropdown-select/types.d.ts +4 -4
  85. package/dist/components/expander/docs/llms.md +3 -3
  86. package/dist/components/expander/expander.svelte +13 -8
  87. package/dist/components/expander/types.d.ts +5 -5
  88. package/dist/components/flyout/docs/llms.md +1 -1
  89. package/dist/components/flyout/flyout.svelte +17 -6
  90. package/dist/components/flyout/types.d.ts +1 -1
  91. package/dist/components/hyperlink/docs/llms.md +6 -6
  92. package/dist/components/hyperlink/hyperlink.svelte +13 -4
  93. package/dist/components/hyperlink/types.d.ts +1 -1
  94. package/dist/components/info-bar/docs/llms.md +11 -10
  95. package/dist/components/info-bar/info-bar.svelte +3 -2
  96. package/dist/components/info-bar/types.d.ts +4 -0
  97. package/dist/components/label/docs/llms.md +75 -22
  98. package/dist/components/label/label-context.d.ts +14 -0
  99. package/dist/components/label/label-context.js +10 -0
  100. package/dist/components/label/label.svelte +153 -30
  101. package/dist/components/label/label.svelte.d.ts +1 -1
  102. package/dist/components/label/types.d.ts +48 -4
  103. package/dist/components/list-view/docs/llms.md +103 -33
  104. package/dist/components/list-view/list-view-item-branch.svelte +257 -0
  105. package/dist/components/list-view/list-view-item-branch.svelte.d.ts +4 -0
  106. package/dist/components/list-view/list-view-item.svelte +164 -46
  107. package/dist/components/list-view/list-view-item.svelte.d.ts +5 -5
  108. package/dist/components/list-view/list-view.svelte +73 -25
  109. package/dist/components/list-view/types.d.ts +71 -8
  110. package/dist/components/list-view/utils.d.ts +10 -0
  111. package/dist/components/list-view/utils.js +17 -1
  112. package/dist/components/menu/docs/llms.md +98 -15
  113. package/dist/components/menu/menu-command-bar-item.svelte +61 -0
  114. package/dist/components/menu/menu-command-bar-item.svelte.d.ts +14 -0
  115. package/dist/components/menu/menu-command-bar.svelte +218 -0
  116. package/dist/components/menu/menu-command-bar.svelte.d.ts +21 -0
  117. package/dist/components/menu/menu-group.svelte +6 -3
  118. package/dist/components/menu/menu-item-checkbox.svelte +5 -4
  119. package/dist/components/menu/menu-item-radio.svelte +5 -4
  120. package/dist/components/menu/menu-item-switch.svelte +5 -4
  121. package/dist/components/menu/menu-item.svelte +5 -5
  122. package/dist/components/menu/menu-item.svelte.d.ts +2 -3
  123. package/dist/components/menu/menu-list.svelte +10 -1
  124. package/dist/components/menu/menu-popover.svelte +9 -5
  125. package/dist/components/menu/menu-trigger.svelte +2 -1
  126. package/dist/components/menu/menu.svelte.js +1 -0
  127. package/dist/components/menu/types.d.ts +62 -7
  128. package/dist/components/number-box/docs/llms.md +6 -4
  129. package/dist/components/number-box/number-box.svelte +35 -29
  130. package/dist/components/number-box/number-box.svelte.d.ts +1 -1
  131. package/dist/components/number-box/types.d.ts +1 -1
  132. package/dist/components/persona/docs/llms.md +29 -25
  133. package/dist/components/persona/persona.svelte +8 -6
  134. package/dist/components/persona/types.d.ts +4 -3
  135. package/dist/components/progress-bar/docs/llms.md +13 -13
  136. package/dist/components/progress-bar/progress-bar.svelte +6 -6
  137. package/dist/components/progress-bar/types.d.ts +4 -4
  138. package/dist/components/progress-ring/docs/llms.md +14 -14
  139. package/dist/components/progress-ring/progress-ring.svelte +5 -5
  140. package/dist/components/progress-ring/types.d.ts +3 -3
  141. package/dist/components/radio-button/docs/llms.md +11 -8
  142. package/dist/components/radio-button/radio-button.svelte +38 -12
  143. package/dist/components/radio-button/radio-button.svelte.d.ts +1 -1
  144. package/dist/components/radio-button/types.d.ts +11 -8
  145. package/dist/components/rating/docs/llms.md +111 -0
  146. package/dist/components/rating/rating.svelte +247 -0
  147. package/dist/components/rating/rating.svelte.d.ts +19 -0
  148. package/dist/components/rating/types.d.ts +44 -0
  149. package/dist/components/rating/types.js +1 -0
  150. package/dist/components/side-nav/docs/llms.md +110 -0
  151. package/dist/components/side-nav/side-nav-branch.svelte +43 -0
  152. package/dist/components/side-nav/side-nav-branch.svelte.d.ts +4 -0
  153. package/dist/components/side-nav/side-nav-item.svelte +75 -0
  154. package/dist/components/side-nav/side-nav-item.svelte.d.ts +25 -0
  155. package/dist/components/side-nav/side-nav-list.svelte +32 -0
  156. package/dist/components/side-nav/side-nav-list.svelte.d.ts +7 -0
  157. package/dist/components/side-nav/side-nav.d.ts +2 -0
  158. package/dist/components/side-nav/side-nav.js +2 -0
  159. package/dist/components/side-nav/side-nav.svelte +355 -0
  160. package/dist/components/side-nav/side-nav.svelte.d.ts +24 -0
  161. package/dist/components/side-nav/types.d.ts +149 -0
  162. package/dist/components/side-nav/types.js +1 -0
  163. package/dist/components/skeleton/docs/llms.md +1 -1
  164. package/dist/components/skeleton/skeleton.svelte +2 -2
  165. package/dist/components/skeleton/types.d.ts +1 -1
  166. package/dist/components/slider/docs/llms.md +31 -28
  167. package/dist/components/slider/slider.svelte +126 -61
  168. package/dist/components/slider/slider.svelte.d.ts +1 -3
  169. package/dist/components/slider/types.d.ts +21 -14
  170. package/dist/components/tab-view/docs/llms.md +7 -7
  171. package/dist/components/tab-view/tab-view-tab.svelte +16 -14
  172. package/dist/components/tab-view/tab-view.svelte +16 -9
  173. package/dist/components/tab-view/types.d.ts +6 -6
  174. package/dist/components/table/docs/llms.md +38 -33
  175. package/dist/components/table/table-body.svelte +2 -2
  176. package/dist/components/table/table-cell-actions.svelte +8 -2
  177. package/dist/components/table/table-cell-layout.svelte +2 -2
  178. package/dist/components/table/table-cell.svelte +2 -2
  179. package/dist/components/table/table-header-cell.svelte +2 -2
  180. package/dist/components/table/table-header.svelte +2 -2
  181. package/dist/components/table/table-row.svelte +2 -2
  182. package/dist/components/table/table-selection-cell.svelte +6 -6
  183. package/dist/components/table/table.svelte +2 -2
  184. package/dist/components/table/types.d.ts +11 -11
  185. package/dist/components/tag/docs/llms.md +383 -0
  186. package/dist/components/tag/tag-group.d.ts +2 -0
  187. package/dist/components/tag/tag-group.js +2 -0
  188. package/dist/components/tag/tag-group.svelte +117 -0
  189. package/dist/components/tag/tag-group.svelte.d.ts +20 -0
  190. package/dist/components/tag/tag.svelte +459 -0
  191. package/dist/components/tag/tag.svelte.d.ts +19 -0
  192. package/dist/components/tag/types.d.ts +137 -0
  193. package/dist/components/tag/types.js +1 -0
  194. package/dist/components/tag-picker/docs/llms.md +298 -0
  195. package/dist/components/tag-picker/option-group.svelte +51 -0
  196. package/dist/components/tag-picker/option-group.svelte.d.ts +4 -0
  197. package/dist/components/tag-picker/option.svelte +82 -0
  198. package/dist/components/tag-picker/option.svelte.d.ts +4 -0
  199. package/dist/components/tag-picker/tag-picker.d.ts +2 -0
  200. package/dist/components/tag-picker/tag-picker.js +2 -0
  201. package/dist/components/tag-picker/tag-picker.svelte +716 -0
  202. package/dist/components/tag-picker/tag-picker.svelte.d.ts +21 -0
  203. package/dist/components/tag-picker/types.d.ts +142 -0
  204. package/dist/components/tag-picker/types.js +1 -0
  205. package/dist/components/text-box/docs/llms.md +31 -4
  206. package/dist/components/text-box/text-box-button.svelte +3 -3
  207. package/dist/components/text-box/text-box-button.svelte.d.ts +1 -1
  208. package/dist/components/text-box/text-box.svelte +41 -14
  209. package/dist/components/text-box/types.d.ts +5 -5
  210. package/dist/components/textarea/docs/llms.md +4 -3
  211. package/dist/components/textarea/textarea.svelte +14 -6
  212. package/dist/components/textarea/types.d.ts +2 -4
  213. package/dist/components/time-picker/docs/llms.md +18 -15
  214. package/dist/components/time-picker/time-picker.svelte +133 -33
  215. package/dist/components/time-picker/time-picker.svelte.d.ts +1 -1
  216. package/dist/components/time-picker/types.d.ts +23 -13
  217. package/dist/components/title-bar/docs/llms.md +382 -0
  218. package/dist/components/title-bar/title-bar-left-controls.svelte +215 -0
  219. package/dist/components/title-bar/title-bar-left-controls.svelte.d.ts +22 -0
  220. package/dist/components/title-bar/title-bar-right-controls.svelte +190 -0
  221. package/dist/components/title-bar/title-bar-right-controls.svelte.d.ts +27 -0
  222. package/dist/components/title-bar/title-bar.d.ts +3 -0
  223. package/dist/components/title-bar/title-bar.js +4 -0
  224. package/dist/components/title-bar/title-bar.svelte +224 -0
  225. package/dist/components/title-bar/title-bar.svelte.d.ts +26 -0
  226. package/dist/components/title-bar/types.d.ts +165 -0
  227. package/dist/components/title-bar/types.js +1 -0
  228. package/dist/components/toggle-switch/docs/llms.md +11 -9
  229. package/dist/components/toggle-switch/toggle-switch.svelte +23 -14
  230. package/dist/components/toggle-switch/toggle-switch.svelte.d.ts +1 -1
  231. package/dist/components/toggle-switch/types.d.ts +12 -10
  232. package/dist/components/tooltip/docs/llms.md +1 -1
  233. package/dist/components/tooltip/tooltip.svelte +5 -4
  234. package/dist/components/tooltip/types.d.ts +1 -1
  235. package/dist/components/top-nav/docs/llms.md +1 -1
  236. package/dist/components/top-nav/top-nav-item.svelte +2 -2
  237. package/dist/components/top-nav/top-nav.svelte +2 -2
  238. package/dist/components/top-nav/types.d.ts +2 -2
  239. package/dist/components/tree-view/docs/llms.md +11 -11
  240. package/dist/components/tree-view/tree-view-item-content.svelte +3 -3
  241. package/dist/components/tree-view/tree-view-item.svelte +13 -5
  242. package/dist/components/tree-view/tree-view.svelte +20 -5
  243. package/dist/components/tree-view/tree-view.svelte.d.ts +1 -1
  244. package/dist/components/tree-view/tree-view.svelte.js +31 -3
  245. package/dist/components/tree-view/types.d.ts +7 -3
  246. package/dist/index.d.ts +25 -0
  247. package/dist/index.js +32 -0
  248. package/dist/internal/components/dynamic-carousel/dynamic-carousel.svelte +26 -5
  249. package/dist/internal/components/dynamic-carousel/dynamic-carousel.svelte.d.ts +2 -0
  250. package/dist/internal/constants.d.ts +0 -4
  251. package/dist/internal/constants.js +0 -4002
  252. package/dist/internal/index.d.ts +1 -0
  253. package/dist/internal/index.js +1 -0
  254. package/dist/internal/native-field.svelte.d.ts +44 -0
  255. package/dist/internal/native-field.svelte.js +85 -0
  256. package/dist/internal/utils.d.ts +16 -2
  257. package/dist/internal/utils.js +25 -3
  258. package/dist/types/index.d.ts +3 -3
  259. package/package.json +51 -37
@@ -1,52 +1,129 @@
1
1
  <script lang="ts">
2
+ import InfoRegular from 'fluentui-icons-svelte/InfoRegular.svelte';
3
+ import type { Attachment } from 'svelte/attachments';
2
4
  import type { LabelProps } from './types.js';
5
+ import { PREFIX } from '../../internal/constants.js';
6
+ import { RenderSoC } from '../../internal/index.js';
7
+ import { Tooltip } from '../../index.js';
8
+ import { setLabelContext } from './label-context.js';
9
+
10
+ const FALLBACK_ID = $props.id();
3
11
 
4
12
  let {
5
- ref = $bindable(),
13
+ id = `${PREFIX}-label-${FALLBACK_ID}`,
14
+ for: htmlFor,
15
+ ref = $bindable(null),
16
+ as = 'div',
17
+ wrapperRef = $bindable(null),
18
+ wrapperAttributes,
6
19
  class: classes,
7
20
  disabled,
8
21
  required,
9
22
  size = 'medium',
10
23
  weight = 'regular',
11
24
  label = 'Label Element',
12
- labelPosition = 'after',
25
+ labelPosition = 'above',
26
+ tooltipContent,
27
+ tooltipBadge = InfoRegular,
28
+ tooltipProps,
29
+ tooltipButtonAttributes,
13
30
  children,
14
31
  ...attributes
15
32
  }: LabelProps = $props();
33
+
34
+ /** The field inside the label, used to get its id */
35
+ let field = $state<() => string | null | undefined>();
36
+
37
+ const fieldId = $derived(htmlFor ?? `${id}-field`);
38
+
39
+ const INFO_ID = $derived(tooltipButtonAttributes?.id ?? `${id}-info`);
40
+
41
+ setLabelContext({
42
+ get labelId() {
43
+ return id;
44
+ },
45
+ get fieldId() {
46
+ return fieldId;
47
+ },
48
+ claim(report) {
49
+ if (field) return false;
50
+ field = report;
51
+ return true;
52
+ }
53
+ });
16
54
  </script>
17
55
 
18
- <label
56
+ <svelte:element
57
+ this={as}
58
+ {...wrapperAttributes}
19
59
  class={[
20
60
  'fs-label',
21
61
  `size-${size}`,
22
- `weight-${weight}`,
23
- classes,
24
62
  { disabled, required },
25
- (labelPosition === 'above' || labelPosition === 'below') && 'column'
63
+ (labelPosition === 'above' || labelPosition === 'below') && 'column',
64
+ wrapperAttributes?.class
26
65
  ]}
27
- bind:this={ref}
28
- {...attributes}
66
+ bind:this={wrapperRef}
29
67
  >
30
68
  {#if labelPosition === 'before' || labelPosition === 'above'}
31
- <span>
32
- {label}
33
- {#if required}
34
- <abbr title={required.message || label}>{required.abbr ?? '*'}</abbr>
35
- {/if}
36
- </span>
69
+ {@render labelText()}
37
70
  {/if}
38
71
 
39
72
  {@render children?.()}
40
73
 
41
74
  {#if labelPosition === 'after' || labelPosition === 'below'}
42
- <span>
43
- {label}
44
- {#if required}
45
- <abbr title={required.message || label}>{required.abbr ?? '*'}</abbr>
46
- {/if}
75
+ {@render labelText()}
76
+ {/if}
77
+ </svelte:element>
78
+
79
+ {#snippet labelText()}
80
+ {#if tooltipContent}
81
+ <!-- The badge sits beside the label text, not in it, or its name would join the name of the field. -->
82
+ <span class={['fs-label-heading', `size-${size}`]}>
83
+ {@render text()}
84
+ <Tooltip
85
+ withArrow
86
+ placement="top"
87
+ {...tooltipProps}
88
+ content={tooltipContent}
89
+ relationship="description"
90
+ children={badge}
91
+ />
47
92
  </span>
93
+ {:else}
94
+ {@render text()}
48
95
  {/if}
49
- </label>
96
+ {/snippet}
97
+
98
+ {#snippet badge(attrs: { 'aria-describedby'?: string }, attach: Attachment)}
99
+ <button
100
+ type="button"
101
+ aria-label="More information"
102
+ {...tooltipButtonAttributes}
103
+ {...attrs}
104
+ id={INFO_ID}
105
+ aria-labelledby={tooltipButtonAttributes?.['aria-labelledby'] ?? `${id} ${INFO_ID}`}
106
+ class={['fs-label-info', tooltipButtonAttributes?.class]}
107
+ {@attach attach}
108
+ >
109
+ <RenderSoC SoC={tooltipBadge} />
110
+ </button>
111
+ {/snippet}
112
+
113
+ {#snippet text()}
114
+ <label
115
+ {...attributes}
116
+ {id}
117
+ for={field ? field() : fieldId}
118
+ class={['fs-label-text', `size-${size}`, `weight-${weight}`, classes]}
119
+ bind:this={ref}
120
+ >
121
+ {label}
122
+ {#if required}
123
+ <abbr aria-hidden="true" title={required.message || label}>{required.abbr ?? '*'}</abbr>
124
+ {/if}
125
+ </label>
126
+ {/snippet}
50
127
 
51
128
  <style>
52
129
  .fs-label {
@@ -58,24 +135,14 @@
58
135
  align-items: flex-start;
59
136
  }
60
137
  &.size-small {
61
- font-size: var(--fs-caption-font-size);
62
- letter-spacing: 0.04em;
63
138
  gap: 0.25rem;
64
139
  }
65
140
  &.size-medium {
66
- font-size: var(--fs-body-font-size);
67
141
  gap: 0.375rem;
68
142
  }
69
143
  &.size-large {
70
- font-size: var(--fs-subtitle2-font-size);
71
144
  gap: 0.5rem;
72
145
  }
73
- &.weight-regular {
74
- font-weight: 400;
75
- }
76
- &.weight-semibold {
77
- font-weight: 600;
78
- }
79
146
  &.disabled {
80
147
  color: var(--fs-text-disabled);
81
148
  pointer-events: none;
@@ -91,5 +158,61 @@
91
158
  color: var(--fs-text-disabled);
92
159
  }
93
160
  }
161
+ & .fs-label-heading {
162
+ display: inline-flex;
163
+ align-items: center;
164
+ gap: 0.25rem;
165
+ &.size-small .fs-label-info {
166
+ font-size: 0.75rem;
167
+ }
168
+ &.size-large .fs-label-info {
169
+ font-size: 1.25rem;
170
+ }
171
+ }
172
+ & .fs-label-info {
173
+ display: inline-flex;
174
+ align-items: center;
175
+ padding: 0;
176
+ border: none;
177
+ border-radius: var(--fs-control-border-radius);
178
+ background: none;
179
+ color: var(--fs-text-secondary);
180
+ font-size: 1rem;
181
+ cursor: pointer;
182
+ &:hover {
183
+ color: var(--fs-text-primary);
184
+ }
185
+ &:focus-visible {
186
+ outline: 0.125rem var(--fs-focus-stroke-outer) solid;
187
+ outline-offset: 0.063rem;
188
+ }
189
+ & :global(svg) {
190
+ inline-size: 1em;
191
+ block-size: 1em;
192
+ }
193
+ }
194
+ & .fs-label-text {
195
+ &.size-small {
196
+ font-size: var(--fs-caption-font-size);
197
+ letter-spacing: 0.04em;
198
+ }
199
+ &.size-medium {
200
+ font-size: var(--fs-body-font-size);
201
+ }
202
+ &.size-large {
203
+ font-size: var(--fs-subtitle2-font-size);
204
+ }
205
+ &.weight-regular {
206
+ font-weight: 400;
207
+ }
208
+ &.weight-semibold {
209
+ font-weight: 600;
210
+ }
211
+ }
212
+ &:global(:has(*:user-invalid)) {
213
+ & .fs-label-text {
214
+ color: var(--fs-system-critical);
215
+ }
216
+ }
94
217
  }
95
218
  </style>
@@ -1,4 +1,4 @@
1
1
  import type { LabelProps } from './types.ts';
2
- declare const Label: import("svelte").Component<LabelProps, {}, "ref">;
2
+ declare const Label: import("svelte").Component<LabelProps, {}, "ref" | "wrapperRef">;
3
3
  type Label = ReturnType<typeof Label>;
4
4
  export default Label;
@@ -1,8 +1,27 @@
1
- import type { HTMLLabelAttributes } from 'svelte/elements';
1
+ import type { Component, Snippet } from 'svelte';
2
+ import type { HTMLAttributes, HTMLButtonAttributes, HTMLLabelAttributes } from 'svelte/elements';
2
3
  import type { Sizes } from '../../types/index.js';
4
+ import type { TooltipProps } from '../tooltip/types.ts';
3
5
  /** @propsmith LabelProps */
4
6
  export type LabelProps = {
5
- /** The text of the label. Falls back to the rendered children.
7
+ /** The element used to wrap the label and its field.
8
+ * @default 'div'
9
+ */
10
+ as?: 'div' | 'span';
11
+ /** The field described by the label, rendered beside the label text.
12
+ * @type Snippet
13
+ */
14
+ children?: Snippet;
15
+ /** The DOM reference of the wrapper element.
16
+ * @type HTMLDivElement | HTMLSpanElement
17
+ * @bindable
18
+ */
19
+ wrapperRef?: HTMLDivElement | HTMLSpanElement | null;
20
+ /** The attributes to spread on the wrapper element.
21
+ * @type HTMLAttributes
22
+ */
23
+ wrapperAttributes?: HTMLAttributes<HTMLDivElement | HTMLSpanElement>;
24
+ /** The text of the label.
6
25
  * @default 'Label Element'
7
26
  */
8
27
  label?: string;
@@ -28,5 +47,30 @@ export type LabelProps = {
28
47
  /** The DOM reference of the label element.
29
48
  * @bindable
30
49
  */
31
- ref?: HTMLLabelElement;
32
- } & HTMLLabelAttributes;
50
+ ref?: HTMLLabelElement | null;
51
+ /** The id of the label element. A control inside the label is named after it, including a picker whose visible control stands in for its native field.
52
+ * @default Generated
53
+ */
54
+ id?: string;
55
+ /** The id of the field the label is for. Without it, the label is for the first field inside it, which takes a generated id when it has none of its own. With `labelPosition` `before` or `above` and a field that has an id of its own, pass that id here, so the server renders the association too.
56
+ * @default The field inside
57
+ */
58
+ for?: string;
59
+ /** More about the field, in a tooltip shown from a badge after the label text, on hover and on focus. People cannot move into a tooltip, so keep links and buttons out of it.
60
+ * @type string | Snippet | Component
61
+ */
62
+ tooltipContent?: string | Snippet | Component;
63
+ /** What the badge that shows the tooltip displays. Only rendered with `tooltipContent`.
64
+ * @type Snippet | Component
65
+ * @default InfoRegular
66
+ */
67
+ tooltipBadge?: Snippet | Component;
68
+ /** The props to spread on the tooltip.
69
+ * @type TooltipProps
70
+ */
71
+ tooltipProps?: Omit<TooltipProps, 'content' | 'relationship' | 'children'>;
72
+ /** The attributes to spread on the button of the badge. Its name is the label text followed by its `aria-label`.
73
+ * @type HTMLButtonAttributes
74
+ */
75
+ tooltipButtonAttributes?: HTMLButtonAttributes;
76
+ } & Omit<HTMLLabelAttributes, 'for'>;
@@ -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
- > **Best practices:** Please check the Fluent UI React List best practices for guidance.
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
- This option allows you to set keyboard navigation based on your needs. For view-only data, you do not need to set this unless the items perform some action. If your items have multiple actionable elements within the ListViewItem, like buttons or menus, you can set this to composite.
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 it 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. Note: every actionable element inside this ListViewItem, except the checkbox, must call e.stopPropagation().
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={(e) => {
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
- | `selectionMode` | `'none'` &#124; `'single'` &#124; `'multiselect'` &#124; `'extended'` | `'none'` | How many items can be selected, and how the selection is made. |
141
- | `navigationMode` | `'items'` &#124; `'composite'` | `'items'` | Whether the list itself takes a single tab stop, or every item takes its own. |
142
- | `selectedItems` _bindable_ | `string[]` | | The values of the selected items. |
143
- | `shape` | `'circular'` &#124; `'rounded'` &#124; `'square'` | `'rounded'` | The items can have a circular, rounded or square shape. |
144
- | `onSelectionChange` | `(e: Event, selectedItems: string[]` &#124; `[]) => void` | | Called whenever the selection changes. |
145
- | `toggleOnClick` | `boolean` | `false` | When `selectionMode` is `'multiselect'`, clicking an item toggles its selection directly instead of requiring Ctrl/Cmd + click. |
146
- | `as` | `'ul'` &#124; `'ol'` &#124; `'div'` | `'ul'` | The HTML element to render the list as. |
147
- | `ref` _bindable_ | `HTMLUListElement` &#124; `HTMLOListElement` &#124; `HTMLDivElement` | | The DOM reference of the list element. |
148
- | `disableTabspot` | `boolean` | `false` | Opts the list out of the tabspot focus management, to wire your own. |
149
- | HTML Attributes | | | |
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'` &#124; `'single'` &#124; `'multiselect'` &#124; `'extended'` | `'none'` | How many items can be selected, and how the selection is made. |
189
+ | `navigationMode` | `'items'` &#124; `'composite'` | `'items'` | Whether the list itself takes a single tab stop, or every item takes its own. |
190
+ | `manageSpecialKeys` | `boolean` &#124; `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'` &#124; `'rounded'` &#124; `'square'` | `'rounded'` | The items can have a circular, rounded or square shape. |
193
+ | `onSelectionChange` | `(e: Event, selectedItems: string[]` &#124; `[]) => 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'` &#124; `'ol'` &#124; `'div'` | `'ul'` | The HTML element to render the list as. |
196
+ | `ref` _bindable_ | `HTMLUListElement` &#124; `HTMLOListElement` &#124; `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 | Default | Description |
159
- | ---------------- | ------------------------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------ |
160
- | `as` | `'li'` &#124; `'a'` &#124; `'div'` | `'li'` | The HTML element to render the item as. |
161
- | `shape` | `'circular'` &#124; `'rounded'` &#124; `'square'` | | The item can have a circular, rounded or square shape. Inherited from the list by default. |
162
- | `value` | `string` | | The value reported to the list when the item is selected. Falls back to a generated id. |
163
- | `active` | `boolean` | | Renders the item in its pressed state. |
164
- | `role` | `'treeitem'` &#124; `'menuitem'` &#124; `'option'` &#124; `'row'` | | The ARIA role of the item. Derived from the list by default. |
165
- | `disabled` | `boolean` | | Disables the user interaction. |
166
- | `checkmark` | `CheckboxProps` | | The props to spread on the checkbox rendered when the list is multiselect. |
167
- | `onAction` | `(e: MouseEvent, value: string) => void` | | Called when the item is clicked or activated with the keyboard. |
168
- | `onfocus` | `(e: Event, value: string) => void` | | Called when the item receives the focus. |
169
- | `ref` _bindable_ | `HTMLLIElement` &#124; `HTMLAnchorElement` &#124; `HTMLDivElement` | | The DOM reference of the item element. |
170
- | HTML Attributes | | | |
207
+ | Name | Type | Default | Description |
208
+ | ---------------- | --------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
209
+ | `as` | `'li'` &#124; `'a'` &#124; `'button'` &#124; `'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'` &#124; `'rounded'` &#124; `'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'` &#124; `'menuitem'` &#124; `'option'` &#124; `'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` &#124; `HTMLAnchorElement` &#124; `HTMLButtonElement` &#124; `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` &#124; `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'` &#124; `'rounded'` &#124; `'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` &#124; `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 -->