@widgetic/design-system 0.5.21 → 0.5.23

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 (246) hide show
  1. package/README.md +2 -0
  2. package/dist/components/CopyableHeader.svelte +260 -448
  3. package/dist/components/CopyableHeader.svelte.d.ts +8 -5
  4. package/dist/components/EmptyState.svelte +100 -128
  5. package/dist/components/EmptyState.svelte.d.ts +16 -19
  6. package/dist/components/GenerateLoader.svelte +17 -10
  7. package/dist/components/PasswordInput.svelte +41 -44
  8. package/dist/components/PasswordInput.svelte.d.ts +2 -0
  9. package/dist/components/ThumbHashImage.svelte +117 -119
  10. package/dist/components/WScrollArea.svelte +47 -41
  11. package/dist/components/chat/ActivityRow.svelte +115 -0
  12. package/dist/components/chat/ActivityRow.svelte.d.ts +18 -0
  13. package/dist/components/chat/ChatHeader.svelte +114 -0
  14. package/dist/components/chat/ChatHeader.svelte.d.ts +26 -0
  15. package/dist/components/chat/Composer.svelte +172 -0
  16. package/dist/components/chat/Composer.svelte.d.ts +27 -0
  17. package/dist/components/chat/Message.svelte +158 -0
  18. package/dist/components/chat/Message.svelte.d.ts +28 -0
  19. package/dist/components/chat/OptionRow.svelte +59 -0
  20. package/dist/components/chat/OptionRow.svelte.d.ts +14 -0
  21. package/dist/components/chat/PlanCard.svelte +220 -0
  22. package/dist/components/chat/PlanCard.svelte.d.ts +34 -0
  23. package/dist/components/chat/QuestionCard.svelte +265 -0
  24. package/dist/components/chat/QuestionCard.svelte.d.ts +38 -0
  25. package/dist/components/chat/ScrollToBottom.svelte +51 -0
  26. package/dist/components/chat/ScrollToBottom.svelte.d.ts +11 -0
  27. package/dist/components/chat/SuggestionCard.svelte +79 -0
  28. package/dist/components/chat/SuggestionCard.svelte.d.ts +20 -0
  29. package/dist/components/chat/TaskRow.svelte +59 -0
  30. package/dist/components/chat/TaskRow.svelte.d.ts +11 -0
  31. package/dist/components/chat/composerLogic.d.ts +16 -0
  32. package/dist/components/chat/composerLogic.js +29 -0
  33. package/dist/components/chat/index.d.ts +16 -0
  34. package/dist/components/chat/index.js +16 -0
  35. package/dist/components/chat/questionCardLogic.d.ts +11 -0
  36. package/dist/components/chat/questionCardLogic.js +39 -0
  37. package/dist/components/index.d.ts +10 -1
  38. package/dist/components/index.js +10 -0
  39. package/dist/components/modals/ActionModal.svelte +186 -180
  40. package/dist/components/modals/BaseModal.svelte +404 -395
  41. package/dist/components/modals/BaseModal.svelte.d.ts +3 -0
  42. package/dist/components/modals/NewItemDialog.svelte +200 -243
  43. package/dist/components/modals/Portal.svelte +107 -105
  44. package/dist/components/modals/README.md +16 -2
  45. package/dist/components/modals/RenameDialog.svelte +234 -292
  46. package/dist/components/navigation/Breadcrumbs.svelte +415 -377
  47. package/dist/components/navigation/Breadcrumbs.svelte.d.ts +3 -2
  48. package/dist/components/navigation/types.d.ts +2 -0
  49. package/dist/components/pdf/PDFViewer.svelte +54 -1
  50. package/dist/components/search-input/SearchInput.svelte +51 -104
  51. package/dist/components/search-input/SearchInput.svelte.d.ts +9 -27
  52. package/dist/components/shad-editor/editor.css +1 -1
  53. package/dist/components/shad-editor/i18n/messages.d.ts +1 -1
  54. package/dist/components/shad-editor/i18n/messages.js +1 -1
  55. package/dist/components/shell/AppShell.svelte +52 -0
  56. package/dist/components/shell/AppShell.svelte.d.ts +13 -0
  57. package/dist/components/shell/Banner.svelte +90 -0
  58. package/dist/components/shell/Banner.svelte.d.ts +61 -0
  59. package/dist/components/shell/ErrorState.svelte +60 -0
  60. package/dist/components/shell/ErrorState.svelte.d.ts +13 -0
  61. package/dist/components/shell/Link.svelte +63 -0
  62. package/dist/components/shell/Link.svelte.d.ts +53 -0
  63. package/dist/components/shell/NavDrawer.svelte +117 -0
  64. package/dist/components/shell/NavDrawer.svelte.d.ts +10 -0
  65. package/dist/components/shell/NavRow.svelte +128 -0
  66. package/dist/components/shell/NavRow.svelte.d.ts +65 -0
  67. package/dist/components/shell/NavSectionLabel.svelte +27 -0
  68. package/dist/components/shell/NavSectionLabel.svelte.d.ts +9 -0
  69. package/dist/components/shell/NotificationRow.svelte +76 -0
  70. package/dist/components/shell/NotificationRow.svelte.d.ts +16 -0
  71. package/dist/components/shell/PageHeader.svelte +42 -0
  72. package/dist/components/shell/PageHeader.svelte.d.ts +12 -0
  73. package/dist/components/shell/ProfileRow.svelte +95 -0
  74. package/dist/components/shell/ProfileRow.svelte.d.ts +54 -0
  75. package/dist/components/shell/SettingsDialog.svelte +118 -0
  76. package/dist/components/shell/SettingsDialog.svelte.d.ts +19 -0
  77. package/dist/components/shell/SettingsNav.svelte +46 -0
  78. package/dist/components/shell/SettingsNav.svelte.d.ts +11 -0
  79. package/dist/components/shell/Sidebar.svelte +82 -0
  80. package/dist/components/shell/Sidebar.svelte.d.ts +25 -0
  81. package/dist/components/shell/Stat.svelte +63 -0
  82. package/dist/components/shell/Stat.svelte.d.ts +58 -0
  83. package/dist/components/shell/TopBar.svelte +37 -0
  84. package/dist/components/shell/TopBar.svelte.d.ts +11 -0
  85. package/dist/components/shell/WidgetRow.svelte +126 -0
  86. package/dist/components/shell/WidgetRow.svelte.d.ts +78 -0
  87. package/dist/components/shell/error-state-messages.d.ts +7 -0
  88. package/dist/components/shell/error-state-messages.js +9 -0
  89. package/dist/components/shell/index.d.ts +22 -0
  90. package/dist/components/shell/index.js +25 -0
  91. package/dist/components/shell/link-external.d.ts +2 -0
  92. package/dist/components/shell/link-external.js +7 -0
  93. package/dist/components/shell/messages.d.ts +7 -0
  94. package/dist/components/shell/messages.js +5 -0
  95. package/dist/components/shell/settings-nav-types.d.ts +12 -0
  96. package/dist/components/shell/settings-nav-types.js +3 -0
  97. package/dist/components/shell/shell-utils.d.ts +7 -0
  98. package/dist/components/shell/shell-utils.js +27 -0
  99. package/dist/components/shell/stat-tone.d.ts +3 -0
  100. package/dist/components/shell/stat-tone.js +11 -0
  101. package/dist/components/toast/ToasterModal.svelte +102 -168
  102. package/dist/components/toast/ToasterModal.svelte.d.ts +2 -12
  103. package/dist/components/ui/accordion/accordion-content.svelte +3 -2
  104. package/dist/components/ui/accordion/accordion-item.svelte +10 -1
  105. package/dist/components/ui/accordion/accordion-trigger.svelte +4 -3
  106. package/dist/components/ui/alert/alert-description.svelte +5 -1
  107. package/dist/components/ui/alert/alert-title.svelte +2 -1
  108. package/dist/components/ui/alert/index.d.ts +13 -11
  109. package/dist/components/ui/alert/index.js +4 -4
  110. package/dist/components/ui/avatar/avatar-utils.d.ts +2 -0
  111. package/dist/components/ui/avatar/avatar-utils.js +9 -0
  112. package/dist/components/ui/avatar/avatar.svelte +63 -0
  113. package/dist/components/ui/avatar/avatar.svelte.d.ts +80 -0
  114. package/dist/components/ui/avatar/index.d.ts +4 -0
  115. package/dist/components/ui/avatar/index.js +4 -0
  116. package/dist/components/ui/badge/badge.svelte +22 -10
  117. package/dist/components/ui/badge/badge.svelte.d.ts +14 -15
  118. package/dist/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +2 -2
  119. package/dist/components/ui/breadcrumb/breadcrumb-link.svelte +1 -1
  120. package/dist/components/ui/breadcrumb/breadcrumb-page.svelte +1 -1
  121. package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte +2 -2
  122. package/dist/components/ui/button/button-padding.d.ts +9 -0
  123. package/dist/components/ui/button/button-padding.js +15 -0
  124. package/dist/components/ui/button/button.svelte +81 -31
  125. package/dist/components/ui/button/button.svelte.d.ts +48 -29
  126. package/dist/components/ui/calendar/calendar-cell.svelte +1 -1
  127. package/dist/components/ui/calendar/calendar-head-cell.svelte +1 -1
  128. package/dist/components/ui/calendar/calendar-next-button.svelte +2 -2
  129. package/dist/components/ui/calendar/calendar-prev-button.svelte +2 -2
  130. package/dist/components/ui/card/card-description.svelte +1 -1
  131. package/dist/components/ui/card/card-title.svelte +1 -1
  132. package/dist/components/ui/card/card.svelte +1 -1
  133. package/dist/components/ui/checkbox/checkbox.svelte +9 -5
  134. package/dist/components/ui/chip/chip.svelte +48 -0
  135. package/dist/components/ui/chip/chip.svelte.d.ts +13 -0
  136. package/dist/components/ui/chip/index.d.ts +2 -0
  137. package/dist/components/ui/chip/index.js +2 -0
  138. package/dist/components/ui/command/command-dialog.svelte +1 -1
  139. package/dist/components/ui/command/command-input.svelte +4 -4
  140. package/dist/components/ui/command/command-item.svelte +1 -1
  141. package/dist/components/ui/command/command.svelte +1 -1
  142. package/dist/components/ui/dialog/dialog-content.svelte +4 -4
  143. package/dist/components/ui/dialog/dialog-description.svelte +1 -1
  144. package/dist/components/ui/dialog/dialog-overlay.svelte +1 -1
  145. package/dist/components/ui/dialog/dialog-title.svelte +1 -1
  146. package/dist/components/ui/drawer/drawer-content.svelte +1 -1
  147. package/dist/components/ui/drawer/drawer-overlay.svelte +1 -1
  148. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +5 -5
  149. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +1 -1
  150. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +1 -1
  151. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +20 -2
  152. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +4 -0
  153. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +5 -1
  154. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +3 -3
  155. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +2 -1
  156. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  157. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +3 -3
  158. package/dist/components/ui/field/field-ids.d.ts +7 -0
  159. package/dist/components/ui/field/field-ids.js +15 -0
  160. package/dist/components/ui/field/field.svelte +62 -0
  161. package/dist/components/ui/field/field.svelte.d.ts +21 -0
  162. package/dist/components/ui/field/index.d.ts +3 -0
  163. package/dist/components/ui/field/index.js +3 -0
  164. package/dist/components/ui/hover-card/hover-card-content.svelte +1 -1
  165. package/dist/components/ui/icon-button/icon-button.svelte +72 -0
  166. package/dist/components/ui/icon-button/icon-button.svelte.d.ts +90 -0
  167. package/dist/components/ui/icon-button/index.d.ts +2 -0
  168. package/dist/components/ui/icon-button/index.js +4 -0
  169. package/dist/components/ui/input/index.d.ts +1 -0
  170. package/dist/components/ui/input/input.svelte +11 -4
  171. package/dist/components/ui/input/input.svelte.d.ts +4 -1
  172. package/dist/components/ui/input-otp/input-otp-separator.svelte +2 -2
  173. package/dist/components/ui/input-otp/input-otp-slot.svelte +5 -4
  174. package/dist/components/ui/input-otp/input-otp-slot.svelte.d.ts +1 -1
  175. package/dist/components/ui/input-otp/input-otp.svelte +1 -1
  176. package/dist/components/ui/label/label.svelte +3 -2
  177. package/dist/components/ui/popover/popover-content.svelte +1 -1
  178. package/dist/components/ui/progress/progress.svelte +19 -5
  179. package/dist/components/ui/progress/progress.svelte.d.ts +4 -2
  180. package/dist/components/ui/radio-group/radio-group-item.svelte +4 -4
  181. package/dist/components/ui/range-calendar/range-calendar-head-cell.svelte +1 -1
  182. package/dist/components/ui/range-calendar/range-calendar-next-button.svelte +2 -2
  183. package/dist/components/ui/range-calendar/range-calendar-prev-button.svelte +2 -2
  184. package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +4 -1
  185. package/dist/components/ui/scroll-area/scroll-area.svelte +1 -1
  186. package/dist/components/ui/select/select-content.svelte +1 -3
  187. package/dist/components/ui/select/select-item.svelte +5 -4
  188. package/dist/components/ui/select/select-scroll-down-button.svelte +2 -2
  189. package/dist/components/ui/select/select-scroll-up-button.svelte +2 -2
  190. package/dist/components/ui/select/select-trigger.svelte +4 -3
  191. package/dist/components/ui/skeleton/index.d.ts +2 -0
  192. package/dist/components/ui/skeleton/index.js +2 -0
  193. package/dist/components/ui/skeleton/skeleton.svelte +24 -0
  194. package/dist/components/ui/skeleton/skeleton.svelte.d.ts +8 -0
  195. package/dist/components/ui/slider/slider.svelte +5 -10
  196. package/dist/components/ui/sonner/sonner.svelte +19 -13
  197. package/dist/components/ui/stepper-button/index.d.ts +3 -0
  198. package/dist/components/ui/stepper-button/index.js +2 -0
  199. package/dist/components/ui/stepper-button/stepper-button.svelte +37 -0
  200. package/dist/components/ui/stepper-button/stepper-button.svelte.d.ts +9 -0
  201. package/dist/components/ui/switch/switch.svelte +8 -3
  202. package/dist/components/ui/table/table-cell.svelte +1 -1
  203. package/dist/components/ui/table/table-head.svelte +1 -1
  204. package/dist/components/ui/table/table-row.svelte +1 -1
  205. package/dist/components/ui/tabs/tabs-list.svelte +1 -1
  206. package/dist/components/ui/tabs/tabs-trigger.svelte +1 -1
  207. package/dist/components/ui/tag/index.d.ts +2 -0
  208. package/dist/components/ui/tag/index.js +2 -0
  209. package/dist/components/ui/tag/tag.svelte +42 -0
  210. package/dist/components/ui/tag/tag.svelte.d.ts +11 -0
  211. package/dist/components/ui/textarea/textarea.svelte +4 -3
  212. package/dist/components/ui/textarea/textarea.svelte.d.ts +2 -2
  213. package/dist/components/ui/toggle/toggle.svelte +9 -9
  214. package/dist/components/ui/toggle/toggle.svelte.d.ts +14 -21
  215. package/dist/components/ui/tooltip/tooltip-content.svelte +1 -1
  216. package/dist/fonts/Inter/Inter-Black.woff2 +0 -0
  217. package/dist/fonts/Inter/Inter-BlackItalic.woff2 +0 -0
  218. package/dist/fonts/Inter/Inter-Bold.woff2 +0 -0
  219. package/dist/fonts/Inter/Inter-BoldItalic.woff2 +0 -0
  220. package/dist/fonts/Inter/Inter-ExtraBold.woff2 +0 -0
  221. package/dist/fonts/Inter/Inter-ExtraBoldItalic.woff2 +0 -0
  222. package/dist/fonts/Inter/Inter-ExtraLight-BETA.woff2 +0 -0
  223. package/dist/fonts/Inter/Inter-ExtraLightItalic-BETA.woff2 +0 -0
  224. package/dist/fonts/Inter/Inter-Italic.woff2 +0 -0
  225. package/dist/fonts/Inter/Inter-Light-BETA.woff2 +0 -0
  226. package/dist/fonts/Inter/Inter-LightItalic-BETA.woff2 +0 -0
  227. package/dist/fonts/Inter/Inter-Medium.woff2 +0 -0
  228. package/dist/fonts/Inter/Inter-MediumItalic.woff2 +0 -0
  229. package/dist/fonts/Inter/Inter-Regular.woff2 +0 -0
  230. package/dist/fonts/Inter/Inter-SemiBold.woff2 +0 -0
  231. package/dist/fonts/Inter/Inter-SemiBoldItalic.woff2 +0 -0
  232. package/dist/fonts/Inter/Inter-Thin-BETA.woff2 +0 -0
  233. package/dist/fonts/Inter/Inter-ThinItalic-BETA.woff2 +0 -0
  234. package/dist/fonts/Inter/Inter-italic.var.woff2 +0 -0
  235. package/dist/fonts/Inter/Inter-upright.var.woff2 +0 -0
  236. package/dist/fonts/Inter/Inter.var.woff2 +0 -0
  237. package/dist/fonts/JetBrainsMono/JetBrainsMono-Regular.woff2 +0 -0
  238. package/dist/i18n/audit/designSystemWords.d.ts +1 -1
  239. package/dist/i18n/audit/designSystemWords.js +1 -1
  240. package/dist/styles/fonts.css +18 -14
  241. package/dist/styles/global.css +7 -19
  242. package/dist/styles/tokens.css +332 -0
  243. package/dist/utils.d.ts +27 -0
  244. package/dist/utils.js +33 -2
  245. package/package.json +2 -1
  246. package/tailwind.config.ts +7 -47
@@ -0,0 +1,63 @@
1
+ <!--
2
+ Figma: Link (component set 232:35, page Auth)
3
+ -->
4
+ <script lang="ts" module>
5
+ import type { WithElementRef } from 'bits-ui';
6
+ import type { HTMLAnchorAttributes } from 'svelte/elements';
7
+ import type { VariantProps } from 'tailwind-variants';
8
+
9
+ export const linkVariants = tv({
10
+ base: 'inline-flex items-center gap-1 text-primary transition-colors duration-fast focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background hover:text-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:stroke-[1.333]',
11
+ variants: {
12
+ size: {
13
+ default: 'text-body-medium',
14
+ small: 'text-caption-medium'
15
+ }
16
+ },
17
+ defaultVariants: {
18
+ size: 'default'
19
+ }
20
+ });
21
+
22
+ export type LinkSize = VariantProps<typeof linkVariants>['size'];
23
+
24
+ export type LinkProps = WithElementRef<HTMLAnchorAttributes> & {
25
+ ref?: HTMLAnchorElement | null;
26
+ class?: string;
27
+ href: string;
28
+ label: string;
29
+ size?: LinkSize;
30
+ external?: boolean;
31
+ };
32
+ </script>
33
+
34
+ <script lang="ts">
35
+ import IconExternalLink from '@tabler/icons-svelte/icons/external-link';
36
+ import { cn, tv } from '../../utils.js';
37
+ import { externalLinkAttributes } from './link-external.js';
38
+
39
+ let {
40
+ class: className,
41
+ ref = $bindable(null),
42
+ href,
43
+ label,
44
+ size = 'default',
45
+ external = false,
46
+ ...restProps
47
+ }: LinkProps = $props();
48
+
49
+ const externalAttrs = $derived(external ? externalLinkAttributes() : {});
50
+ </script>
51
+
52
+ <a
53
+ bind:this={ref}
54
+ {href}
55
+ class={cn(linkVariants({ size }), className)}
56
+ {...externalAttrs}
57
+ {...restProps}
58
+ >
59
+ <span>{label}</span>
60
+ {#if external}
61
+ <IconExternalLink aria-hidden="true" />
62
+ {/if}
63
+ </a>
@@ -0,0 +1,53 @@
1
+ import type { WithElementRef } from 'bits-ui';
2
+ import type { HTMLAnchorAttributes } from 'svelte/elements';
3
+ import type { VariantProps } from 'tailwind-variants';
4
+ export declare const linkVariants: import("tailwind-variants").TVReturnType<{
5
+ size: {
6
+ default: string;
7
+ small: string;
8
+ };
9
+ }, undefined, "inline-flex items-center gap-1 text-primary transition-colors duration-fast focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background hover:text-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:stroke-[1.333]", {
10
+ responsiveVariants?: boolean | (string | number | symbol)[] | {
11
+ size?: boolean | (string | number | symbol)[] | undefined;
12
+ } | undefined;
13
+ } & import("tailwind-variants/dist/config.js").TWMConfig & {
14
+ twMergeConfig: {
15
+ classGroups: {
16
+ "font-size": {
17
+ text: ("display-hero" | "heading-page" | "heading-section" | "body" | "body-medium" | "body-large" | "caption" | "caption-medium" | "label" | "label-small" | "code")[];
18
+ }[];
19
+ };
20
+ };
21
+ }, {
22
+ size: {
23
+ default: string;
24
+ small: string;
25
+ };
26
+ }, undefined, import("tailwind-variants").TVReturnType<{
27
+ size: {
28
+ default: string;
29
+ small: string;
30
+ };
31
+ }, undefined, "inline-flex items-center gap-1 text-primary transition-colors duration-fast focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background hover:text-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:stroke-[1.333]", import("tailwind-variants/dist/config.js").TVConfig<{
32
+ size: {
33
+ default: string;
34
+ small: string;
35
+ };
36
+ }, {
37
+ size: {
38
+ default: string;
39
+ small: string;
40
+ };
41
+ }>, unknown, unknown, undefined>>;
42
+ export type LinkSize = VariantProps<typeof linkVariants>['size'];
43
+ export type LinkProps = WithElementRef<HTMLAnchorAttributes> & {
44
+ ref?: HTMLAnchorElement | null;
45
+ class?: string;
46
+ href: string;
47
+ label: string;
48
+ size?: LinkSize;
49
+ external?: boolean;
50
+ };
51
+ declare const Link: import("svelte").Component<LinkProps, {}, "ref">;
52
+ type Link = ReturnType<typeof Link>;
53
+ export default Link;
@@ -0,0 +1,117 @@
1
+ <!-- Figma: Responsive app shell — mobile/tablet nav drawer (ledger decisions.appShell). -->
2
+ <script lang="ts">
3
+ import { tick } from 'svelte';
4
+ import type { Snippet } from 'svelte';
5
+ import { cn } from '../../utils.js';
6
+ import {
7
+ getFocusableElements,
8
+ navDrawerEffectiveTransitionMs,
9
+ navDrawerTabTarget,
10
+ navDrawerTransitionEasing
11
+ } from './shell-utils.js';
12
+
13
+ let {
14
+ open = $bindable(false),
15
+ class: className,
16
+ onClose,
17
+ children
18
+ }: {
19
+ open?: boolean;
20
+ class?: string;
21
+ onClose?: () => void;
22
+ children?: Snippet;
23
+ } = $props();
24
+
25
+ let mounted = $state(false);
26
+ let visible = $state(false);
27
+ let panelRef = $state<HTMLElement | null>(null);
28
+ let reducedMotion = $state(false);
29
+
30
+ $effect(() => {
31
+ if (typeof window === 'undefined') return;
32
+ const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
33
+ const sync = () => {
34
+ reducedMotion = mq.matches;
35
+ };
36
+ sync();
37
+ mq.addEventListener('change', sync);
38
+ return () => mq.removeEventListener('change', sync);
39
+ });
40
+
41
+ const transitionMs = $derived(navDrawerEffectiveTransitionMs(visible, reducedMotion));
42
+ const transitionEase = $derived(navDrawerTransitionEasing(visible));
43
+
44
+ $effect(() => {
45
+ if (open) {
46
+ mounted = true;
47
+ void tick().then(() => {
48
+ visible = true;
49
+ void tick().then(() => {
50
+ if (!panelRef) return;
51
+ const first = getFocusableElements(panelRef)[0];
52
+ first?.focus();
53
+ });
54
+ });
55
+ return;
56
+ }
57
+ visible = false;
58
+ const closeMs = navDrawerEffectiveTransitionMs(false, reducedMotion);
59
+ const timer = window.setTimeout(() => {
60
+ mounted = false;
61
+ }, closeMs);
62
+ return () => window.clearTimeout(timer);
63
+ });
64
+
65
+ function close() {
66
+ open = false;
67
+ onClose?.();
68
+ }
69
+
70
+ function handleKeydown(e: KeyboardEvent) {
71
+ if (!open || !mounted) return;
72
+ if (e.key === 'Escape') {
73
+ e.preventDefault();
74
+ close();
75
+ return;
76
+ }
77
+ if (e.key !== 'Tab' || !panelRef) return;
78
+ const active = document.activeElement;
79
+ if (!(active instanceof HTMLElement) || !panelRef.contains(active)) return;
80
+ const next = navDrawerTabTarget(panelRef, active, e.shiftKey);
81
+ if (!next) return;
82
+ e.preventDefault();
83
+ next.focus();
84
+ }
85
+ </script>
86
+
87
+ <svelte:window onkeydown={handleKeydown} />
88
+
89
+ {#if mounted}
90
+ <div class="fixed inset-0 z-40 lg:hidden" role="presentation">
91
+ <button
92
+ type="button"
93
+ class={cn(
94
+ 'bg-foreground/50 absolute inset-0 motion-reduce:transition-none',
95
+ visible ? 'opacity-100' : 'opacity-0'
96
+ )}
97
+ style="transition: opacity {transitionMs}ms {transitionEase};"
98
+ aria-label="Close navigation"
99
+ tabindex={visible ? 0 : -1}
100
+ onclick={close}
101
+ ></button>
102
+ <div
103
+ bind:this={panelRef}
104
+ class={cn(
105
+ 'w-sidebar border-border bg-sidebar absolute inset-y-0 start-0 z-50 flex flex-col border-e shadow-none motion-reduce:transition-none',
106
+ visible ? 'translate-x-0' : '-translate-x-full rtl:translate-x-full',
107
+ className
108
+ )}
109
+ style="transition: transform {transitionMs}ms {transitionEase};"
110
+ role="dialog"
111
+ aria-modal="true"
112
+ aria-label="Navigation"
113
+ >
114
+ {@render children?.()}
115
+ </div>
116
+ </div>
117
+ {/if}
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ open?: boolean;
4
+ class?: string;
5
+ onClose?: () => void;
6
+ children?: Snippet;
7
+ };
8
+ declare const NavDrawer: import("svelte").Component<$$ComponentProps, {}, "open">;
9
+ type NavDrawer = ReturnType<typeof NavDrawer>;
10
+ export default NavDrawer;
@@ -0,0 +1,128 @@
1
+ <!-- Figma: Nav Row (component set 39:3, node 39:3). -->
2
+ <script lang="ts" module>
3
+ import type { WithElementRef } from 'bits-ui';
4
+ import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
5
+
6
+ export const navRowVariants = tv({
7
+ base: 'group/nav-row flex h-8 w-full min-w-0 items-center gap-2 rounded-lg py-1.5 ps-2 pe-2 text-start transition-colors duration-fast focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-sidebar-ring focus-visible:ring-offset-2 focus-visible:ring-offset-sidebar disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:stroke-[1.333]',
8
+ variants: {
9
+ active: {
10
+ true: 'bg-sidebar-accent text-sidebar-accent-foreground text-body-medium',
11
+ false: 'text-muted-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground'
12
+ }
13
+ },
14
+ defaultVariants: {
15
+ active: false
16
+ }
17
+ });
18
+
19
+ export type NavRowVisualState = 'default' | 'hover' | 'active' | 'focus' | 'disabled';
20
+
21
+ export type NavRowProps = WithElementRef<HTMLButtonAttributes> &
22
+ WithElementRef<HTMLAnchorAttributes> & {
23
+ ref?: HTMLAnchorElement | HTMLButtonElement | null;
24
+ class?: string;
25
+ label: string;
26
+ href?: string;
27
+ active?: boolean;
28
+ disabled?: boolean;
29
+ showIcon?: boolean;
30
+ showTrailing?: boolean;
31
+ trailing?: string;
32
+ /** Showcase-only forced visual state (CSS `:hover` / `:focus-visible` otherwise). */
33
+ visualState?: NavRowVisualState;
34
+ };
35
+ </script>
36
+
37
+ <script lang="ts">
38
+ import type { Icon } from '@tabler/icons-svelte';
39
+ import type { Snippet } from 'svelte';
40
+ import { cn, tv } from '../../utils.js';
41
+
42
+ let {
43
+ ref = $bindable(null),
44
+ class: className,
45
+ label,
46
+ href = undefined,
47
+ active = false,
48
+ disabled = false,
49
+ showIcon = true,
50
+ showTrailing = false,
51
+ trailing = '',
52
+ visualState = undefined,
53
+ icon,
54
+ iconComponent = undefined,
55
+ children,
56
+ ...restProps
57
+ }: NavRowProps & {
58
+ icon?: Snippet;
59
+ /** Tabler icon component (alternative to the `icon` snippet). */
60
+ iconComponent?: Icon;
61
+ children?: Snippet;
62
+ } = $props();
63
+
64
+ const hasIcon = $derived(showIcon && (Boolean(icon) || Boolean(iconComponent)));
65
+
66
+ const isActive = $derived(active || visualState === 'active');
67
+ const isDisabled = $derived(disabled || visualState === 'disabled');
68
+
69
+ const showcaseClass = $derived.by(() => {
70
+ if (!visualState || visualState === 'default' || visualState === 'active') return '';
71
+ if (visualState === 'hover') return 'bg-sidebar-accent text-sidebar-accent-foreground';
72
+ if (visualState === 'focus')
73
+ return 'ring-2 ring-sidebar-ring ring-offset-2 ring-offset-sidebar';
74
+ return '';
75
+ });
76
+ </script>
77
+
78
+ {#if href && !isDisabled}
79
+ <a
80
+ bind:this={ref}
81
+ {href}
82
+ class={cn(navRowVariants({ active: isActive }), showcaseClass, className)}
83
+ aria-current={isActive ? 'page' : undefined}
84
+ aria-disabled={isDisabled ? true : undefined}
85
+ {...restProps}
86
+ >
87
+ {#if hasIcon}
88
+ <span class="flex shrink-0 items-center justify-center text-current" aria-hidden="true">
89
+ {#if icon}
90
+ {@render icon()}
91
+ {:else if iconComponent}
92
+ {@const IconComp = iconComponent}
93
+ <IconComp />
94
+ {/if}
95
+ </span>
96
+ {/if}
97
+ <span class="min-w-0 flex-1 truncate">{label}</span>
98
+ {#if showTrailing && trailing}
99
+ <span class="text-caption text-muted-foreground shrink-0 tabular-nums">{trailing}</span>
100
+ {/if}
101
+ {@render children?.()}
102
+ </a>
103
+ {:else}
104
+ <button
105
+ bind:this={ref}
106
+ type="button"
107
+ class={cn(navRowVariants({ active: isActive }), showcaseClass, className)}
108
+ disabled={isDisabled}
109
+ aria-current={isActive ? 'page' : undefined}
110
+ {...restProps}
111
+ >
112
+ {#if hasIcon}
113
+ <span class="flex shrink-0 items-center justify-center text-current" aria-hidden="true">
114
+ {#if icon}
115
+ {@render icon()}
116
+ {:else if iconComponent}
117
+ {@const IconComp = iconComponent}
118
+ <IconComp />
119
+ {/if}
120
+ </span>
121
+ {/if}
122
+ <span class="min-w-0 flex-1 truncate">{label}</span>
123
+ {#if showTrailing && trailing}
124
+ <span class="text-caption text-muted-foreground shrink-0 tabular-nums">{trailing}</span>
125
+ {/if}
126
+ {@render children?.()}
127
+ </button>
128
+ {/if}
@@ -0,0 +1,65 @@
1
+ import type { WithElementRef } from 'bits-ui';
2
+ import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
3
+ export declare const navRowVariants: import("tailwind-variants").TVReturnType<{
4
+ active: {
5
+ true: string;
6
+ false: string;
7
+ };
8
+ }, undefined, "group/nav-row flex h-8 w-full min-w-0 items-center gap-2 rounded-lg py-1.5 ps-2 pe-2 text-start transition-colors duration-fast focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-sidebar-ring focus-visible:ring-offset-2 focus-visible:ring-offset-sidebar disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:stroke-[1.333]", {
9
+ responsiveVariants?: boolean | (string | number | symbol)[] | {
10
+ active?: boolean | (string | number | symbol)[] | undefined;
11
+ } | undefined;
12
+ } & import("tailwind-variants/dist/config.js").TWMConfig & {
13
+ twMergeConfig: {
14
+ classGroups: {
15
+ "font-size": {
16
+ text: ("display-hero" | "heading-page" | "heading-section" | "body" | "body-medium" | "body-large" | "caption" | "caption-medium" | "label" | "label-small" | "code")[];
17
+ }[];
18
+ };
19
+ };
20
+ }, {
21
+ active: {
22
+ true: string;
23
+ false: string;
24
+ };
25
+ }, undefined, import("tailwind-variants").TVReturnType<{
26
+ active: {
27
+ true: string;
28
+ false: string;
29
+ };
30
+ }, undefined, "group/nav-row flex h-8 w-full min-w-0 items-center gap-2 rounded-lg py-1.5 ps-2 pe-2 text-start transition-colors duration-fast focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-sidebar-ring focus-visible:ring-offset-2 focus-visible:ring-offset-sidebar disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:stroke-[1.333]", import("tailwind-variants/dist/config.js").TVConfig<{
31
+ active: {
32
+ true: string;
33
+ false: string;
34
+ };
35
+ }, {
36
+ active: {
37
+ true: string;
38
+ false: string;
39
+ };
40
+ }>, unknown, unknown, undefined>>;
41
+ export type NavRowVisualState = 'default' | 'hover' | 'active' | 'focus' | 'disabled';
42
+ export type NavRowProps = WithElementRef<HTMLButtonAttributes> & WithElementRef<HTMLAnchorAttributes> & {
43
+ ref?: HTMLAnchorElement | HTMLButtonElement | null;
44
+ class?: string;
45
+ label: string;
46
+ href?: string;
47
+ active?: boolean;
48
+ disabled?: boolean;
49
+ showIcon?: boolean;
50
+ showTrailing?: boolean;
51
+ trailing?: string;
52
+ /** Showcase-only forced visual state (CSS `:hover` / `:focus-visible` otherwise). */
53
+ visualState?: NavRowVisualState;
54
+ };
55
+ import type { Icon } from '@tabler/icons-svelte';
56
+ import type { Snippet } from 'svelte';
57
+ type $$ComponentProps = NavRowProps & {
58
+ icon?: Snippet;
59
+ /** Tabler icon component (alternative to the `icon` snippet). */
60
+ iconComponent?: Icon;
61
+ children?: Snippet;
62
+ };
63
+ declare const NavRow: import("svelte").Component<$$ComponentProps, {}, "ref">;
64
+ type NavRow = ReturnType<typeof NavRow>;
65
+ export default NavRow;
@@ -0,0 +1,27 @@
1
+ <!-- Figma: Nav Section Label (component set 39:29, node 39:29). -->
2
+ <script lang="ts">
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { cn } from '../../utils.js';
5
+
6
+ let {
7
+ class: className,
8
+ label,
9
+ showTrailing = false,
10
+ trailing = '',
11
+ ...restProps
12
+ }: HTMLAttributes<HTMLDivElement> & {
13
+ label: string;
14
+ showTrailing?: boolean;
15
+ trailing?: string;
16
+ } = $props();
17
+ </script>
18
+
19
+ <div
20
+ class={cn('flex h-8 w-full min-w-0 items-center gap-2 py-1 ps-3 pe-2 pb-1 text-start', className)}
21
+ {...restProps}
22
+ >
23
+ <span class="text-caption-medium text-muted-foreground min-w-0 flex-1 truncate">{label}</span>
24
+ {#if showTrailing && trailing}
25
+ <span class="text-caption text-muted-foreground shrink-0 tabular-nums">{trailing}</span>
26
+ {/if}
27
+ </div>
@@ -0,0 +1,9 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
3
+ label: string;
4
+ showTrailing?: boolean;
5
+ trailing?: string;
6
+ };
7
+ declare const NavSectionLabel: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type NavSectionLabel = ReturnType<typeof NavSectionLabel>;
9
+ export default NavSectionLabel;
@@ -0,0 +1,76 @@
1
+ <!--
2
+ Figma: Notification Row (component set 110:77, page Notification)
3
+ -->
4
+ <script lang="ts" module>
5
+ import type { WithElementRef } from 'bits-ui';
6
+ import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
7
+ import type { Snippet } from 'svelte';
8
+
9
+ export type NotificationRowProps = WithElementRef<HTMLButtonAttributes> &
10
+ WithElementRef<HTMLAnchorAttributes> & {
11
+ ref?: HTMLButtonElement | HTMLAnchorElement | null;
12
+ class?: string;
13
+ title: string;
14
+ message: string;
15
+ time: string;
16
+ unread?: boolean;
17
+ icon: Snippet;
18
+ href?: string;
19
+ };
20
+ </script>
21
+
22
+ <script lang="ts">
23
+ import { cn } from '../../utils.js';
24
+
25
+ let {
26
+ class: className,
27
+ ref = $bindable(null),
28
+ title,
29
+ message,
30
+ time,
31
+ unread = true,
32
+ icon,
33
+ href = undefined,
34
+ ...restProps
35
+ }: NotificationRowProps = $props();
36
+
37
+ const rowClass = $derived(
38
+ cn(
39
+ 'group flex w-full max-w-content items-center gap-4 rounded-xl px-4 py-3 text-start transition-colors duration-fast hover:bg-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background',
40
+ className
41
+ )
42
+ );
43
+
44
+ const titleClass = $derived(
45
+ unread ? 'text-body-medium text-foreground' : 'text-body text-foreground'
46
+ );
47
+ </script>
48
+
49
+ {#snippet rowInner()}
50
+ <span
51
+ class="bg-muted text-foreground duration-fast group-hover:bg-background flex size-10 shrink-0 items-center justify-center rounded-lg transition-colors"
52
+ >
53
+ {@render icon()}
54
+ </span>
55
+ <span class="min-w-0 flex-1">
56
+ <span class={cn('block truncate', titleClass)}>{title}</span>
57
+ <!-- A message of up to two lines, as in Figma: the one detail that matters is not cut to a single line -->
58
+ <span class="text-caption text-muted-foreground line-clamp-2">{message}</span>
59
+ </span>
60
+ <span class="flex shrink-0 items-center gap-2">
61
+ <span class="text-caption text-muted-foreground">{time}</span>
62
+ {#if unread}
63
+ <span class="bg-brand size-2 shrink-0 rounded-full" aria-hidden="true"></span>
64
+ {/if}
65
+ </span>
66
+ {/snippet}
67
+
68
+ {#if href}
69
+ <a bind:this={ref} {href} class={rowClass} {...restProps as HTMLAnchorAttributes}>
70
+ {@render rowInner()}
71
+ </a>
72
+ {:else}
73
+ <button bind:this={ref} type="button" class={rowClass} {...restProps as HTMLButtonAttributes}>
74
+ {@render rowInner()}
75
+ </button>
76
+ {/if}
@@ -0,0 +1,16 @@
1
+ import type { WithElementRef } from 'bits-ui';
2
+ import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
3
+ import type { Snippet } from 'svelte';
4
+ export type NotificationRowProps = WithElementRef<HTMLButtonAttributes> & WithElementRef<HTMLAnchorAttributes> & {
5
+ ref?: HTMLButtonElement | HTMLAnchorElement | null;
6
+ class?: string;
7
+ title: string;
8
+ message: string;
9
+ time: string;
10
+ unread?: boolean;
11
+ icon: Snippet;
12
+ href?: string;
13
+ };
14
+ declare const NotificationRow: import("svelte").Component<NotificationRowProps, {}, "ref">;
15
+ type NotificationRow = ReturnType<typeof NotificationRow>;
16
+ export default NotificationRow;
@@ -0,0 +1,42 @@
1
+ <!-- Figma: Page Header (component set 54:107, node 54:107). -->
2
+ <script lang="ts">
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import type { Snippet } from 'svelte';
5
+ import { cn } from '../../utils.js';
6
+
7
+ let {
8
+ class: className,
9
+ title,
10
+ description = undefined,
11
+ showDescription = false,
12
+ /** When true, hides below the 1024px desktop breakpoint (title moves to Top Bar). */
13
+ hideBelowDesktop = true,
14
+ actions,
15
+ ...restProps
16
+ }: HTMLAttributes<HTMLElement> & {
17
+ title: string;
18
+ description?: string;
19
+ showDescription?: boolean;
20
+ hideBelowDesktop?: boolean;
21
+ actions?: Snippet;
22
+ } = $props();
23
+ </script>
24
+
25
+ <header
26
+ class={cn(
27
+ 'flex w-full flex-wrap items-center justify-between gap-4 ps-8 pe-8 pt-6 pb-4',
28
+ hideBelowDesktop && 'max-lg:hidden',
29
+ className
30
+ )}
31
+ {...restProps}
32
+ >
33
+ <div class="flex min-w-0 flex-col gap-0.5">
34
+ <h1 class="text-heading-page text-foreground truncate">{title}</h1>
35
+ {#if showDescription && description}
36
+ <p class="text-body text-muted-foreground">{description}</p>
37
+ {/if}
38
+ </div>
39
+ {#if actions}
40
+ <div class="flex shrink-0 flex-wrap items-center gap-2">{@render actions()}</div>
41
+ {/if}
42
+ </header>
@@ -0,0 +1,12 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { Snippet } from 'svelte';
3
+ type $$ComponentProps = HTMLAttributes<HTMLElement> & {
4
+ title: string;
5
+ description?: string;
6
+ showDescription?: boolean;
7
+ hideBelowDesktop?: boolean;
8
+ actions?: Snippet;
9
+ };
10
+ declare const PageHeader: import("svelte").Component<$$ComponentProps, {}, "">;
11
+ type PageHeader = ReturnType<typeof PageHeader>;
12
+ export default PageHeader;