fluentui-svelte 0.3.0 → 0.4.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 (33) hide show
  1. package/dist/components/breadcrumb/breadcrumb-button.svelte +130 -0
  2. package/dist/components/breadcrumb/breadcrumb-button.svelte.d.ts +35 -0
  3. package/dist/components/breadcrumb/breadcrumb-divider.svelte +39 -0
  4. package/dist/components/breadcrumb/breadcrumb-divider.svelte.d.ts +14 -0
  5. package/dist/components/breadcrumb/breadcrumb-item.svelte +30 -0
  6. package/dist/components/breadcrumb/breadcrumb-item.svelte.d.ts +16 -0
  7. package/dist/components/breadcrumb/breadcrumb.svelte +101 -0
  8. package/dist/components/breadcrumb/breadcrumb.svelte.d.ts +25 -0
  9. package/dist/components/breadcrumb/docs/llms.md +193 -0
  10. package/dist/components/breadcrumb/types.d.ts +80 -0
  11. package/dist/components/breadcrumb/types.js +1 -0
  12. package/dist/components/tab-view/docs/llms.md +146 -0
  13. package/dist/components/tab-view/tab-view-tab.svelte +290 -0
  14. package/dist/components/tab-view/tab-view-tab.svelte.d.ts +20 -0
  15. package/dist/components/tab-view/tab-view.svelte +188 -0
  16. package/dist/components/tab-view/tab-view.svelte.d.ts +26 -0
  17. package/dist/components/tab-view/tab-view.svelte.js +15 -0
  18. package/dist/components/tab-view/types.d.ts +79 -0
  19. package/dist/components/tab-view/types.js +1 -0
  20. package/dist/components/top-nav/docs/llms.md +176 -0
  21. package/dist/components/top-nav/top-nav-item.svelte +234 -0
  22. package/dist/components/top-nav/top-nav-item.svelte.d.ts +41 -0
  23. package/dist/components/top-nav/top-nav.svelte +259 -0
  24. package/dist/components/top-nav/top-nav.svelte.d.ts +26 -0
  25. package/dist/components/top-nav/top-nav.svelte.js +18 -0
  26. package/dist/components/top-nav/types.d.ts +89 -0
  27. package/dist/components/top-nav/types.js +1 -0
  28. package/dist/css/class-darkmode.css +1 -1
  29. package/dist/css/media-darkmode.css +1 -1
  30. package/dist/css/theme.css +1 -1
  31. package/dist/index.d.ts +8 -0
  32. package/dist/index.js +14 -0
  33. package/package.json +1 -1
@@ -0,0 +1,130 @@
1
+ <script lang="ts" generics="T extends BreadcrumbItemGenerics = 'button'">
2
+ import { invokeHandlers, RenderSoC } from '../../internal/index.js';
3
+ import type { BreadcrumbButtonProps, BreadcrumbItemElementDOMType, BreadcrumbItemGenerics } from './types.js';
4
+
5
+ let {
6
+ as = 'button' as T,
7
+ ref = $bindable(),
8
+ icon,
9
+ iconPosition = 'before',
10
+ current = false,
11
+ disabled,
12
+ disabledFocusable = false,
13
+ onclick,
14
+ class: classes,
15
+ children,
16
+ ...attributes
17
+ }: BreadcrumbButtonProps<T> = $props();
18
+
19
+ const _as = $derived.by(() => {
20
+ if (as !== 'button' && as !== 'a') throw new Error(`Invalid tag: ${as}. Must be one of button, a`);
21
+ return as;
22
+ });
23
+
24
+ const nativelyDisabled = $derived(_as === 'button' && disabled && !disabledFocusable);
25
+ </script>
26
+
27
+ <!--
28
+ @component
29
+ A step of a `Breadcrumb` that can be activated: an anchor when it goes somewhere, a button when
30
+ it does something. The last step is the page itself, and `current` is what announces it.
31
+
32
+ - Usage:
33
+ ```tsx
34
+ <BreadcrumbButton as="a" href="/files" icon={FolderRegular}>Files</BreadcrumbButton>
35
+ <BreadcrumbButton current>This page</BreadcrumbButton>
36
+ ```
37
+ -->
38
+ <svelte:element
39
+ this={_as}
40
+ bind:this={ref as BreadcrumbItemElementDOMType[T]}
41
+ type={_as === 'button' ? 'button' : undefined}
42
+ disabled={nativelyDisabled || undefined}
43
+ aria-disabled={disabled || undefined}
44
+ aria-current={current ? 'page' : undefined}
45
+ class={['fs-breadcrumb-button', { current, disabled }, classes]}
46
+ onclick={(e: MouseEvent) => invokeHandlers(e, disabled, [onclick])}
47
+ {...attributes}
48
+ >
49
+ {#if icon && iconPosition === 'before'}
50
+ <span class="fs-breadcrumb-button-icon">
51
+ <RenderSoC SoC={icon} />
52
+ </span>
53
+ {/if}
54
+ <span class="fs-breadcrumb-button-label">
55
+ {@render children?.()}
56
+ </span>
57
+ {#if icon && iconPosition === 'after'}
58
+ <span class="fs-breadcrumb-button-icon">
59
+ <RenderSoC SoC={icon} />
60
+ </span>
61
+ {/if}
62
+ </svelte:element>
63
+
64
+ <style>
65
+ .fs-breadcrumb-button {
66
+ display: inline-flex;
67
+ align-items: center;
68
+ gap: var(--fs-breadcrumb-gap, 0.25rem);
69
+ box-sizing: border-box;
70
+ min-width: 0;
71
+ height: var(--fs-breadcrumb-height, 1.5rem);
72
+ padding: 0 var(--fs-breadcrumb-padding-inline, 0.375rem);
73
+ border: none;
74
+ border-radius: var(--fs-control-border-radius);
75
+ background: transparent;
76
+ color: var(--fs-text-secondary);
77
+ font-family: inherit;
78
+ font-size: var(--fs-breadcrumb-font-size, var(--fs-body2-font-size));
79
+ line-height: var(--fs-breadcrumb-line-height, var(--fs-body2-line-height));
80
+ /* An anchor arrives underlined and in the colour of a link; a step is neither. */
81
+ text-decoration: none;
82
+ cursor: pointer;
83
+ outline: none;
84
+ transition:
85
+ color var(--fs-fast-duration) var(--fs-point-to-point),
86
+ background var(--fs-fast-duration) var(--fs-point-to-point);
87
+ &:hover:not(.disabled) {
88
+ background: var(--fs-subtle-fill-secondary);
89
+ color: var(--fs-text-primary);
90
+ }
91
+ &:active:not(.disabled) {
92
+ background: var(--fs-subtle-fill-tertiary);
93
+ color: var(--fs-text-secondary);
94
+ }
95
+ &:focus-visible {
96
+ outline: 0.125rem var(--fs-focus-stroke-outer) solid;
97
+ outline-offset: 0.125rem;
98
+ }
99
+ /* The end of the trail is where the reader already is, so it reads as text, not as a way out. */
100
+ &.current {
101
+ color: var(--fs-text-primary);
102
+ font-weight: 600;
103
+ cursor: default;
104
+ &:hover,
105
+ &:active {
106
+ background: transparent;
107
+ color: var(--fs-text-primary);
108
+ }
109
+ }
110
+ &.disabled {
111
+ color: var(--fs-text-disabled);
112
+ cursor: not-allowed;
113
+ }
114
+ & .fs-breadcrumb-button-icon {
115
+ display: flex;
116
+ flex: 0 0 auto;
117
+ align-items: center;
118
+ justify-content: center;
119
+ & :global(svg) {
120
+ width: var(--fs-breadcrumb-icon-size, 1rem);
121
+ height: var(--fs-breadcrumb-icon-size, 1rem);
122
+ }
123
+ }
124
+ & .fs-breadcrumb-button-label {
125
+ overflow: hidden;
126
+ text-overflow: ellipsis;
127
+ white-space: nowrap;
128
+ }
129
+ }
130
+ </style>
@@ -0,0 +1,35 @@
1
+ import type { BreadcrumbButtonProps, BreadcrumbItemGenerics } from './types.ts';
2
+ declare function $$render<T extends BreadcrumbItemGenerics = 'button'>(): {
3
+ props: BreadcrumbButtonProps<T>;
4
+ exports: {};
5
+ bindings: "ref";
6
+ slots: {};
7
+ events: {};
8
+ };
9
+ declare class __sveltets_Render<T extends BreadcrumbItemGenerics = 'button'> {
10
+ props(): ReturnType<typeof $$render<T>>['props'];
11
+ events(): ReturnType<typeof $$render<T>>['events'];
12
+ slots(): ReturnType<typeof $$render<T>>['slots'];
13
+ bindings(): "ref";
14
+ exports(): {};
15
+ }
16
+ interface $$IsomorphicComponent {
17
+ new <T extends BreadcrumbItemGenerics = 'button'>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
18
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
19
+ } & ReturnType<__sveltets_Render<T>['exports']>;
20
+ <T extends BreadcrumbItemGenerics = 'button'>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
21
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
22
+ }
23
+ /**
24
+ * A step of a `Breadcrumb` that can be activated: an anchor when it goes somewhere, a button when
25
+ * it does something. The last step is the page itself, and `current` is what announces it.
26
+ *
27
+ * - Usage:
28
+ * ```tsx
29
+ * <BreadcrumbButton as="a" href="/files" icon={FolderRegular}>Files</BreadcrumbButton>
30
+ * <BreadcrumbButton current>This page</BreadcrumbButton>
31
+ * ```
32
+ */
33
+ declare const BreadcrumbButton: $$IsomorphicComponent;
34
+ type BreadcrumbButton<T extends BreadcrumbItemGenerics = 'button'> = InstanceType<typeof BreadcrumbButton<T>>;
35
+ export default BreadcrumbButton;
@@ -0,0 +1,39 @@
1
+ <script lang="ts">
2
+ import ChevronRightRegular from 'fluentui-icons-svelte/ChevronRightRegular.svelte';
3
+ import type { BreadcrumbDividerProps } from './types.js';
4
+
5
+ let { ref = $bindable(), class: classes, children, ...attributes }: BreadcrumbDividerProps = $props();
6
+ </script>
7
+
8
+ <!--
9
+ @component
10
+ The mark between two steps of a `Breadcrumb`. It is decoration, so it is held out of the
11
+ accessibility tree: a reader counting the steps of the trail should not be read a chevron
12
+ between each one, nor be told the list is twice as long as it is.
13
+
14
+ - Usage:
15
+ ```tsx
16
+ <BreadcrumbDivider />
17
+ ```
18
+ -->
19
+ <li bind:this={ref} aria-hidden="true" class={['fs-breadcrumb-divider', classes]} {...attributes}>
20
+ {#if children}
21
+ {@render children()}
22
+ {:else}
23
+ <ChevronRightRegular />
24
+ {/if}
25
+ </li>
26
+
27
+ <style>
28
+ .fs-breadcrumb-divider {
29
+ display: flex;
30
+ flex: 0 0 auto;
31
+ align-items: center;
32
+ justify-content: center;
33
+ color: var(--fs-text-secondary);
34
+ & :global(svg) {
35
+ width: var(--fs-breadcrumb-divider-size, 0.75rem);
36
+ height: var(--fs-breadcrumb-divider-size, 0.75rem);
37
+ }
38
+ }
39
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { BreadcrumbDividerProps } from './types.ts';
2
+ /**
3
+ * The mark between two steps of a `Breadcrumb`. It is decoration, so it is held out of the
4
+ * accessibility tree: a reader counting the steps of the trail should not be read a chevron
5
+ * between each one, nor be told the list is twice as long as it is.
6
+ *
7
+ * - Usage:
8
+ * ```tsx
9
+ * <BreadcrumbDivider />
10
+ * ```
11
+ */
12
+ declare const BreadcrumbDivider: import("svelte").Component<BreadcrumbDividerProps, {}, "ref">;
13
+ type BreadcrumbDivider = ReturnType<typeof BreadcrumbDivider>;
14
+ export default BreadcrumbDivider;
@@ -0,0 +1,30 @@
1
+ <script lang="ts">
2
+ import type { BreadcrumbItemProps } from './types.js';
3
+
4
+ let { ref = $bindable(), class: classes, children, ...attributes }: BreadcrumbItemProps = $props();
5
+ </script>
6
+
7
+ <!--
8
+ @component
9
+ One step of a `Breadcrumb`: the list item the step lives in. What goes inside is usually a
10
+ `BreadcrumbButton`, but it takes anything — a menu holding the steps that were folded away, for
11
+ instance.
12
+
13
+ - Usage:
14
+ ```tsx
15
+ <BreadcrumbItem>
16
+ <BreadcrumbButton as="a" href="/">Home</BreadcrumbButton>
17
+ </BreadcrumbItem>
18
+ ```
19
+ -->
20
+ <li bind:this={ref} class={['fs-breadcrumb-item', classes]} {...attributes}>
21
+ {@render children?.()}
22
+ </li>
23
+
24
+ <style>
25
+ .fs-breadcrumb-item {
26
+ display: flex;
27
+ align-items: center;
28
+ min-width: 0;
29
+ }
30
+ </style>
@@ -0,0 +1,16 @@
1
+ import type { BreadcrumbItemProps } from './types.ts';
2
+ /**
3
+ * One step of a `Breadcrumb`: the list item the step lives in. What goes inside is usually a
4
+ * `BreadcrumbButton`, but it takes anything — a menu holding the steps that were folded away, for
5
+ * instance.
6
+ *
7
+ * - Usage:
8
+ * ```tsx
9
+ * <BreadcrumbItem>
10
+ * <BreadcrumbButton as="a" href="/">Home</BreadcrumbButton>
11
+ * </BreadcrumbItem>
12
+ * ```
13
+ */
14
+ declare const BreadcrumbItem: import("svelte").Component<BreadcrumbItemProps, {}, "ref">;
15
+ type BreadcrumbItem = ReturnType<typeof BreadcrumbItem>;
16
+ export default BreadcrumbItem;
@@ -0,0 +1,101 @@
1
+ <script lang="ts">
2
+ import { getTabspotAttributes } from 'tabspot';
3
+ import type { BreadcrumbProps } from './types.js';
4
+
5
+ /** The steps a mover lands on when the trail takes a single tab stop. */
6
+ const TABSPOT_ITEMS = '.fs-breadcrumb-button';
7
+
8
+ let {
9
+ ref = $bindable(),
10
+ listRef = $bindable(),
11
+ listProps,
12
+ size = 'medium',
13
+ focusMode = 'tab',
14
+ 'aria-label': ariaLabel,
15
+ 'aria-labelledby': ariaLabelledby,
16
+ class: classes,
17
+ children,
18
+ ...attributes
19
+ }: BreadcrumbProps = $props();
20
+
21
+ const tabspotAttributes = $derived(
22
+ focusMode === 'arrow' &&
23
+ getTabspotAttributes({
24
+ root: { manageSpecialKeys: { Home: true, End: true } },
25
+ mover: { axis: 'horizontal', items: TABSPOT_ITEMS }
26
+ })
27
+ );
28
+ </script>
29
+
30
+ <!--
31
+ @component
32
+ A breadcrumb shows where a page sits in the hierarchy above it, and gives the reader a way back
33
+ up. It renders a landmark of its own, so a screen reader can jump straight to it.
34
+
35
+ - Usage:
36
+ ```tsx
37
+ <script>
38
+ import { Breadcrumb, BreadcrumbItem, BreadcrumbButton, BreadcrumbDivider } from 'fluentui-svelte';
39
+ </script>
40
+
41
+ <Breadcrumb>
42
+ <BreadcrumbItem>
43
+ <BreadcrumbButton as="a" href="/">Home</BreadcrumbButton>
44
+ </BreadcrumbItem>
45
+ <BreadcrumbDivider />
46
+ <BreadcrumbItem>
47
+ <BreadcrumbButton current>This page</BreadcrumbButton>
48
+ </BreadcrumbItem>
49
+ </Breadcrumb>
50
+ ```
51
+ -->
52
+ <nav
53
+ bind:this={ref}
54
+ aria-label={ariaLabelledby ? undefined : (ariaLabel ?? 'Breadcrumb')}
55
+ aria-labelledby={ariaLabelledby}
56
+ class={['fs-breadcrumb', size, classes]}
57
+ {...attributes}
58
+ >
59
+ <ol bind:this={listRef} class="fs-breadcrumb-list" {...tabspotAttributes} {...listProps}>
60
+ {@render children?.()}
61
+ </ol>
62
+ </nav>
63
+
64
+ <style>
65
+ .fs-breadcrumb {
66
+ font-family: var(--fs-font-family-base);
67
+ color: var(--fs-text-primary);
68
+ /* Read by every step and divider */
69
+ --fs-breadcrumb-font-size: var(--fs-body2-font-size);
70
+ --fs-breadcrumb-line-height: var(--fs-body2-line-height);
71
+ --fs-breadcrumb-height: 1.5rem;
72
+ --fs-breadcrumb-padding-inline: 0.375rem;
73
+ --fs-breadcrumb-gap: 0.25rem;
74
+ --fs-breadcrumb-icon-size: 1rem;
75
+ --fs-breadcrumb-divider-size: 1rem;
76
+ &.small {
77
+ --fs-breadcrumb-font-size: var(--fs-caption-font-size);
78
+ --fs-breadcrumb-line-height: var(--fs-caption-line-height);
79
+ --fs-breadcrumb-height: 1.25rem;
80
+ --fs-breadcrumb-padding-inline: 0.25rem;
81
+ --fs-breadcrumb-icon-size: 0.875rem;
82
+ --fs-breadcrumb-divider-size: 0.625rem;
83
+ }
84
+ &.large {
85
+ --fs-breadcrumb-font-size: var(--fs-body-font-size);
86
+ --fs-breadcrumb-line-height: var(--fs-body-line-height);
87
+ --fs-breadcrumb-height: 2rem;
88
+ --fs-breadcrumb-padding-inline: 0.5rem;
89
+ --fs-breadcrumb-icon-size: 1.25rem;
90
+ --fs-breadcrumb-divider-size: 1.25rem;
91
+ }
92
+ & .fs-breadcrumb-list {
93
+ display: flex;
94
+ flex-wrap: wrap;
95
+ align-items: center;
96
+ margin: 0;
97
+ padding: 0;
98
+ list-style: none;
99
+ }
100
+ }
101
+ </style>
@@ -0,0 +1,25 @@
1
+ import type { BreadcrumbProps } from './types.ts';
2
+ /**
3
+ * A breadcrumb shows where a page sits in the hierarchy above it, and gives the reader a way back
4
+ * up. It renders a landmark of its own, so a screen reader can jump straight to it.
5
+ *
6
+ * - Usage:
7
+ * ```tsx
8
+ * <script>
9
+ * import { Breadcrumb, BreadcrumbItem, BreadcrumbButton, BreadcrumbDivider } from 'fluentui-svelte';
10
+ * </script>
11
+ *
12
+ * <Breadcrumb>
13
+ * <BreadcrumbItem>
14
+ * <BreadcrumbButton as="a" href="/">Home</BreadcrumbButton>
15
+ * </BreadcrumbItem>
16
+ * <BreadcrumbDivider />
17
+ * <BreadcrumbItem>
18
+ * <BreadcrumbButton current>This page</BreadcrumbButton>
19
+ * </BreadcrumbItem>
20
+ * </Breadcrumb>
21
+ * ```
22
+ */
23
+ declare const Breadcrumb: import("svelte").Component<BreadcrumbProps, {}, "ref" | "listRef">;
24
+ type Breadcrumb = ReturnType<typeof Breadcrumb>;
25
+ export default Breadcrumb;
@@ -0,0 +1,193 @@
1
+ # Breadcrumb
2
+
3
+ A breadcrumb shows where a page sits in the hierarchy above it, and gives the reader a way back up. It renders a `nav` landmark around an ordered list, so a screen reader can jump straight to it.
4
+
5
+ The landmark names itself `Breadcrumb`, the trail is an `ol` so its order is part of the markup rather than of the styling, the last step carries `aria-current="page"`, and the dividers are held out of the accessibility tree — a trail of three steps reads as three, not as five. Every one of those can be overridden: pass your own `aria-label`, or an `aria-labelledby`, and the default steps aside.
6
+
7
+ To create a breadcrumb, you will need to use the following components:
8
+
9
+ - `Breadcrumb`: The landmark and the list. It creates the context the rest read.
10
+ - `BreadcrumbItem`: One step of the trail — the list item the step lives in. It takes anything, not only a step.
11
+ - `BreadcrumbButton`: A step that can be activated: an anchor when it goes somewhere, a button when it does something.
12
+ - `BreadcrumbDivider`: The mark between two steps. It is decoration, and is hidden from assistive technology.
13
+
14
+ ## Usage
15
+
16
+ A breadcrumb is a list of steps with a divider between them. The last step is the page the reader is already on, so it is marked `current` rather than linked away.
17
+
18
+ ```svelte
19
+ <script>
20
+ import { Breadcrumb, BreadcrumbItem, BreadcrumbButton, BreadcrumbDivider } from 'fluentui-svelte';
21
+ </script>
22
+
23
+ <Breadcrumb>
24
+ <BreadcrumbItem>
25
+ <BreadcrumbButton as="a" href="/">Home</BreadcrumbButton>
26
+ </BreadcrumbItem>
27
+ <BreadcrumbDivider />
28
+ <BreadcrumbItem>
29
+ <BreadcrumbButton as="a" href="/files">Files</BreadcrumbButton>
30
+ </BreadcrumbItem>
31
+ <BreadcrumbDivider />
32
+ <BreadcrumbItem>
33
+ <BreadcrumbButton current>Quarterly report</BreadcrumbButton>
34
+ </BreadcrumbItem>
35
+ </Breadcrumb>
36
+ ```
37
+
38
+ ## Examples
39
+
40
+ ### Size
41
+
42
+ `size` sets the type, the height and the divider of every step at once.
43
+
44
+ ```svelte
45
+ <Breadcrumb size="small">...</Breadcrumb>
46
+ <Breadcrumb size="medium">...</Breadcrumb>
47
+ <Breadcrumb size="large">...</Breadcrumb>
48
+ ```
49
+
50
+ ### Icon
51
+
52
+ `icon` takes a snippet or a component and renders it beside the label, on the side `iconPosition` asks for.
53
+
54
+ ```svelte
55
+ <BreadcrumbItem>
56
+ <BreadcrumbButton as="a" href="/files" icon={FolderRegular}>Files</BreadcrumbButton>
57
+ </BreadcrumbItem>
58
+ ```
59
+
60
+ ### Current Step
61
+
62
+ `current` marks the step as the page the trail ends at. It announces `aria-current="page"` and reads as text rather than as a way out, so the last step does not offer to take the reader where they already are.
63
+
64
+ ```svelte
65
+ <BreadcrumbItem>
66
+ <BreadcrumbButton current>Quarterly report</BreadcrumbButton>
67
+ </BreadcrumbItem>
68
+ ```
69
+
70
+ ### Overflow Menu
71
+
72
+ A step takes whatever you put in it, so a long trail folds its middle into a menu by making that menu a step of its own. Which steps fold is your call — slice the list wherever the layout needs it.
73
+
74
+ ```svelte
75
+ <script>
76
+ // Keep the root and the last two steps; everything between them goes into the menu.
77
+ const head = trail.slice(0, 1);
78
+ const folded = trail.slice(1, -2);
79
+ const tail = trail.slice(-2);
80
+ </script>
81
+
82
+ <Breadcrumb>
83
+ {#each head as item (item.name)}
84
+ <BreadcrumbItem>
85
+ <BreadcrumbButton as="a" href={item.href}>{item.name}</BreadcrumbButton>
86
+ </BreadcrumbItem>
87
+ <BreadcrumbDivider />
88
+ {/each}
89
+
90
+ <BreadcrumbItem>
91
+ <Menu>
92
+ <MenuTrigger>
93
+ {#snippet children({ state, menuTriggerProps })}
94
+ <Button bind:ref={state.ref} {...menuTriggerProps} appearance="subtle" aria-label="More steps">
95
+ <MoreHorizontalRegular />
96
+ </Button>
97
+ {/snippet}
98
+ </MenuTrigger>
99
+ <MenuPopover>
100
+ <MenuList>
101
+ <!-- A step that goes somewhere is a link, in the menu as much as in the trail. -->
102
+ {#each folded as item (item.name)}
103
+ <MenuItem href={item.href}>{item.name}</MenuItem>
104
+ {/each}
105
+ </MenuList>
106
+ </MenuPopover>
107
+ </Menu>
108
+ </BreadcrumbItem>
109
+ <BreadcrumbDivider />
110
+
111
+ {#each tail as item (item.name)}
112
+ <BreadcrumbItem>
113
+ <BreadcrumbButton current>{item.name}</BreadcrumbButton>
114
+ </BreadcrumbItem>
115
+ {/each}
116
+ </Breadcrumb>
117
+ ```
118
+
119
+ The label on the menu button is yours to write, and it is worth writing: a trigger with only an icon says nothing to a screen reader. Note also that what lives inside a `MenuPopover` is not rendered until the menu opens, so the folded steps are not in the HTML a crawler reads.
120
+
121
+ ### Focus Mode
122
+
123
+ `focusMode` decides how the focus walks the trail. `tab`, the default, leaves every step its own tab stop, which is what a reader expects of a row of links. `arrow` gives the whole trail a single tab stop and moves between steps with the arrow keys, with `Home` and `End` for the ends.
124
+
125
+ ```svelte
126
+ <Breadcrumb focusMode="arrow">...</Breadcrumb>
127
+ ```
128
+
129
+ ## Component Props (Breadcrumb)
130
+
131
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
132
+ <!-- props:BreadcrumbProps -->
133
+
134
+ | Name | Type | Default | Description |
135
+ | -------------------- | -------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
136
+ | `ref` _bindable_ | `HTMLElement` | | The DOM reference of the `nav`. |
137
+ | `listRef` _bindable_ | `HTMLOListElement` | | The DOM reference of the list. |
138
+ | `listProps` | `HTMLOlAttributes` | | The props to spread on the list element. |
139
+ | `size` | `'small'` &#124; `'medium'` &#124; `'large'` | `'medium'` | The size of every step and divider of the trail. |
140
+ | `focusMode` | `'tab'` &#124; `'arrow'` | `'tab'` | How the focus walks the trail: `tab` leaves every step its own tab stop, `arrow` gives the trail a single one and moves between steps with the arrow keys. |
141
+ | Element Attributes | | | |
142
+
143
+ <!-- /props:BreadcrumbProps -->
144
+
145
+ ## Component Props (BreadcrumbItem)
146
+
147
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
148
+ <!-- props:BreadcrumbItemProps -->
149
+
150
+ | Name | Type | Default | Description |
151
+ | ------------------------- | --------------- | ------- | ------------------------------ |
152
+ | `ref` _bindable_ | `HTMLLIElement` | | The DOM reference of the item. |
153
+ | Element Attributes (`li`) | | | |
154
+
155
+ <!-- /props:BreadcrumbItemProps -->
156
+
157
+ ## Component Props (BreadcrumbButton)
158
+
159
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
160
+ <!-- props:BreadcrumbButtonProps -->
161
+
162
+ | Name | Type | Default | Description |
163
+ | ------------------- | --------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------ |
164
+ | `ref` _bindable_ | `BreadcrumbItemElementDOMType[T]` | | The DOM reference of the step. |
165
+ | `as` | `'button'` &#124; `'a'` | `'button'` | The DOM element to render. A step that goes somewhere is an anchor and takes `href`. |
166
+ | `icon` | `Snippet` &#124; `Component` | | The icon to display beside the label. |
167
+ | `iconPosition` | `'before'` &#124; `'after'` | `'before'` | Which side of the label the icon sits on. |
168
+ | `current` | `boolean` | `false` | Marks the step as the page the trail ends at, which is what `aria-current` announces. |
169
+ | `disabled` | `boolean` | | Disables the user interaction. |
170
+ | `disabledFocusable` | `boolean` | `false` | Keeps a disabled step focusable, so the tab order stays the same for a keyboard or screen reader user. |
171
+ | HTML Attributes | | | |
172
+
173
+ <!-- /props:BreadcrumbButtonProps -->
174
+
175
+ ## Component Props (BreadcrumbDivider)
176
+
177
+ <!-- DO NOT EDIT THIS SECTION (propsmith generated) -->
178
+ <!-- props:BreadcrumbDividerProps -->
179
+
180
+ | Name | Type | Default | Description |
181
+ | ------------------------- | --------------- | ------- | --------------------------------- |
182
+ | `ref` _bindable_ | `HTMLLIElement` | | The DOM reference of the divider. |
183
+ | Element Attributes (`li`) | | | |
184
+
185
+ <!-- /props:BreadcrumbDividerProps -->
186
+
187
+ ## Accessibility
188
+
189
+ The landmark is named `Breadcrumb` by default, which is what a screen reader announces when jumping to it. Give it your own `aria-label` when a page carries more than one trail, so each is distinguishable, or an `aria-labelledby` pointing at a heading you already render — the default steps aside for both.
190
+
191
+ The dividers are decoration and are hidden, so the list reads as the number of steps it has. The last step carries `aria-current="page"`. A step with an icon and no label needs an `aria-label` of its own.
192
+
193
+ Structured data is left to you. A breadcrumb is one of the few components a search engine reads directly, through `BreadcrumbList` from schema.org, but the text of a step lives in your markup and the URLs live in your routing — so the trail you publish is yours to build, in whichever shape your site already uses.
@@ -0,0 +1,80 @@
1
+ import type { BeforeOrAfter, PolymorphicProps, Sizes } from '../../types/index.js';
2
+ import type { Snippet, Component } from 'svelte';
3
+ import type { HTMLAttributes, HTMLOlAttributes } from 'svelte/elements';
4
+ /** How the focus walks the trail. */
5
+ export type BreadcrumbFocusMode = 'tab' | 'arrow';
6
+ export type BreadcrumbItemGenerics = 'button' | 'a';
7
+ export type BreadcrumbItemElementDOMType = {
8
+ button: HTMLButtonElement;
9
+ a: HTMLAnchorElement;
10
+ };
11
+ /** @propsmith BreadcrumbProps */
12
+ export type BreadcrumbProps = {
13
+ /** The DOM reference of the `nav`.
14
+ * @bindable
15
+ */
16
+ ref?: HTMLElement;
17
+ /** The DOM reference of the list.
18
+ * @bindable
19
+ */
20
+ listRef?: HTMLOListElement;
21
+ /** The props to spread on the list element.
22
+ * @type HTMLOlAttributes
23
+ */
24
+ listProps?: HTMLOlAttributes;
25
+ /** The size of every step and divider of the trail.
26
+ * @default 'medium'
27
+ */
28
+ size?: Sizes;
29
+ /** How the focus walks the trail: `tab` leaves every step its own tab stop, `arrow` gives the
30
+ * trail a single one and moves between steps with the arrow keys.
31
+ * @default 'tab'
32
+ */
33
+ focusMode?: BreadcrumbFocusMode;
34
+ } & HTMLAttributes<HTMLElement>;
35
+ /** @propsmith BreadcrumbItemProps */
36
+ export type BreadcrumbItemProps = {
37
+ /** The DOM reference of the item.
38
+ * @bindable
39
+ */
40
+ ref?: HTMLLIElement;
41
+ } & HTMLAttributes<HTMLLIElement>;
42
+ /** @propsmith BreadcrumbButtonProps */
43
+ export type BreadcrumbButtonProps<T extends BreadcrumbItemGenerics = 'button'> = {
44
+ /** The DOM reference of the step.
45
+ * @type BreadcrumbItemElementDOMType[T]
46
+ * @bindable
47
+ */
48
+ ref?: BreadcrumbItemElementDOMType[T];
49
+ /** The DOM element to render. A step that goes somewhere is an anchor and takes `href`.
50
+ * @type 'button' | 'a'
51
+ * @default 'button'
52
+ */
53
+ as?: T;
54
+ /** The icon to display beside the label.
55
+ * @type Snippet | Component
56
+ */
57
+ icon?: Snippet | Component;
58
+ /** Which side of the label the icon sits on.
59
+ * @default 'before'
60
+ */
61
+ iconPosition?: BeforeOrAfter;
62
+ /** Marks the step as the page the trail ends at, which is what `aria-current` announces.
63
+ * @default false
64
+ */
65
+ current?: boolean;
66
+ /** Disables the user interaction. */
67
+ disabled?: boolean;
68
+ /** Keeps a disabled step focusable, so the tab order stays the same for a keyboard or screen
69
+ * reader user.
70
+ * @default false
71
+ */
72
+ disabledFocusable?: boolean;
73
+ } & PolymorphicProps<T>;
74
+ /** @propsmith BreadcrumbDividerProps */
75
+ export type BreadcrumbDividerProps = {
76
+ /** The DOM reference of the divider.
77
+ * @bindable
78
+ */
79
+ ref?: HTMLLIElement;
80
+ } & HTMLAttributes<HTMLLIElement>;
@@ -0,0 +1 @@
1
+ export {};