@noahbaumgartner/svelte-ui 0.0.4 → 0.0.6

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 (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +28 -13
  3. package/dist/components/accordion/Accordion.svelte +44 -0
  4. package/dist/components/accordion/Accordion.svelte.d.ts +13 -0
  5. package/dist/components/accordion/AccordionItem.svelte +145 -0
  6. package/dist/components/accordion/AccordionItem.svelte.d.ts +17 -0
  7. package/dist/components/accordion/context.d.ts +5 -0
  8. package/dist/components/accordion/context.js +2 -0
  9. package/dist/components/alert-dialog/AlertDialog.svelte +108 -76
  10. package/dist/components/alert-dialog/AlertDialog.svelte.d.ts +5 -2
  11. package/dist/components/avatar/Avatar.svelte +71 -49
  12. package/dist/components/avatar/Avatar.svelte.d.ts +5 -2
  13. package/dist/components/avatar-group/AvatarGroup.svelte +103 -0
  14. package/dist/components/avatar-group/AvatarGroup.svelte.d.ts +19 -0
  15. package/dist/components/badge/Badge.svelte +50 -28
  16. package/dist/components/badge/Badge.svelte.d.ts +6 -4
  17. package/dist/components/breadcrumb/Breadcrumb.svelte +21 -17
  18. package/dist/components/breadcrumb/Breadcrumb.svelte.d.ts +3 -1
  19. package/dist/components/breadcrumb/BreadcrumbEllipsis.svelte +17 -6
  20. package/dist/components/breadcrumb/BreadcrumbEllipsis.svelte.d.ts +5 -2
  21. package/dist/components/breadcrumb/BreadcrumbItem.svelte +75 -36
  22. package/dist/components/breadcrumb/BreadcrumbItem.svelte.d.ts +8 -5
  23. package/dist/components/breadcrumb/BreadcrumbSeparator.svelte +32 -9
  24. package/dist/components/breadcrumb/BreadcrumbSeparator.svelte.d.ts +10 -17
  25. package/dist/components/button/Button.svelte +206 -168
  26. package/dist/components/button/Button.svelte.d.ts +9 -5
  27. package/dist/components/button-group/ButtonGroup.svelte +52 -55
  28. package/dist/components/button-group/ButtonGroup.svelte.d.ts +3 -1
  29. package/dist/components/calendar/Calendar.svelte +232 -144
  30. package/dist/components/calendar/Calendar.svelte.d.ts +19 -2
  31. package/dist/components/calendar/dates.d.ts +4 -1
  32. package/dist/components/calendar/dates.js +8 -2
  33. package/dist/components/card/Card.svelte +48 -32
  34. package/dist/components/card/Card.svelte.d.ts +3 -1
  35. package/dist/components/card/CardAction.svelte +11 -7
  36. package/dist/components/card/CardAction.svelte.d.ts +3 -1
  37. package/dist/components/card/CardContent.svelte +8 -4
  38. package/dist/components/card/CardContent.svelte.d.ts +3 -1
  39. package/dist/components/card/CardDescription.svelte +11 -7
  40. package/dist/components/card/CardDescription.svelte.d.ts +3 -1
  41. package/dist/components/card/CardFooter.svelte +15 -11
  42. package/dist/components/card/CardFooter.svelte.d.ts +3 -1
  43. package/dist/components/card/CardHeader.svelte +15 -11
  44. package/dist/components/card/CardHeader.svelte.d.ts +3 -1
  45. package/dist/components/card/CardTitle.svelte +11 -7
  46. package/dist/components/card/CardTitle.svelte.d.ts +3 -1
  47. package/dist/components/checkbox/Checkbox.svelte +152 -61
  48. package/dist/components/checkbox/Checkbox.svelte.d.ts +5 -2
  49. package/dist/components/color-picker/ColorPicker.svelte +131 -78
  50. package/dist/components/color-picker/ColorPicker.svelte.d.ts +10 -1
  51. package/dist/components/context-menu/ContextMenu.svelte +78 -61
  52. package/dist/components/context-menu/ContextMenu.svelte.d.ts +5 -2
  53. package/dist/components/context-menu/ContextMenuInfo.svelte +91 -0
  54. package/dist/components/context-menu/ContextMenuInfo.svelte.d.ts +19 -0
  55. package/dist/components/context-menu/ContextMenuItem.svelte +102 -57
  56. package/dist/components/context-menu/ContextMenuItem.svelte.d.ts +10 -5
  57. package/dist/components/context-menu/ContextMenuLabel.svelte +28 -0
  58. package/dist/components/context-menu/ContextMenuLabel.svelte.d.ts +10 -0
  59. package/dist/components/context-menu/ContextMenuSeparator.svelte +29 -0
  60. package/dist/components/context-menu/ContextMenuSeparator.svelte.d.ts +8 -0
  61. package/dist/components/dialog/Dialog.svelte +149 -108
  62. package/dist/components/dialog/Dialog.svelte.d.ts +7 -2
  63. package/dist/components/drawer/Drawer.svelte +419 -0
  64. package/dist/components/drawer/Drawer.svelte.d.ts +28 -0
  65. package/dist/components/empty-state/EmptyState.svelte +106 -0
  66. package/dist/components/empty-state/EmptyState.svelte.d.ts +19 -0
  67. package/dist/components/entry/Entry.svelte +94 -0
  68. package/dist/components/entry/Entry.svelte.d.ts +16 -0
  69. package/dist/components/field/Field.svelte +66 -45
  70. package/dist/components/field/Field.svelte.d.ts +2 -1
  71. package/dist/components/field/FieldContent.svelte +11 -8
  72. package/dist/components/field/FieldContent.svelte.d.ts +2 -1
  73. package/dist/components/field/FieldDescription.svelte +18 -15
  74. package/dist/components/field/FieldDescription.svelte.d.ts +2 -1
  75. package/dist/components/field/FieldError.svelte +22 -13
  76. package/dist/components/field/FieldError.svelte.d.ts +2 -1
  77. package/dist/components/field/FieldGroup.svelte +15 -12
  78. package/dist/components/field/FieldGroup.svelte.d.ts +2 -1
  79. package/dist/components/field/FieldLegend.svelte +23 -14
  80. package/dist/components/field/FieldLegend.svelte.d.ts +2 -1
  81. package/dist/components/field/FieldSeparator.svelte +12 -9
  82. package/dist/components/field/FieldSeparator.svelte.d.ts +2 -1
  83. package/dist/components/field/FieldSet.svelte +18 -15
  84. package/dist/components/field/FieldSet.svelte.d.ts +2 -1
  85. package/dist/components/footer/Footer.svelte +105 -0
  86. package/dist/components/footer/Footer.svelte.d.ts +14 -0
  87. package/dist/components/footer/FooterColumn.svelte +37 -0
  88. package/dist/components/footer/FooterColumn.svelte.d.ts +11 -0
  89. package/dist/components/image/Image.svelte +61 -0
  90. package/dist/components/image/Image.svelte.d.ts +18 -0
  91. package/dist/components/input/Input.svelte +307 -208
  92. package/dist/components/input/Input.svelte.d.ts +12 -1
  93. package/dist/components/input-group/InputGroup.svelte +101 -61
  94. package/dist/components/input-group/InputGroup.svelte.d.ts +2 -1
  95. package/dist/components/input-group/InputGroupAddon.svelte +58 -49
  96. package/dist/components/kbd/Kbd.svelte +39 -30
  97. package/dist/components/kbd/Kbd.svelte.d.ts +2 -1
  98. package/dist/components/kbd/KbdGroup.svelte +15 -12
  99. package/dist/components/kbd/KbdGroup.svelte.d.ts +2 -1
  100. package/dist/components/label/Label.svelte +47 -28
  101. package/dist/components/label/Label.svelte.d.ts +2 -1
  102. package/dist/components/link/Link.svelte +71 -17
  103. package/dist/components/link/Link.svelte.d.ts +2 -1
  104. package/dist/components/mesh-gradient/MeshGradient.svelte +97 -0
  105. package/dist/components/mesh-gradient/MeshGradient.svelte.d.ts +11 -0
  106. package/dist/components/navbar/Navbar.svelte +137 -99
  107. package/dist/components/navbar/Navbar.svelte.d.ts +4 -2
  108. package/dist/components/navigation-menu/NavigationMenu.svelte +37 -20
  109. package/dist/components/navigation-menu/NavigationMenu.svelte.d.ts +4 -2
  110. package/dist/components/navigation-menu/NavigationMenuItem.svelte +131 -89
  111. package/dist/components/navigation-menu/NavigationMenuItem.svelte.d.ts +4 -2
  112. package/dist/components/navigation-menu/NavigationMenuLink.svelte +90 -51
  113. package/dist/components/navigation-menu/NavigationMenuLink.svelte.d.ts +7 -5
  114. package/dist/components/number-stepper/NumberStepper.svelte +101 -0
  115. package/dist/components/number-stepper/NumberStepper.svelte.d.ts +21 -0
  116. package/dist/components/popover/Popover.svelte +85 -65
  117. package/dist/components/popover/Popover.svelte.d.ts +5 -2
  118. package/dist/components/preview-card/PreviewCard.svelte +184 -0
  119. package/dist/components/preview-card/PreviewCard.svelte.d.ts +23 -0
  120. package/dist/components/progress/Progress.svelte +111 -0
  121. package/dist/components/progress/Progress.svelte.d.ts +13 -0
  122. package/dist/components/radio-group/RadioGroup.svelte +24 -19
  123. package/dist/components/radio-group/RadioGroup.svelte.d.ts +2 -1
  124. package/dist/components/radio-group/RadioGroupItem.svelte +101 -54
  125. package/dist/components/radio-group/RadioGroupItem.svelte.d.ts +2 -1
  126. package/dist/components/section/Section.svelte +114 -0
  127. package/dist/components/section/Section.svelte.d.ts +22 -0
  128. package/dist/components/select/Select.svelte +474 -0
  129. package/dist/components/select/Select.svelte.d.ts +48 -0
  130. package/dist/components/separator/Separator.svelte +21 -10
  131. package/dist/components/separator/Separator.svelte.d.ts +2 -1
  132. package/dist/components/sidebar/Sidebar.svelte +158 -87
  133. package/dist/components/sidebar/Sidebar.svelte.d.ts +6 -1
  134. package/dist/components/sidebar/SidebarContent.svelte +15 -12
  135. package/dist/components/sidebar/SidebarContent.svelte.d.ts +2 -1
  136. package/dist/components/sidebar/SidebarFooter.svelte +10 -7
  137. package/dist/components/sidebar/SidebarFooter.svelte.d.ts +2 -1
  138. package/dist/components/sidebar/SidebarGroup.svelte +35 -25
  139. package/dist/components/sidebar/SidebarGroup.svelte.d.ts +2 -1
  140. package/dist/components/sidebar/SidebarHeader.svelte +37 -8
  141. package/dist/components/sidebar/SidebarHeader.svelte.d.ts +6 -1
  142. package/dist/components/sidebar/SidebarInset.svelte +11 -8
  143. package/dist/components/sidebar/SidebarInset.svelte.d.ts +2 -1
  144. package/dist/components/sidebar/SidebarMenu.svelte +13 -10
  145. package/dist/components/sidebar/SidebarMenu.svelte.d.ts +2 -1
  146. package/dist/components/sidebar/SidebarMenuItem.svelte +195 -114
  147. package/dist/components/sidebar/SidebarMenuItem.svelte.d.ts +11 -5
  148. package/dist/components/sidebar/SidebarProvider.svelte +18 -9
  149. package/dist/components/sidebar/SidebarProvider.svelte.d.ts +2 -1
  150. package/dist/components/sidebar/SidebarSeparator.svelte +6 -1
  151. package/dist/components/sidebar/SidebarSeparator.svelte.d.ts +6 -17
  152. package/dist/components/sidebar/SidebarTrigger.svelte +17 -5
  153. package/dist/components/sidebar/SidebarTrigger.svelte.d.ts +4 -2
  154. package/dist/components/skeleton/Skeleton.svelte +26 -16
  155. package/dist/components/skeleton/Skeleton.svelte.d.ts +4 -2
  156. package/dist/components/spinner/Spinner.svelte +71 -46
  157. package/dist/components/spinner/Spinner.svelte.d.ts +2 -1
  158. package/dist/components/switch/Switch.svelte +126 -65
  159. package/dist/components/switch/Switch.svelte.d.ts +4 -2
  160. package/dist/components/table/Table.svelte +135 -76
  161. package/dist/components/table/Table.svelte.d.ts +12 -2
  162. package/dist/components/tabs/Tabs.svelte +337 -0
  163. package/dist/components/tabs/Tabs.svelte.d.ts +50 -0
  164. package/dist/components/textarea/Textarea.svelte +76 -42
  165. package/dist/components/textarea/Textarea.svelte.d.ts +4 -1
  166. package/dist/components/time-picker/TimePicker.svelte +214 -85
  167. package/dist/components/time-picker/TimePicker.svelte.d.ts +18 -1
  168. package/dist/components/toaster/Toaster.svelte +132 -70
  169. package/dist/components/toaster/Toaster.svelte.d.ts +18 -2
  170. package/dist/components/toaster/toast.svelte.d.ts +3 -3
  171. package/dist/components/toggle/Toggle.svelte +25 -4
  172. package/dist/components/toggle/Toggle.svelte.d.ts +1 -1
  173. package/dist/components/tooltip/Tooltip.svelte +87 -58
  174. package/dist/components/tooltip/Tooltip.svelte.d.ts +4 -2
  175. package/dist/icon.d.ts +12 -0
  176. package/dist/icon.js +1 -0
  177. package/dist/index.d.ts +21 -0
  178. package/dist/index.js +19 -0
  179. package/dist/internal/icons/ArrowDown.svelte +14 -0
  180. package/dist/internal/icons/ArrowDown.svelte.d.ts +4 -0
  181. package/dist/internal/icons/ArrowUp.svelte +14 -0
  182. package/dist/internal/icons/ArrowUp.svelte.d.ts +4 -0
  183. package/dist/internal/icons/Calendar.svelte +16 -0
  184. package/dist/internal/icons/Calendar.svelte.d.ts +4 -0
  185. package/dist/internal/icons/Check.svelte +8 -0
  186. package/dist/internal/icons/Check.svelte.d.ts +4 -0
  187. package/dist/internal/icons/ChevronDown.svelte +8 -0
  188. package/dist/internal/icons/ChevronDown.svelte.d.ts +4 -0
  189. package/dist/internal/icons/ChevronLeft.svelte +8 -0
  190. package/dist/internal/icons/ChevronLeft.svelte.d.ts +4 -0
  191. package/dist/internal/icons/ChevronRight.svelte +8 -0
  192. package/dist/internal/icons/ChevronRight.svelte.d.ts +4 -0
  193. package/dist/internal/icons/ChevronUp.svelte +8 -0
  194. package/dist/internal/icons/ChevronUp.svelte.d.ts +4 -0
  195. package/dist/internal/icons/ChevronsUpDown.svelte +14 -0
  196. package/dist/internal/icons/ChevronsUpDown.svelte.d.ts +4 -0
  197. package/dist/internal/icons/Clock.svelte +14 -0
  198. package/dist/internal/icons/Clock.svelte.d.ts +4 -0
  199. package/dist/internal/icons/Ellipsis.svelte +15 -0
  200. package/dist/internal/icons/Ellipsis.svelte.d.ts +4 -0
  201. package/dist/internal/icons/Icon.svelte +33 -0
  202. package/dist/internal/icons/Icon.svelte.d.ts +8 -0
  203. package/dist/internal/icons/Minus.svelte +8 -0
  204. package/dist/internal/icons/Minus.svelte.d.ts +4 -0
  205. package/dist/internal/icons/PanelLeft.svelte +14 -0
  206. package/dist/internal/icons/PanelLeft.svelte.d.ts +4 -0
  207. package/dist/internal/icons/Plus.svelte +14 -0
  208. package/dist/internal/icons/Plus.svelte.d.ts +4 -0
  209. package/dist/internal/icons/User.svelte +14 -0
  210. package/dist/internal/icons/User.svelte.d.ts +4 -0
  211. package/dist/internal/icons/X.svelte +14 -0
  212. package/dist/internal/icons/X.svelte.d.ts +4 -0
  213. package/dist/styles/tokens.css +39 -41
  214. package/package.json +5 -10
  215. package/dist/icons.d.ts +0 -2
  216. package/dist/icons.js +0 -4
@@ -3,7 +3,8 @@ import type { HTMLAttributes } from 'svelte/elements';
3
3
  type Props = Omit<HTMLAttributes<HTMLUListElement>, 'children'> & {
4
4
  /** `SidebarMenuItem`s. */
5
5
  children: Snippet;
6
+ ref?: HTMLUListElement | null;
6
7
  };
7
- declare const SidebarMenu: import("svelte").Component<Props, {}, "">;
8
+ declare const SidebarMenu: import("svelte").Component<Props, {}, "ref">;
8
9
  type SidebarMenu = ReturnType<typeof SidebarMenu>;
9
10
  export default SidebarMenu;
@@ -1,17 +1,18 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
3
4
  import { slide } from 'svelte/transition';
4
- import type { LucideIcon } from '@lucide/svelte';
5
- import ChevronRight from '@lucide/svelte/icons/chevron-right';
6
- import Ellipsis from '@lucide/svelte/icons/ellipsis';
5
+ import type { IconComponent } from '../../icon.js';
6
+ import ChevronRight from '../../internal/icons/ChevronRight.svelte';
7
+ import Ellipsis from '../../internal/icons/Ellipsis.svelte';
7
8
  import Button from '../button/Button.svelte';
8
9
  import ContextMenu from '../context-menu/ContextMenu.svelte';
9
10
 
10
- type Props = {
11
+ type Props = Omit<HTMLAttributes<HTMLLIElement>, 'children' | 'onclick'> & {
11
12
  /** Links the item. Ignored when the item has `items`. */
12
13
  href?: string;
13
- /** Any Lucide icon (import from `svelte-ui/icons`). Stays visible when the sidebar is collapsed to icons. */
14
- icon?: LucideIcon;
14
+ /** Any icon component, e.g. from `@lucide/svelte`. Stays visible when the sidebar is collapsed to icons. */
15
+ icon?: IconComponent;
15
16
  /** Marks the item as the current page. */
16
17
  active?: boolean;
17
18
  /** Short count or status at the end of the item, e.g. unread messages. */
@@ -24,6 +25,9 @@
24
25
  menu?: Snippet;
25
26
  onclick?: () => void;
26
27
  children: Snippet;
28
+ /** Accessible name of the menu trigger. */
29
+ labels?: { more?: string };
30
+ ref?: HTMLLIElement | null;
27
31
  };
28
32
 
29
33
  let {
@@ -35,12 +39,20 @@
35
39
  expanded = $bindable(false),
36
40
  menu,
37
41
  onclick,
38
- children
42
+ children,
43
+ labels,
44
+ ref = $bindable(null),
45
+ class: className,
46
+ ...rest
39
47
  }: Props = $props();
40
48
 
41
49
  const id = $props.id();
42
50
  let classes = $derived(['sidebar-menu-button', { 'sidebar-menu-button--active': active }]);
43
51
 
52
+ function reducedMotion() {
53
+ return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
54
+ }
55
+
44
56
  function toggle() {
45
57
  expanded = !expanded;
46
58
  onclick?.();
@@ -54,7 +66,11 @@
54
66
  {#if items}<ChevronRight class="sidebar-menu-item-chevron" aria-hidden="true" />{/if}
55
67
  {/snippet}
56
68
 
57
- <li class={['sidebar-menu-item', { 'sidebar-menu-item--has-menu': menu }]}>
69
+ <li
70
+ {...rest}
71
+ bind:this={ref}
72
+ class={['sidebar-menu-item', { 'sidebar-menu-item--has-menu': menu }, className]}
73
+ >
58
74
  {#if items}
59
75
  <button
60
76
  type="button"
@@ -81,7 +97,13 @@
81
97
  <div class="sidebar-menu-item-menu">
82
98
  <ContextMenu align="end">
83
99
  {#snippet trigger(props)}
84
- <Button {...props} variant="ghost" size="sm" icon={Ellipsis} label="More" />
100
+ <Button
101
+ {...props}
102
+ variant="ghost"
103
+ size="sm"
104
+ icon={Ellipsis}
105
+ label={labels?.more ?? 'More'}
106
+ />
85
107
  {/snippet}
86
108
  {@render menu()}
87
109
  </ContextMenu>
@@ -89,133 +111,192 @@
89
111
  {/if}
90
112
 
91
113
  {#if items && expanded}
92
- <ul id="{id}-items" class="sidebar-menu-sub" transition:slide={{ duration: 200 }}>
114
+ <ul
115
+ id="{id}-items"
116
+ class="sidebar-menu-sub"
117
+ transition:slide={{ duration: reducedMotion() ? 0 : 200 }}
118
+ >
93
119
  {@render items()}
94
120
  </ul>
95
121
  {/if}
96
122
  </li>
97
123
 
98
124
  <style>
99
- .sidebar-menu-item {
100
- position: relative;
101
- min-width: 0;
102
- }
103
-
104
- .sidebar-menu-button {
105
- display: flex;
106
- align-items: center;
107
- gap: 8px;
108
- width: 100%;
109
- height: 32px;
110
- padding: 0 8px;
111
- box-sizing: border-box;
112
- overflow: hidden;
113
- background-color: transparent;
114
- border: none;
115
- border-radius: 8px;
116
- font: inherit;
117
- font-size: 13px;
118
- color: var(--color-text-secondary);
119
- text-align: left;
120
- text-decoration: none;
121
- outline: none;
122
- cursor: pointer;
123
- transition:
124
- background-color 150ms ease,
125
- color 150ms ease,
126
- width 200ms ease;
127
- }
128
-
129
- .sidebar-menu-button:hover {
130
- background-color: var(--color-surface);
131
- color: var(--color-text);
132
- }
125
+ @layer svelte-ui {
126
+ .sidebar-menu-item {
127
+ position: relative;
128
+ min-width: 0;
129
+ }
133
130
 
134
- .sidebar-menu-button:focus-visible {
135
- outline: 2px solid var(--color-accent);
136
- outline-offset: -2px;
137
- }
131
+ .sidebar-menu-button {
132
+ display: flex;
133
+ align-items: center;
134
+ gap: 8px;
135
+ width: 100%;
136
+ height: 32px;
137
+ padding: 0 8px;
138
+ box-sizing: border-box;
139
+ overflow: hidden;
140
+ background-color: transparent;
141
+ border: none;
142
+ border-radius: 8px;
143
+ font: inherit;
144
+ font-size: 13px;
145
+ color: var(--color-text-secondary);
146
+ text-align: left;
147
+ text-decoration: none;
148
+ outline: none;
149
+ cursor: pointer;
150
+ transition:
151
+ background-color 150ms ease,
152
+ color 150ms ease,
153
+ width 200ms ease;
154
+ }
138
155
 
139
- .sidebar-menu-button--active {
140
- background-color: var(--color-surface);
141
- color: var(--color-text);
142
- font-weight: 500;
143
- }
156
+ .sidebar-menu-button:hover {
157
+ background-color: var(--color-surface);
158
+ color: var(--color-text);
159
+ }
144
160
 
145
- .sidebar-menu-item--has-menu > .sidebar-menu-button {
146
- padding-right: 36px;
147
- }
161
+ .sidebar-menu-button:focus-visible {
162
+ outline: 2px solid var(--color-accent);
163
+ outline-offset: -2px;
164
+ }
148
165
 
149
- .sidebar-menu-item :global(.sidebar-menu-item-icon) {
150
- width: 16px;
151
- height: 16px;
152
- flex-shrink: 0;
153
- }
166
+ .sidebar-menu-button--active {
167
+ background-color: var(--color-surface);
168
+ color: var(--color-text);
169
+ font-weight: 500;
170
+ }
154
171
 
155
- .sidebar-menu-item-label {
156
- flex: 1;
157
- min-width: 0;
158
- overflow: hidden;
159
- white-space: nowrap;
160
- text-overflow: ellipsis;
161
- }
172
+ .sidebar-menu-item--has-menu > .sidebar-menu-button {
173
+ padding-right: 36px;
174
+ }
162
175
 
163
- .sidebar-menu-item-badge {
164
- font-size: 12px;
165
- font-variant-numeric: tabular-nums;
166
- color: var(--color-text-muted);
167
- }
176
+ .sidebar-menu-item :global(.sidebar-menu-item-icon) {
177
+ width: 16px;
178
+ height: 16px;
179
+ flex-shrink: 0;
180
+ }
168
181
 
169
- .sidebar-menu-item :global(.sidebar-menu-item-chevron) {
170
- width: 14px;
171
- height: 14px;
172
- flex-shrink: 0;
173
- color: var(--color-text-muted);
174
- transition: rotate 200ms ease;
175
- }
182
+ .sidebar-menu-item-label {
183
+ flex: 1;
184
+ min-width: 0;
185
+ overflow: hidden;
186
+ white-space: nowrap;
187
+ text-overflow: ellipsis;
188
+ }
176
189
 
177
- .sidebar-menu-button[aria-expanded='true'] :global(.sidebar-menu-item-chevron) {
178
- rotate: 90deg;
179
- }
190
+ .sidebar-menu-item-badge {
191
+ font-size: 12px;
192
+ font-variant-numeric: tabular-nums;
193
+ color: var(--color-text-muted);
194
+ }
180
195
 
181
- /* Menu trigger, shown while the item is hovered or the menu has focus */
182
- .sidebar-menu-item-menu {
183
- position: absolute;
184
- top: 2px;
185
- right: 2px;
186
- opacity: 0;
187
- transition: opacity 150ms ease;
188
- }
196
+ .sidebar-menu-item :global(.sidebar-menu-item-chevron) {
197
+ width: 14px;
198
+ height: 14px;
199
+ flex-shrink: 0;
200
+ color: var(--color-text-muted);
201
+ transition: rotate 200ms ease;
202
+ }
189
203
 
190
- .sidebar-menu-item:hover > .sidebar-menu-item-menu,
191
- .sidebar-menu-item-menu:focus-within {
192
- opacity: 1;
193
- }
204
+ .sidebar-menu-button[aria-expanded='true'] :global(.sidebar-menu-item-chevron) {
205
+ rotate: 90deg;
206
+ }
194
207
 
195
- @media (hover: none) {
208
+ /* Menu trigger, shown while the item is hovered or the menu has focus */
196
209
  .sidebar-menu-item-menu {
210
+ position: absolute;
211
+ top: 2px;
212
+ right: 2px;
213
+ opacity: 0;
214
+ transition: opacity 150ms ease;
215
+ }
216
+
217
+ .sidebar-menu-item:hover > .sidebar-menu-item-menu,
218
+ .sidebar-menu-item-menu:focus-within {
197
219
  opacity: 1;
198
220
  }
199
- }
200
221
 
201
- .sidebar-menu-sub {
202
- display: flex;
203
- flex-direction: column;
204
- gap: 2px;
205
- margin: 2px 0 2px 15px;
206
- padding: 0 0 0 8px;
207
- list-style: none;
208
- border-left: 1px solid var(--color-border);
209
- }
222
+ @media (hover: none) {
223
+ .sidebar-menu-item-menu {
224
+ opacity: 1;
225
+ }
226
+ }
210
227
 
211
- /* Collapsed to icons: a square button with the label clipped (it stays the accessible name) */
212
- :global(.sidebar--collapsed-icon) .sidebar-menu-item .sidebar-menu-button {
213
- width: 32px;
214
- padding: 0 8px;
215
- }
228
+ .sidebar-menu-sub {
229
+ display: flex;
230
+ flex-direction: column;
231
+ gap: 2px;
232
+ margin: 2px 0 2px 15px;
233
+ padding: 0 0 0 8px;
234
+ list-style: none;
235
+ border-left: 1px solid var(--color-border);
236
+ }
237
+
238
+ /* Collapsed to icons: a square button with the label clipped (it stays the accessible name) */
239
+ :global(.sidebar--collapsed-icon) .sidebar-menu-item .sidebar-menu-button {
240
+ width: 32px;
241
+ padding: 0 8px;
242
+ }
243
+
244
+ @media (pointer: coarse) {
245
+ .sidebar-menu-button {
246
+ min-height: 44px;
247
+ }
216
248
 
217
- :global(.sidebar--collapsed-icon) .sidebar-menu-item-menu,
218
- :global(.sidebar--collapsed-icon) .sidebar-menu-sub {
219
- display: none;
249
+ .sidebar-menu-item-menu {
250
+ top: 0;
251
+ right: 0;
252
+ }
253
+
254
+ .sidebar-menu-item-menu :global(.button) {
255
+ min-width: 44px;
256
+ min-height: 44px;
257
+ }
258
+
259
+ .sidebar-menu-item--has-menu > .sidebar-menu-button {
260
+ padding-right: 48px;
261
+ }
262
+ }
263
+
264
+ @media (forced-colors: active) {
265
+ .sidebar-menu-button {
266
+ color: ButtonText;
267
+ }
268
+
269
+ .sidebar-menu-button:hover {
270
+ outline: 1px solid Highlight;
271
+ outline-offset: -1px;
272
+ }
273
+
274
+ .sidebar-menu-button--active {
275
+ background-color: Highlight;
276
+ color: HighlightText;
277
+ }
278
+
279
+ .sidebar-menu-button:focus-visible {
280
+ outline: 2px solid CanvasText;
281
+ outline-offset: -2px;
282
+ }
283
+
284
+ .sidebar-menu-sub {
285
+ border-left-color: CanvasText;
286
+ }
287
+ }
288
+
289
+ @media (prefers-reduced-motion: reduce) {
290
+ .sidebar-menu-button,
291
+ .sidebar-menu-item :global(.sidebar-menu-item-chevron),
292
+ .sidebar-menu-item-menu {
293
+ transition: none;
294
+ }
295
+ }
296
+
297
+ :global(.sidebar--collapsed-icon) .sidebar-menu-item-menu,
298
+ :global(.sidebar--collapsed-icon) .sidebar-menu-sub {
299
+ display: none;
300
+ }
220
301
  }
221
302
  </style>
@@ -1,10 +1,11 @@
1
1
  import type { Snippet } from 'svelte';
2
- import type { LucideIcon } from '@lucide/svelte';
3
- type Props = {
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { IconComponent } from '../../icon.js';
4
+ type Props = Omit<HTMLAttributes<HTMLLIElement>, 'children' | 'onclick'> & {
4
5
  /** Links the item. Ignored when the item has `items`. */
5
6
  href?: string;
6
- /** Any Lucide icon (import from `svelte-ui/icons`). Stays visible when the sidebar is collapsed to icons. */
7
- icon?: LucideIcon;
7
+ /** Any icon component, e.g. from `@lucide/svelte`. Stays visible when the sidebar is collapsed to icons. */
8
+ icon?: IconComponent;
8
9
  /** Marks the item as the current page. */
9
10
  active?: boolean;
10
11
  /** Short count or status at the end of the item, e.g. unread messages. */
@@ -17,7 +18,12 @@ type Props = {
17
18
  menu?: Snippet;
18
19
  onclick?: () => void;
19
20
  children: Snippet;
21
+ /** Accessible name of the menu trigger. */
22
+ labels?: {
23
+ more?: string;
24
+ };
25
+ ref?: HTMLLIElement | null;
20
26
  };
21
- declare const SidebarMenuItem: import("svelte").Component<Props, {}, "expanded">;
27
+ declare const SidebarMenuItem: import("svelte").Component<Props, {}, "ref" | "expanded">;
22
28
  type SidebarMenuItem = ReturnType<typeof SidebarMenuItem>;
23
29
  export default SidebarMenuItem;
@@ -8,9 +8,16 @@
8
8
  open?: boolean;
9
9
  /** A `Sidebar` and a `SidebarInset`. Size them with the `--sidebar-width`, `--sidebar-width-icon` and `--sidebar-height` custom properties. */
10
10
  children: Snippet;
11
+ ref?: HTMLDivElement | null;
11
12
  };
12
13
 
13
- let { open = $bindable(true), class: className, children, ...rest }: Props = $props();
14
+ let {
15
+ open = $bindable(true),
16
+ ref = $bindable(null),
17
+ class: className,
18
+ children,
19
+ ...rest
20
+ }: Props = $props();
14
21
 
15
22
  const id = $props.id();
16
23
  let mobile = $state(false);
@@ -46,17 +53,19 @@
46
53
  });
47
54
  </script>
48
55
 
49
- <div {...rest} class={['sidebar-provider', className]}>
56
+ <div {...rest} bind:this={ref} class={['sidebar-provider', className]}>
50
57
  {@render children()}
51
58
  </div>
52
59
 
53
60
  <style>
54
- .sidebar-provider {
55
- --sidebar-width: 256px;
56
- --sidebar-width-icon: 48px;
57
- --sidebar-height: 100svh;
58
- display: flex;
59
- width: 100%;
60
- min-height: var(--sidebar-height);
61
+ @layer svelte-ui {
62
+ .sidebar-provider {
63
+ --sidebar-width: 256px;
64
+ --sidebar-width-icon: 48px;
65
+ --sidebar-height: 100svh;
66
+ display: flex;
67
+ width: 100%;
68
+ min-height: var(--sidebar-height);
69
+ }
61
70
  }
62
71
  </style>
@@ -5,7 +5,8 @@ type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
5
5
  open?: boolean;
6
6
  /** A `Sidebar` and a `SidebarInset`. Size them with the `--sidebar-width`, `--sidebar-width-icon` and `--sidebar-height` custom properties. */
7
7
  children: Snippet;
8
+ ref?: HTMLDivElement | null;
8
9
  };
9
- declare const SidebarProvider: import("svelte").Component<Props, {}, "open">;
10
+ declare const SidebarProvider: import("svelte").Component<Props, {}, "ref" | "open">;
10
11
  type SidebarProvider = ReturnType<typeof SidebarProvider>;
11
12
  export default SidebarProvider;
@@ -1,5 +1,10 @@
1
1
  <script lang="ts">
2
+ import type { ComponentProps } from 'svelte';
2
3
  import Separator from '../separator/Separator.svelte';
4
+
5
+ type Props = ComponentProps<typeof Separator>;
6
+
7
+ let { ref = $bindable(null), style, ...rest }: Props = $props();
3
8
  </script>
4
9
 
5
- <Separator decorative={false} style="margin: 0 8px;" />
10
+ <Separator {...rest} bind:ref decorative={false} style="margin: 0 8px;{style ? ` ${style}` : ''}" />
@@ -1,18 +1,7 @@
1
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
- $$bindings?: Bindings;
4
- } & Exports;
5
- (internal: unknown, props: {
6
- $$events?: Events;
7
- $$slots?: Slots;
8
- }): Exports & {
9
- $set?: any;
10
- $on?: any;
11
- };
12
- z_$$bindings?: Bindings;
13
- }
14
- declare const SidebarSeparator: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
- [evt: string]: CustomEvent<any>;
16
- }, {}, {}, string>;
17
- type SidebarSeparator = InstanceType<typeof SidebarSeparator>;
1
+ declare const SidebarSeparator: import("svelte").Component<Omit<import("svelte/elements").HTMLAttributes<HTMLDivElement>, "children"> & {
2
+ orientation?: "horizontal" | "vertical";
3
+ decorative?: boolean;
4
+ ref?: HTMLDivElement | null;
5
+ }, {}, "ref">;
6
+ type SidebarSeparator = ReturnType<typeof SidebarSeparator>;
18
7
  export default SidebarSeparator;
@@ -1,14 +1,21 @@
1
1
  <script lang="ts">
2
- import PanelLeft from '@lucide/svelte/icons/panel-left';
2
+ import type { ComponentProps } from 'svelte';
3
+ import PanelLeft from '../../internal/icons/PanelLeft.svelte';
3
4
  import Button from '../button/Button.svelte';
4
5
  import { getSidebarContext } from './context.js';
5
6
 
6
- type Props = {
7
+ type Props = Omit<ComponentProps<typeof Button>, 'href' | 'target' | 'rel' | 'type'> & {
7
8
  /** Accessible name of the button. */
8
9
  label?: string;
9
10
  };
10
11
 
11
- let { label = 'Toggle sidebar' }: Props = $props();
12
+ let {
13
+ label = 'Toggle sidebar',
14
+ icon = PanelLeft,
15
+ ref = $bindable(null),
16
+ onclick,
17
+ ...rest
18
+ }: Props = $props();
12
19
 
13
20
  const sidebar = getSidebarContext();
14
21
  </script>
@@ -16,9 +23,14 @@
16
23
  <Button
17
24
  variant="ghost"
18
25
  size="sm"
19
- icon={PanelLeft}
26
+ {icon}
20
27
  {label}
28
+ {...rest}
29
+ bind:ref
21
30
  aria-controls={sidebar.id}
22
31
  aria-expanded={sidebar.mobile ? sidebar.openMobile : sidebar.open}
23
- onclick={sidebar.toggle}
32
+ onclick={(event) => {
33
+ sidebar.toggle();
34
+ onclick?.(event);
35
+ }}
24
36
  />
@@ -1,7 +1,9 @@
1
- type Props = {
1
+ import type { ComponentProps } from 'svelte';
2
+ import Button from '../button/Button.svelte';
3
+ type Props = Omit<ComponentProps<typeof Button>, 'href' | 'target' | 'rel' | 'type'> & {
2
4
  /** Accessible name of the button. */
3
5
  label?: string;
4
6
  };
5
- declare const SidebarTrigger: import("svelte").Component<Props, {}, "">;
7
+ declare const SidebarTrigger: import("svelte").Component<Props, {}, "ref">;
6
8
  type SidebarTrigger = ReturnType<typeof SidebarTrigger>;
7
9
  export default SidebarTrigger;
@@ -1,30 +1,40 @@
1
1
  <script lang="ts">
2
2
  import type { HTMLAttributes } from 'svelte/elements';
3
3
 
4
- type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'>;
4
+ type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
5
+ ref?: HTMLDivElement | null;
6
+ };
5
7
 
6
- let { class: className, ...rest }: Props = $props();
8
+ let { ref = $bindable(null), class: className, ...rest }: Props = $props();
7
9
  </script>
8
10
 
9
- <div {...rest} aria-hidden="true" class={['skeleton', className]}></div>
11
+ <div {...rest} bind:this={ref} aria-hidden="true" class={['skeleton', className]}></div>
10
12
 
11
13
  <style>
12
- .skeleton {
13
- flex-shrink: 0;
14
- border-radius: 6px;
15
- background-color: var(--color-surface);
16
- animation: skeleton-pulse 2s ease-in-out infinite;
17
- }
14
+ @layer svelte-ui {
15
+ .skeleton {
16
+ flex-shrink: 0;
17
+ border-radius: 6px;
18
+ background-color: var(--color-surface);
19
+ animation: skeleton-pulse 2s ease-in-out infinite;
20
+ }
18
21
 
19
- @keyframes skeleton-pulse {
20
- 50% {
21
- opacity: 0.5;
22
+ @keyframes skeleton-pulse {
23
+ 50% {
24
+ opacity: 0.5;
25
+ }
22
26
  }
23
- }
24
27
 
25
- @media (prefers-reduced-motion: reduce) {
26
- .skeleton {
27
- animation: none;
28
+ @media (forced-colors: active) {
29
+ .skeleton {
30
+ border: 1px solid GrayText;
31
+ }
32
+ }
33
+
34
+ @media (prefers-reduced-motion: reduce) {
35
+ .skeleton {
36
+ animation: none;
37
+ }
28
38
  }
29
39
  }
30
40
  </style>
@@ -1,5 +1,7 @@
1
1
  import type { HTMLAttributes } from 'svelte/elements';
2
- type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'>;
3
- declare const Skeleton: import("svelte").Component<Props, {}, "">;
2
+ type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
3
+ ref?: HTMLDivElement | null;
4
+ };
5
+ declare const Skeleton: import("svelte").Component<Props, {}, "ref">;
4
6
  type Skeleton = ReturnType<typeof Skeleton>;
5
7
  export default Skeleton;