noph-ui 0.51.2 → 0.52.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 (130) hide show
  1. package/dist/animation.d.ts +26 -1
  2. package/dist/animation.js +50 -2
  3. package/dist/app-bar/AppBar.svelte +71 -7
  4. package/dist/app-bar/types.d.ts +6 -0
  5. package/dist/autocomplete/AutoComplete.svelte +6 -31
  6. package/dist/autocomplete/AutoComplete.svelte.d.ts +1 -1
  7. package/dist/badge/Badge.svelte +12 -4
  8. package/dist/badge/description.d.ts +4 -0
  9. package/dist/badge/description.js +4 -0
  10. package/dist/button/Button.svelte +55 -20
  11. package/dist/button/ButtonGroup.svelte +139 -19
  12. package/dist/button/ButtonGroup.svelte.d.ts +1 -1
  13. package/dist/button/IconButton.svelte +49 -18
  14. package/dist/button/SegmentedButton.svelte +44 -4
  15. package/dist/button/SplitButton.svelte +77 -3
  16. package/dist/button/SplitButton.svelte.d.ts +1 -1
  17. package/dist/button/buttonGroup.d.ts +0 -4
  18. package/dist/button/buttonGroup.js +0 -9
  19. package/dist/button/groupContext.d.ts +10 -0
  20. package/dist/button/groupContext.js +4 -0
  21. package/dist/button/types.d.ts +19 -0
  22. package/dist/checkbox/Checkbox.svelte +5 -0
  23. package/dist/chip/ChipSet.svelte +28 -2
  24. package/dist/chip/FilterChip.svelte +32 -4
  25. package/dist/chip/InputChip.svelte +127 -26
  26. package/dist/chip/SuggestionChip.svelte +6 -22
  27. package/dist/chip/SuggestionChip.svelte.d.ts +1 -2
  28. package/dist/chip/types.d.ts +8 -1
  29. package/dist/date-picker/Calendar.svelte +4 -2
  30. package/dist/date-picker/DatePickerDialog.svelte +1 -0
  31. package/dist/date-picker/DatePickerDialog.svelte.d.ts +1 -1
  32. package/dist/date-picker/DateRangePicker.svelte +1 -0
  33. package/dist/date-picker/DateRangePicker.svelte.d.ts +1 -1
  34. package/dist/date-picker/DockedDatePicker.svelte +12 -5
  35. package/dist/date-picker/DockedDatePicker.svelte.d.ts +1 -1
  36. package/dist/date-picker/DockedDateTimePicker.svelte +12 -5
  37. package/dist/date-picker/DockedDateTimePicker.svelte.d.ts +1 -1
  38. package/dist/date-picker/YearGrid.svelte +4 -2
  39. package/dist/dialog/Dialog.svelte +171 -33
  40. package/dist/dialog/Dialog.svelte.d.ts +2 -1
  41. package/dist/dialog/types.d.ts +6 -0
  42. package/dist/divider/Divider.svelte +36 -10
  43. package/dist/divider/types.d.ts +1 -0
  44. package/dist/fab/ExtendedFab.svelte +26 -60
  45. package/dist/fab/Fab.svelte +13 -48
  46. package/dist/fab/FabMenu.svelte +102 -44
  47. package/dist/fab/FabMenu.svelte.d.ts +2 -1
  48. package/dist/fab/FabMenuItem.svelte +8 -0
  49. package/dist/fab/FabMenuItem.svelte.d.ts +4 -0
  50. package/dist/fab/index.d.ts +1 -0
  51. package/dist/fab/index.js +1 -0
  52. package/dist/fab/types.d.ts +6 -4
  53. package/dist/icons/MenuIcon.svelte +13 -0
  54. package/dist/icons/MenuIcon.svelte.d.ts +7 -0
  55. package/dist/icons/MenuOpenIcon.svelte +15 -0
  56. package/dist/icons/MenuOpenIcon.svelte.d.ts +7 -0
  57. package/dist/icons/index.d.ts +2 -0
  58. package/dist/icons/index.js +2 -0
  59. package/dist/internal/exit.css +47 -0
  60. package/dist/internal/fieldTypes.d.ts +6 -0
  61. package/dist/internal/focus-ring.css +4 -0
  62. package/dist/internal/interest.css +3 -1
  63. package/dist/keyboard-nav.d.ts +12 -1
  64. package/dist/keyboard-nav.js +104 -14
  65. package/dist/list/Item.svelte +52 -6
  66. package/dist/list/List.svelte +35 -2
  67. package/dist/list/ListItem.svelte +16 -2
  68. package/dist/list/context.d.ts +6 -0
  69. package/dist/list/context.js +4 -0
  70. package/dist/list/types.d.ts +7 -0
  71. package/dist/media.d.ts +1 -0
  72. package/dist/media.js +1 -0
  73. package/dist/menu/Menu.svelte +70 -18
  74. package/dist/menu/Menu.svelte.d.ts +2 -1
  75. package/dist/menu/MenuItem.svelte +9 -3
  76. package/dist/menu/types.d.ts +7 -1
  77. package/dist/navigation-bar/NavigationBar.svelte +9 -3
  78. package/dist/navigation-bar/NavigationBarItem.svelte +29 -13
  79. package/dist/navigation-drawer/NavigationDrawer.svelte +96 -20
  80. package/dist/navigation-drawer/NavigationDrawer.svelte.d.ts +2 -1
  81. package/dist/navigation-drawer/NavigationDrawerItem.svelte +8 -3
  82. package/dist/navigation-drawer/NavigationDrawerSection.svelte +49 -0
  83. package/dist/navigation-drawer/NavigationDrawerSection.svelte.d.ts +4 -0
  84. package/dist/navigation-drawer/index.d.ts +1 -0
  85. package/dist/navigation-drawer/index.js +1 -0
  86. package/dist/navigation-drawer/types.d.ts +12 -0
  87. package/dist/navigation-rail/NavigationRail.svelte +367 -7
  88. package/dist/navigation-rail/NavigationRail.svelte.d.ts +1 -1
  89. package/dist/navigation-rail/NavigationRailItem.svelte +190 -53
  90. package/dist/navigation-rail/NavigationRailSection.svelte +57 -0
  91. package/dist/navigation-rail/NavigationRailSection.svelte.d.ts +4 -0
  92. package/dist/navigation-rail/context.d.ts +6 -0
  93. package/dist/navigation-rail/context.js +5 -0
  94. package/dist/navigation-rail/index.d.ts +1 -0
  95. package/dist/navigation-rail/index.js +1 -0
  96. package/dist/navigation-rail/morph.d.ts +14 -0
  97. package/dist/navigation-rail/morph.js +78 -0
  98. package/dist/navigation-rail/types.d.ts +21 -0
  99. package/dist/progress/CircularProgress.svelte +2 -1
  100. package/dist/progress/LinearProgress.svelte +48 -20
  101. package/dist/progress/types.d.ts +1 -0
  102. package/dist/radio/Radio.svelte +7 -1
  103. package/dist/search/Search.svelte +245 -58
  104. package/dist/search/types.d.ts +4 -0
  105. package/dist/select/NativeSelect.svelte +20 -12
  106. package/dist/select/Option.svelte +1 -2
  107. package/dist/select/Select.svelte +59 -140
  108. package/dist/select/VirtualList.svelte +16 -1
  109. package/dist/select/VirtualList.svelte.d.ts +6 -2
  110. package/dist/sheet/Sheet.svelte +223 -5
  111. package/dist/sheet/Sheet.svelte.d.ts +3 -1
  112. package/dist/sheet/types.d.ts +10 -0
  113. package/dist/slider/Slider.svelte +1 -27
  114. package/dist/snackbar/Snackbar.svelte +3 -0
  115. package/dist/snackbar/Snackbar.svelte.d.ts +2 -1
  116. package/dist/switch/Switch.svelte +51 -11
  117. package/dist/tabs/Tab.svelte +28 -14
  118. package/dist/tabs/Tabs.svelte +28 -4
  119. package/dist/tabs/types.d.ts +3 -0
  120. package/dist/text-field/TextField.svelte +49 -13
  121. package/dist/time-picker/DockedTimePicker.svelte +6 -1
  122. package/dist/time-picker/DockedTimePicker.svelte.d.ts +1 -1
  123. package/dist/time-picker/TimePickerDialog.svelte +1 -0
  124. package/dist/time-picker/TimePickerDialog.svelte.d.ts +1 -1
  125. package/dist/toolbar/Toolbar.svelte +21 -11
  126. package/dist/toolbar/types.d.ts +1 -0
  127. package/dist/tooltip/RichTooltip.svelte.d.ts +1 -1
  128. package/dist/tooltip/Tooltip.svelte +3 -1
  129. package/dist/tooltip/Tooltip.svelte.d.ts +1 -1
  130. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import '../internal/focus-ring.css'
3
3
  import Badge from '../badge/Badge.svelte'
4
+ import { badgeDescription } from '../badge/description.js'
4
5
  import Ripple from '../ripple/Ripple.svelte'
5
6
  import type { HTMLButtonAttributes } from 'svelte/elements'
6
7
  import type { NavigationBarItemProps } from './types.js'
@@ -18,7 +19,11 @@
18
19
  ...attributes
19
20
  }: NavigationBarItemProps = $props()
20
21
 
21
- let touchEl: HTMLSpanElement | undefined = $state()
22
+ const uid = $props.id()
23
+ let badgeId = $derived(badge ? `${uid}-badge` : undefined)
24
+ let describedBy = $derived(
25
+ [attributes['aria-describedby'], badgeId].filter(Boolean).join(' ') || undefined,
26
+ )
22
27
 
23
28
  let isLink = $derived(attributes.href != null)
24
29
  let classes = $derived([
@@ -32,21 +37,24 @@
32
37
 
33
38
  {#snippet content()}
34
39
  {#if orientation === 'horizontal'}
35
- <Ripple forElement={touchEl} />
40
+ <Ripple forElement={element} />
36
41
  {/if}
37
42
  <span class="np-navigation-bar-item-icon">
38
43
  {#if orientation === 'vertical'}
39
- <Ripple forElement={touchEl} />
44
+ <Ripple forElement={element} />
40
45
  {/if}
41
46
  {@render icon()}
42
47
  {#if badge}
43
48
  <span class="np-navigation-bar-item-badge">
44
- <Badge label={badgeLabel} aria-label={badgeAriaLabel} />
49
+ <Badge label={badgeLabel} />
45
50
  </span>
46
51
  {/if}
47
52
  </span>
48
53
  <span class="np-navigation-bar-item-label">{label}</span>
49
- <span class="np-touch" bind:this={touchEl}></span>
54
+ {#if badgeId}
55
+ <span id={badgeId} hidden>{badgeDescription(badgeLabel, badgeAriaLabel)}</span>
56
+ {/if}
57
+ <span class="np-touch"></span>
50
58
  {/snippet}
51
59
 
52
60
  {#if isLink}
@@ -54,6 +62,7 @@
54
62
  {...attributes}
55
63
  bind:this={element}
56
64
  href={attributes.href}
65
+ aria-describedby={describedBy}
57
66
  class={classes}
58
67
  aria-current={selected ? 'page' : undefined}
59
68
  tabindex={selected ? 0 : -1}
@@ -64,6 +73,7 @@
64
73
  <button
65
74
  {...attributes as HTMLButtonAttributes}
66
75
  bind:this={element}
76
+ aria-describedby={describedBy}
67
77
  class={classes}
68
78
  aria-current={selected ? 'page' : undefined}
69
79
  tabindex={selected ? 0 : -1}
@@ -80,6 +90,8 @@
80
90
  cursor: pointer;
81
91
  font: inherit;
82
92
  border-width: 0;
93
+ padding-block: 0;
94
+ padding-inline: 0.375rem;
83
95
  background: none;
84
96
  display: flex;
85
97
  flex-direction: column;
@@ -150,6 +162,7 @@
150
162
  }
151
163
 
152
164
  .np-navigation-bar-item-horizontal {
165
+ flex: 0 0 auto;
153
166
  flex-direction: row;
154
167
  justify-content: center;
155
168
  gap: 0.25rem;
@@ -182,14 +195,12 @@
182
195
  .np-navigation-bar-item-horizontal .np-navigation-bar-item-icon::before {
183
196
  content: none;
184
197
  }
185
- .np-navigation-bar-item-horizontal .np-navigation-bar-item-badge {
186
- --np-badge-top: -0.25rem;
187
- --np-badge-end: -0.25rem;
188
- }
189
198
  .np-navigation-bar-item-horizontal .np-touch {
190
- inset: 0;
199
+ inset-inline: 0;
200
+ inset-block-start: 50%;
201
+ translate: 0 -50%;
191
202
  width: 100%;
192
- height: 100%;
203
+ height: max(3rem, 100%);
193
204
  }
194
205
  @media (prefers-reduced-motion: no-preference) {
195
206
  .np-navigation-bar-item-horizontal::before {
@@ -200,10 +211,11 @@
200
211
  }
201
212
 
202
213
  .np-navigation-bar-item-badge {
203
- --np-badge-top: 0;
204
- --np-badge-end: 1rem;
205
214
  position: absolute;
206
215
  inset: 0;
216
+ width: 1.5rem;
217
+ height: 1.5rem;
218
+ margin: auto;
207
219
  pointer-events: none;
208
220
  }
209
221
 
@@ -221,6 +233,10 @@
221
233
  outline-offset: 2px;
222
234
  border-radius: 1rem;
223
235
  }
236
+ /* The focused state layer, on top of the ring. */
237
+ .np-navigation-bar-item:focus-visible :global(.np-ripple-surface)::before {
238
+ opacity: var(--np-ripple-focus-opacity, 0.1);
239
+ }
224
240
 
225
241
  @media (prefers-reduced-motion: no-preference) {
226
242
  .np-navigation-bar-item-icon::before {
@@ -1,12 +1,15 @@
1
1
  <script lang="ts">
2
- import { arrowKeyNav, rovingTabindex } from '../keyboard-nav.js'
2
+ import '../internal/exit.css'
3
+ import { exitAnimation } from '../animation.js'
4
+ import { arrowKeyNav, focusableItems, rovingTabindex } from '../keyboard-nav.js'
3
5
  import { syncOpenEffect } from '../popover.svelte.js'
4
6
  import type { NavigationDrawerProps } from './types.js'
5
7
 
6
8
  let {
7
9
  modal = false,
8
- backdrop = false,
9
- open = $bindable(false),
10
+ backdrop = true,
11
+ open = $bindable(),
12
+ headline,
10
13
  element = $bindable(),
11
14
  direction,
12
15
  children,
@@ -15,8 +18,10 @@
15
18
  ...attributes
16
19
  }: NavigationDrawerProps = $props()
17
20
 
18
- const attach = rovingTabindex('.np-navigation-drawer-item')
19
- const arrowHandler = arrowKeyNav('.np-navigation-drawer-item')
21
+ const uid = $props.id()
22
+ const ITEMS = '.np-navigation-drawer-item'
23
+ const attach = rovingTabindex(ITEMS)
24
+ const arrowHandler = arrowKeyNav(ITEMS)
20
25
 
21
26
  const handleKeydown = (event: KeyboardEvent & { currentTarget: EventTarget & HTMLElement }) => {
22
27
  userKeydown?.(event)
@@ -40,8 +45,23 @@
40
45
  show,
41
46
  close,
42
47
  )
48
+
49
+ // The headline names the navigation unless the drawer is named otherwise.
50
+ let headlineId = $derived(headline ? `${uid}-headline` : undefined)
51
+ let labelledBy = $derived(
52
+ attributes['aria-labelledby'] ?? (attributes['aria-label'] ? undefined : headlineId),
53
+ )
43
54
  </script>
44
55
 
56
+ {#snippet content()}
57
+ <div class="np-navigation-drawer">
58
+ {#if headline}
59
+ <div id={headlineId} class="np-navigation-drawer-headline">{headline}</div>
60
+ {/if}
61
+ {@render children?.()}
62
+ </div>
63
+ {/snippet}
64
+
45
65
  {#if modal}
46
66
  <dialog
47
67
  {...attributes}
@@ -55,13 +75,15 @@
55
75
  class={[
56
76
  'np-navigation-drawer-container',
57
77
  'np-navigation-drawer-container-modal',
58
- backdrop && 'np-navigation-drawer-backdrop',
78
+ backdrop && 'np-navigation-drawer-backdrop np-exit-scrim',
59
79
  attributes.class,
60
80
  ]}
81
+ {@attach exitAnimation}
61
82
  onkeydown={handleKeydown}
62
83
  ontoggle={(event) => {
63
84
  open = event.newState === 'open'
64
- if (event.newState === 'open') element?.focus()
85
+ // Focus lands on the first destination, the first interactive element.
86
+ if (open && element) focusableItems(element, ITEMS)[0]?.focus()
65
87
  ontoggle?.(event)
66
88
  }}
67
89
  onclick={(event) => {
@@ -71,12 +93,10 @@
71
93
  >
72
94
  <nav
73
95
  aria-label={attributes['aria-label']}
74
- aria-labelledby={attributes['aria-labelledby']}
96
+ aria-labelledby={labelledBy}
75
97
  class="np-navigation-wrapper np-navigation-drawer-shade"
76
98
  >
77
- <div class="np-navigation-drawer">
78
- {@render children?.()}
79
- </div>
99
+ {@render content()}
80
100
  </nav>
81
101
  </dialog>
82
102
  {:else}
@@ -84,13 +104,16 @@
84
104
  {...attributes}
85
105
  {@attach attach}
86
106
  bind:this={element}
87
- class={['np-navigation-drawer-container', attributes.class]}
107
+ aria-labelledby={labelledBy}
108
+ class={[
109
+ 'np-navigation-drawer-container',
110
+ open === false && 'np-navigation-drawer-closed',
111
+ attributes.class,
112
+ ]}
88
113
  onkeydown={handleKeydown}
89
114
  >
90
115
  <div class="np-navigation-wrapper">
91
- <div class="np-navigation-drawer">
92
- {@render children?.()}
93
- </div>
116
+ {@render content()}
94
117
  </div>
95
118
  </nav>
96
119
  {/if}
@@ -98,7 +121,7 @@
98
121
  <style>
99
122
  .np-navigation-drawer-container {
100
123
  color: var(--np-color-on-surface-variant);
101
- width: calc(var(--np-navigation-drawer-width, 22.5rem) + 3px);
124
+ width: var(--np-navigation-drawer-width, 22.5rem);
102
125
  border: 0;
103
126
  outline: none;
104
127
  margin: 0;
@@ -140,16 +163,28 @@
140
163
  transform: translateX(0);
141
164
  }
142
165
 
166
+ /* It moves like the modal navigation rail: it springs open and slides back without the spring. */
143
167
  @media (prefers-reduced-motion: no-preference) {
144
168
  .np-navigation-drawer-container-modal .np-navigation-wrapper {
145
- transition: transform var(--np-motion-standard-slow-spatial);
169
+ --_motion: var(--np-motion-standard-fast-spatial);
170
+ transition: transform var(--_motion);
171
+ /* Its colour carries on past the window's edge, so the spring shows no gap there. */
172
+ box-shadow:
173
+ var(--_bleed) 0 0 0
174
+ var(--np-navigation-drawer-background, var(--np-color-surface-container-low)),
175
+ var(--np-elevation-1);
146
176
  }
147
177
  .np-navigation-drawer-container-modal {
178
+ --_bleed: -2rem;
148
179
  transition:
149
- overlay var(--np-motion-standard-slow-spatial) allow-discrete,
150
- display var(--np-motion-standard-slow-spatial) allow-discrete;
180
+ overlay var(--np-motion-standard-fast-spatial) allow-discrete,
181
+ display var(--np-motion-standard-fast-spatial) allow-discrete;
182
+ }
183
+ .np-navigation-drawer-container-modal:dir(rtl) {
184
+ --_bleed: 2rem;
151
185
  }
152
186
  .np-navigation-drawer-container-modal[open] .np-navigation-wrapper {
187
+ --_motion: var(--np-motion-expressive-default-spatial);
153
188
  @starting-style {
154
189
  transform: var(--_hidden);
155
190
  }
@@ -158,9 +193,50 @@
158
193
 
159
194
  .np-navigation-drawer {
160
195
  display: flex;
161
- padding: var(--np-navigation-drawer-padding, 1.25rem 0.75rem);
196
+ padding: var(--np-navigation-drawer-padding, 0.75rem);
162
197
  flex-direction: column;
163
198
  }
199
+ /* The headline sits like a 56dp row, its text in line with the labels below. */
200
+ .np-navigation-drawer-headline {
201
+ display: flex;
202
+ align-items: center;
203
+ min-height: 3.5rem;
204
+ padding-inline: 1rem;
205
+ font-size: 0.875rem;
206
+ line-height: 1.25rem;
207
+ font-weight: 500;
208
+ letter-spacing: 0.006rem;
209
+ color: var(--np-color-on-surface-variant);
210
+ }
211
+
212
+ /* A dismissible standard drawer slides out to the start and gives its space back. */
213
+ .np-navigation-drawer-container:not(.np-navigation-drawer-container-modal) {
214
+ --_hidden: translateX(-100%);
215
+ overflow: hidden;
216
+ }
217
+ .np-navigation-drawer-container:not(.np-navigation-drawer-container-modal):dir(rtl) {
218
+ --_hidden: translateX(100%);
219
+ }
220
+ .np-navigation-drawer-closed {
221
+ width: 0;
222
+ visibility: hidden;
223
+ }
224
+ .np-navigation-drawer-closed .np-navigation-wrapper {
225
+ transform: var(--_hidden);
226
+ }
227
+ @media (prefers-reduced-motion: no-preference) {
228
+ /* visibility stays visible for as long as either end is, so it hides only once the drawer
229
+ has slid out. */
230
+ .np-navigation-drawer-container:not(.np-navigation-drawer-container-modal) {
231
+ transition:
232
+ width var(--np-motion-standard-slow-spatial),
233
+ visibility var(--np-motion-standard-slow-spatial);
234
+ }
235
+ .np-navigation-drawer-container:not(.np-navigation-drawer-container-modal)
236
+ .np-navigation-wrapper {
237
+ transition: transform var(--np-motion-standard-slow-spatial);
238
+ }
239
+ }
164
240
  .np-navigation-drawer-shade {
165
241
  box-shadow: var(--np-elevation-1);
166
242
  }
@@ -1,7 +1,8 @@
1
+ import '../internal/exit.css';
1
2
  import type { NavigationDrawerProps } from './types.js';
2
3
  declare const NavigationDrawer: import("svelte").Component<NavigationDrawerProps, {
3
4
  show: () => void;
4
5
  close: () => void;
5
- }, "element" | "open">;
6
+ }, "open" | "element">;
6
7
  type NavigationDrawer = ReturnType<typeof NavigationDrawer>;
7
8
  export default NavigationDrawer;
@@ -95,9 +95,6 @@
95
95
  height: 100%;
96
96
  opacity: 0;
97
97
  transform: scaleX(0.32);
98
- transition-duration: 0.2s;
99
- transition-property: transform, opacity;
100
- transition-timing-function: linear;
101
98
  background-color: var(--np-color-secondary-container);
102
99
  border-radius: var(--np-navigation-drawer-item-container-shape, var(--np-shape-corner-full));
103
100
  z-index: -1;
@@ -107,6 +104,14 @@
107
104
  opacity: 1;
108
105
  transform: scaleX(1);
109
106
  }
107
+ /* Like the active indicator in the navigation bar and rail. */
108
+ @media (prefers-reduced-motion: no-preference) {
109
+ .np-navigation-drawer-item::before {
110
+ transition:
111
+ transform var(--np-motion-expressive-default-spatial),
112
+ opacity var(--np-motion-expressive-fast-effects);
113
+ }
114
+ }
110
115
 
111
116
  .np-navigation-drawer-item:focus-visible {
112
117
  outline-style: solid;
@@ -0,0 +1,49 @@
1
+ <script lang="ts">
2
+ import type { NavigationDrawerSectionProps } from './types.js'
3
+
4
+ let {
5
+ label,
6
+ children,
7
+ element = $bindable(),
8
+ ...attributes
9
+ }: NavigationDrawerSectionProps = $props()
10
+
11
+ const uid = $props.id()
12
+ </script>
13
+
14
+ <!-- A group of related destinations, set off by a divider and named by its label. -->
15
+ <div
16
+ {...attributes}
17
+ bind:this={element}
18
+ role="group"
19
+ aria-labelledby="{uid}-label"
20
+ class={['np-navigation-drawer-section', attributes.class]}
21
+ >
22
+ <div class="np-navigation-drawer-section-divider"></div>
23
+ <div id="{uid}-label" class="np-navigation-drawer-section-label">{label}</div>
24
+ {@render children?.()}
25
+ </div>
26
+
27
+ <style>
28
+ .np-navigation-drawer-section {
29
+ display: flex;
30
+ flex-direction: column;
31
+ }
32
+ /* 16dp above, and 28dp in from both edges of the drawer, like the labels. */
33
+ .np-navigation-drawer-section-divider {
34
+ height: 1px;
35
+ margin: 1rem 1rem 0;
36
+ background-color: var(--np-divider-color, var(--np-color-outline-variant));
37
+ }
38
+ .np-navigation-drawer-section-label {
39
+ display: flex;
40
+ align-items: center;
41
+ min-height: 3.5rem;
42
+ padding-inline: 1rem;
43
+ font-size: 0.875rem;
44
+ line-height: 1.25rem;
45
+ font-weight: 500;
46
+ letter-spacing: 0.006rem;
47
+ color: var(--np-color-on-surface-variant);
48
+ }
49
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { NavigationDrawerSectionProps } from './types.js';
2
+ declare const NavigationDrawerSection: import("svelte").Component<NavigationDrawerSectionProps, {}, "element">;
3
+ type NavigationDrawerSection = ReturnType<typeof NavigationDrawerSection>;
4
+ export default NavigationDrawerSection;
@@ -1,2 +1,3 @@
1
1
  export { default as NavigationDrawer } from './NavigationDrawer.svelte';
2
2
  export { default as NavigationDrawerItem } from './NavigationDrawerItem.svelte';
3
+ export { default as NavigationDrawerSection } from './NavigationDrawerSection.svelte';
@@ -1,2 +1,3 @@
1
1
  export { default as NavigationDrawer } from './NavigationDrawer.svelte';
2
2
  export { default as NavigationDrawerItem } from './NavigationDrawerItem.svelte';
3
+ export { default as NavigationDrawerSection } from './NavigationDrawerSection.svelte';
@@ -2,8 +2,15 @@ import type { Snippet } from 'svelte';
2
2
  import type { HTMLAnchorAttributes, HTMLAttributes, HTMLButtonAttributes } from 'svelte/elements';
3
3
  export interface NavigationDrawerProps extends HTMLAttributes<HTMLElement> {
4
4
  modal?: boolean;
5
+ /** The scrim behind a modal drawer. On by default, as Material 3 asks. */
5
6
  backdrop?: boolean;
7
+ /**
8
+ * Modal: whether the drawer is open. Standard: leave it out for a drawer that is always there,
9
+ * or set it to make the drawer dismissible, sliding in and out.
10
+ */
6
11
  open?: boolean;
12
+ /** A headline above the destinations. It names the navigation unless `aria-label` does. */
13
+ headline?: string;
7
14
  element?: HTMLElement;
8
15
  /**
9
16
  * The edge the modal drawer slides in from: `ltr` from the left, `rtl` from the right. Leave it
@@ -21,3 +28,8 @@ export interface NavigationDrawerItemProps extends HTMLAttributes<NavigationDraw
21
28
  type?: 'submit' | 'reset' | 'button' | (string & {}) | null;
22
29
  element?: NavigationDrawerItemElement;
23
30
  }
31
+ export interface NavigationDrawerSectionProps extends HTMLAttributes<HTMLDivElement> {
32
+ /** The section label, shown above the destinations and naming the group. */
33
+ label: string;
34
+ element?: HTMLDivElement;
35
+ }