svelora 3.0.7 → 3.0.10

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 (36) hide show
  1. package/dist/Chart/Chart.svelte +45 -44
  2. package/dist/Chart/chart.types.d.ts +9 -13
  3. package/dist/Chart/index.d.ts +1 -3
  4. package/dist/Chart/index.js +1 -3
  5. package/dist/NavigationMenu/NavigationMenu.svelte +255 -0
  6. package/dist/NavigationMenu/NavigationMenu.svelte.d.ts +4 -0
  7. package/dist/NavigationMenu/index.d.ts +3 -0
  8. package/dist/NavigationMenu/index.js +3 -0
  9. package/dist/NavigationMenu/navigation-menu.types.d.ts +104 -0
  10. package/dist/NavigationMenu/navigation-menu.variants.d.ts +142 -0
  11. package/dist/NavigationMenu/navigation-menu.variants.js +71 -0
  12. package/dist/Search/Search.svelte +94 -0
  13. package/dist/Search/Search.svelte.d.ts +4 -0
  14. package/dist/Search/index.d.ts +2 -0
  15. package/dist/Search/index.js +1 -0
  16. package/dist/Search/search.types.d.ts +40 -0
  17. package/dist/Search/search.types.js +1 -0
  18. package/dist/Sidebar/Sidebar.svelte +5 -5
  19. package/dist/Sidebar/sidebar.types.d.ts +10 -4
  20. package/dist/Sidebar/sidebar.variants.d.ts +18 -0
  21. package/dist/Sidebar/sidebar.variants.js +16 -6
  22. package/dist/docs/navigation.js +20 -9
  23. package/dist/index.d.ts +2 -3
  24. package/dist/index.js +2 -2
  25. package/dist/mcp/svelora-docs.data.json +11 -9
  26. package/package.json +4 -5
  27. package/dist/Chart/chart.variants.d.ts +0 -3
  28. package/dist/Chart/chart.variants.js +0 -4
  29. package/dist/Menu/Menu.svelte +0 -134
  30. package/dist/Menu/Menu.svelte.d.ts +0 -4
  31. package/dist/Menu/index.d.ts +0 -4
  32. package/dist/Menu/index.js +0 -4
  33. package/dist/Menu/menu.types.d.ts +0 -82
  34. package/dist/Menu/menu.variants.d.ts +0 -46
  35. package/dist/Menu/menu.variants.js +0 -32
  36. /package/dist/{Menu/menu.types.js → NavigationMenu/navigation-menu.types.js} +0 -0
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "version": 1,
3
3
  "packageName": "svelora",
4
- "packageVersion": "3.0.7",
5
- "generatedAt": "2026-06-25T15:23:58.309Z",
4
+ "packageVersion": "3.0.10",
5
+ "generatedAt": "2026-06-26T11:53:53.695Z",
6
6
  "slugs": {
7
7
  "components": [
8
8
  "button",
@@ -18,7 +18,10 @@
18
18
  "card",
19
19
  "container",
20
20
  "resizable",
21
+ "modal",
22
+ "navigation-menu",
21
23
  "scroll-area",
24
+ "search",
22
25
  "separator",
23
26
  "accordion",
24
27
  "chart",
@@ -63,14 +66,12 @@
63
66
  "spotlight",
64
67
  "breadcrumb",
65
68
  "pagination",
66
- "menu",
67
69
  "sidebar",
68
70
  "stepper",
69
71
  "tabs",
70
72
  "collapsible",
71
73
  "command",
72
74
  "context-menu",
73
- "modal",
74
75
  "drawer",
75
76
  "dropdown-menu",
76
77
  "popover",
@@ -108,15 +109,18 @@
108
109
  "link": "<script lang=\"ts\">\n import { Link, Icon } from '$lib/index.js'\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Link</h1>\n <p class=\"text-on-surface-variant\">\n Use the Link component to create hyperlinks with automatic active state detection.\n Renders as an anchor tag when <code class=\"rounded bg-surface-container-highest px-1\"\n >href</code\n >\n is provided, otherwise renders as a button.\n </p>\n </div>\n\n <!-- Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Usage</h2>\n <p class=\"text-sm text-on-surface-variant\">\n The Link component is styled by default with <code\n class=\"rounded bg-surface-container-highest px-1\">text-on-surface-variant</code\n >\n when inactive and\n <code class=\"rounded bg-surface-container-highest px-1\">text-primary</code>\n when active, with a\n <code class=\"rounded bg-surface-container-highest px-1\">hover:text-on-surface</code> transition.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/link\">Link</Link>\n </div>\n </section>\n\n <!-- InactiveClass -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">InactiveClass</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">inactiveClass</code> prop\n to apply additional classes when the link is inactive.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/non-existent\" inactiveClass=\"opacity-50\">Dimmed when inactive</Link>\n <Link href=\"/non-existent\" inactiveClass=\"italic\">Italic when inactive</Link>\n </div>\n </section>\n\n <!-- ActiveClass -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">ActiveClass</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">activeClass</code> prop to\n apply additional classes when the link is active.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/link\" activeClass=\"font-bold\">Bold when active</Link>\n <Link href=\"/link\" activeClass=\"underline underline-offset-4\"\n >Underlined when active</Link\n >\n <Link href=\"/link\" activeClass=\"font-bold underline underline-offset-4\"\n >Bold + underline</Link\n >\n </div>\n </section>\n\n <!-- Active -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Active</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">active</code> prop to force\n the active state, overriding auto-detection from the current route.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/link\" active={true}>Active (forced)</Link>\n <Link href=\"/link\" active={false}>Inactive (forced)</Link>\n <Link href=\"/link\">Auto-detected</Link>\n </div>\n </section>\n\n <!-- Matching Modes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Matching Modes</h2>\n <p class=\"text-sm text-on-surface-variant\">\n By default, a link is active when the current URL starts with the <code\n class=\"rounded bg-surface-container-highest px-1\">href</code\n >. Use <code class=\"rounded bg-surface-container-highest px-1\">exact</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">exactQuery</code>, and\n <code class=\"rounded bg-surface-container-highest px-1\">exactHash</code> to control this behavior.\n </p>\n <div class=\"overflow-x-auto\">\n <table class=\"w-full text-sm\">\n <thead>\n <tr class=\"border-b border-outline-variant\">\n <th class=\"px-3 py-2 text-left font-medium text-on-surface-variant\">Prop</th\n >\n <th class=\"px-3 py-2 text-left font-medium text-on-surface-variant\">Href</th\n >\n <th class=\"px-3 py-2 text-left font-medium text-on-surface-variant\"\n >Preview</th\n >\n <th class=\"px-3 py-2 text-left font-medium text-on-surface-variant\"\n >Description</th\n >\n </tr>\n </thead>\n <tbody>\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-2 font-mono text-xs text-on-surface-variant\">default</td>\n <td class=\"px-3 py-2 font-mono text-xs\">/link</td>\n <td class=\"px-3 py-2\">\n <Link href=\"/link\" activeClass=\"font-semibold\">Link</Link>\n </td>\n <td class=\"px-3 py-2 text-on-surface-variant\"\n >Prefix match — active if URL starts with href</td\n >\n </tr>\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-2 font-mono text-xs text-on-surface-variant\">exact</td>\n <td class=\"px-3 py-2 font-mono text-xs\">/link</td>\n <td class=\"px-3 py-2\">\n <Link href=\"/link\" exact activeClass=\"font-semibold\">Link (exact)</Link>\n </td>\n <td class=\"px-3 py-2 text-on-surface-variant\"\n >Only active when pathname is exactly \"/link\"</td\n >\n </tr>\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-2 font-mono text-xs text-on-surface-variant\"\n >exactHash</td\n >\n <td class=\"px-3 py-2 font-mono text-xs\">/link#section</td>\n <td class=\"px-3 py-2\">\n <Link href=\"/link#section\" exactHash activeClass=\"font-semibold\"\n >#section</Link\n >\n </td>\n <td class=\"px-3 py-2 text-on-surface-variant\"\n >Hash must also match for active state</td\n >\n </tr>\n <tr>\n <td class=\"px-3 py-2 font-mono text-xs text-on-surface-variant\"\n >exactQuery</td\n >\n <td class=\"px-3 py-2 font-mono text-xs\">/link?tab=1</td>\n <td class=\"px-3 py-2\">\n <Link href=\"/link?tab=1\" exactQuery activeClass=\"font-semibold\"\n >?tab=1</Link\n >\n </td>\n <td class=\"px-3 py-2 text-on-surface-variant\"\n >Query params must exactly match</td\n >\n </tr>\n </tbody>\n </table>\n </div>\n </section>\n\n <!-- disabled -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Disabled</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">disabled</code> prop to\n disable the link. On anchors, it removes\n <code class=\"rounded bg-surface-container-highest px-1\">href</code>, sets\n <code class=\"rounded bg-surface-container-highest px-1\">aria-disabled</code>\n and\n <code class=\"rounded bg-surface-container-highest px-1\">role=\"link\"</code>. On buttons,\n it uses the native disabled attribute.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/link\" disabled>Disabled anchor</Link>\n <Link disabled>Disabled button</Link>\n </div>\n </section>\n\n <!-- Raw -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Raw</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">raw</code> prop to strip\n all default styling. Only\n <code class=\"rounded bg-surface-container-highest px-1\">class</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">activeClass</code>, and\n <code class=\"rounded bg-surface-container-highest px-1\">inactiveClass</code> are applied.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link\n href=\"/link\"\n raw\n class=\"text-on-surface underline decoration-primary underline-offset-4 hover:decoration-2\"\n >\n Custom styled\n </Link>\n <Link\n href=\"/link\"\n raw\n class=\"rounded-md bg-primary-container px-3 py-1 text-on-primary-container hover:bg-primary-container/80\"\n >\n Chip style\n </Link>\n <Link\n href=\"/link\"\n raw\n active={true}\n activeClass=\"bg-primary text-on-primary\"\n inactiveClass=\"bg-surface-container-highest text-on-surface-variant hover:bg-surface-container-high\"\n class=\"rounded-full px-4 py-1.5 text-sm font-medium transition-colors\"\n >\n Pill style\n </Link>\n </div>\n </section>\n\n <!-- External -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">External</h2>\n <p class=\"text-sm text-on-surface-variant\">\n External URLs (<code class=\"rounded bg-surface-container-highest px-1\">http://</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">https://</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">//</code>) are auto-detected.\n The component adds\n <code class=\"rounded bg-surface-container-highest px-1\">target=\"_blank\"</code> and\n <code class=\"rounded bg-surface-container-highest px-1\">rel=\"noopener noreferrer\"</code>\n automatically. Use the\n <code class=\"rounded bg-surface-container-highest px-1\">external</code> prop to force this\n behavior on internal paths.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"https://svelte.dev\">\n <Icon name=\"lucide:external-link\" size=\"14\" class=\"mr-1\" />\n Svelte (auto)\n </Link>\n <Link href=\"https://tailwindcss.com\">\n <Icon name=\"lucide:external-link\" size=\"14\" class=\"mr-1\" />\n Tailwind CSS (auto)\n </Link>\n <Link href=\"/api/docs\" external>\n <Icon name=\"lucide:external-link\" size=\"14\" class=\"mr-1\" />\n API Docs (forced)\n </Link>\n </div>\n </section>\n\n <!-- Prefetch -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Prefetch</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Since the Link component extends native HTML anchor attributes, you can use SvelteKit's\n <code class=\"rounded bg-surface-container-highest px-1\"\n >data-sveltekit-preload-data</code\n >\n and\n <code class=\"rounded bg-surface-container-highest px-1\"\n >data-sveltekit-preload-code</code\n >\n attributes to control prefetching behavior.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/link\" data-sveltekit-preload-data=\"hover\">Preload on hover</Link>\n <Link href=\"/link\" data-sveltekit-preload-data=\"tap\">Preload on tap</Link>\n <Link href=\"/link\" data-sveltekit-preload-data=\"off\">No preload</Link>\n <Link href=\"/link\" data-sveltekit-preload-code=\"eager\">Preload code eagerly</Link>\n </div>\n </section>\n\n <!-- As Button -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">As Button</h2>\n <p class=\"text-sm text-on-surface-variant\">\n When no <code class=\"rounded bg-surface-container-highest px-1\">href</code> is provided,\n the component renders a button element with\n <code class=\"rounded bg-surface-container-highest px-1\">type=\"button\"</code> by default.\n Use the <code class=\"rounded bg-surface-container-highest px-1\">type</code> prop to change\n the button type.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link onclick={() => alert('Clicked!')}>Click action</Link>\n <Link type=\"submit\">Submit type</Link>\n <Link type=\"reset\">Reset type</Link>\n </div>\n </section>\n\n <!-- UI Slot Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">ui</code> prop to override\n styles on specific slots.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/link\" ui={{ base: 'underline underline-offset-4 decoration-2' }}>\n Underlined\n </Link>\n <Link href=\"/link\" ui={{ base: 'font-bold text-lg' }}>Bold & Large</Link>\n <Link href=\"/link\" ui={{ base: 'uppercase tracking-wider text-xs font-semibold' }}>\n Uppercase\n </Link>\n </div>\n </section>\n\n <!-- States Overview -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">States</h2>\n <div class=\"overflow-x-auto\">\n <table class=\"w-full\">\n <thead>\n <tr class=\"border-b border-outline-variant\">\n <th class=\"px-3 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >State</th\n >\n <th class=\"px-3 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >&lt;a&gt;</th\n >\n <th class=\"px-3 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >&lt;button&gt;</th\n >\n </tr>\n </thead>\n <tbody>\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-3 text-sm font-medium text-on-surface-variant\"\n >Default</td\n >\n <td class=\"px-3 py-3\">\n <Link href=\"/demo\">Link text</Link>\n </td>\n <td class=\"px-3 py-3\">\n <Link>Button text</Link>\n </td>\n </tr>\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-3 text-sm font-medium text-on-surface-variant\">Active</td\n >\n <td class=\"px-3 py-3\">\n <Link href=\"/link\" active={true}>Link text</Link>\n </td>\n <td class=\"px-3 py-3\">\n <Link active={true}>Button text</Link>\n </td>\n </tr>\n <tr>\n <td class=\"px-3 py-3 text-sm font-medium text-on-surface-variant\"\n >Disabled</td\n >\n <td class=\"px-3 py-3\">\n <Link href=\"/link\" disabled>Link text</Link>\n </td>\n <td class=\"px-3 py-3\">\n <Link disabled>Button text</Link>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </section>\n\n <!-- Examples -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Examples</h2>\n\n <!-- Navigation Bar -->\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Navigation bar</p>\n <nav class=\"flex items-center gap-6\">\n <Link href=\"/\" exact activeClass=\"font-semibold\">Home</Link>\n <Link href=\"/about\" activeClass=\"font-semibold\">About</Link>\n <Link href=\"/link\" activeClass=\"font-semibold\" active={true}>Docs</Link>\n <Link href=\"/pricing\" activeClass=\"font-semibold\">Pricing</Link>\n </nav>\n </div>\n\n <!-- Sidebar Menu -->\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Sidebar menu</p>\n <div class=\"flex w-56 flex-col gap-0.5\">\n <Link\n href=\"/link\"\n raw\n active={true}\n activeClass=\"bg-primary-container text-on-primary-container font-medium\"\n inactiveClass=\"text-on-surface-variant hover:bg-surface-container-highest\"\n class=\"flex items-center gap-2 rounded-md px-3 py-2 text-sm transition-colors\"\n >\n <Icon name=\"lucide:layout-dashboard\" size=\"16\" />\n Dashboard\n </Link>\n <Link\n href=\"/settings\"\n raw\n activeClass=\"bg-primary-container text-on-primary-container font-medium\"\n inactiveClass=\"text-on-surface-variant hover:bg-surface-container-highest\"\n class=\"flex items-center gap-2 rounded-md px-3 py-2 text-sm transition-colors\"\n >\n <Icon name=\"lucide:settings\" size=\"16\" />\n Settings\n </Link>\n <Link\n href=\"/profile\"\n raw\n activeClass=\"bg-primary-container text-on-primary-container font-medium\"\n inactiveClass=\"text-on-surface-variant hover:bg-surface-container-highest\"\n class=\"flex items-center gap-2 rounded-md px-3 py-2 text-sm transition-colors\"\n >\n <Icon name=\"lucide:user\" size=\"16\" />\n Profile\n </Link>\n </div>\n </div>\n\n <!-- Breadcrumb -->\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Breadcrumb</p>\n <nav class=\"flex items-center gap-1 text-sm\">\n <Link href=\"/\">Home</Link>\n <Icon name=\"lucide:chevron-right\" size=\"14\" class=\"text-on-surface-variant/50\" />\n <Link href=\"/link\">Components</Link>\n <Icon name=\"lucide:chevron-right\" size=\"14\" class=\"text-on-surface-variant/50\" />\n <span class=\"text-on-surface\">Link</span>\n </nav>\n </div>\n\n <!-- Footer Links -->\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Footer links</p>\n <div class=\"flex items-center gap-4 text-sm\">\n <Link href=\"https://github.com\">\n <Icon name=\"lucide:github\" size=\"14\" class=\"mr-1\" />\n GitHub\n </Link>\n <span class=\"text-outline-variant\">|</span>\n <Link href=\"https://svelte.dev\">\n <Icon name=\"lucide:external-link\" size=\"14\" class=\"mr-1\" />\n Svelte\n </Link>\n <span class=\"text-outline-variant\">|</span>\n <Link\n href=\"/link\"\n raw\n class=\"text-on-surface-variant underline hover:text-on-surface\"\n >Privacy Policy</Link\n >\n </div>\n </div>\n </section>\n</div>\n",
109
110
  "locale-button": "<script lang=\"ts\">\n import { CodeBlock, LocaleButton } from '$lib/index.js'\n import type { LocaleButtonLocale } from '$lib/index.js'\n\n const locales: LocaleButtonLocale[] = [\n {\n code: 'en',\n label: 'English',\n shortLabel: 'EN',\n description: 'Default content language'\n },\n {\n code: 'th',\n label: 'Thai',\n shortLabel: 'TH',\n description: 'Thai translation'\n },\n {\n code: 'ja',\n label: 'Japanese',\n shortLabel: 'JA',\n description: 'Japanese translation'\n }\n ]\n\n const variants = ['solid', 'outline', 'soft', 'subtle', 'ghost', 'link'] as const\n const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const\n const integrationStrategies = [\n {\n title: 'Callback Strategy',\n badge: 'Recommended',\n description:\n 'Use onLocaleChange when your app controls locale changes in code. This works well with Paraglide cookie-based setups and custom i18n stores.',\n bullets: [\n 'Keeps the current pathname unchanged',\n 'Works with setLocale(..., { reload: false })',\n 'Best default for consumer apps'\n ]\n },\n {\n title: 'Href Strategy',\n badge: 'Optional',\n description:\n 'Use getLocaleHref when your app intentionally exposes locale-specific URLs such as /th/docs or /en/docs.',\n bullets: [\n 'Generates per-locale links',\n 'Useful for URL-prefix routing',\n 'Navigation happens through hrefs instead of imperative state'\n ]\n },\n {\n title: 'Custom I18n',\n badge: 'Flexible',\n description:\n 'You can use LocaleButton without Paraglide at all. Pass your own locale state, persistence, and translation runtime.',\n bullets: [\n 'No hard dependency on Paraglide',\n 'Works with stores, cookies, or API-backed preferences',\n 'Good for non-SvelteKit or mixed stacks'\n ]\n }\n ] as const\n\n const localeItemFields = [\n {\n field: 'code',\n required: 'Yes',\n description: 'The locale identifier used by your i18n layer, such as en or th.'\n },\n {\n field: 'label',\n required: 'Yes',\n description: 'The full label rendered in the dropdown menu.'\n },\n {\n field: 'shortLabel',\n required: 'No',\n description: 'Compact text for the trigger or badge, such as EN or TH.'\n },\n {\n field: 'description',\n required: 'No',\n description: 'Secondary helper text shown inside the menu.'\n },\n {\n field: 'href',\n required: 'No',\n description: 'A precomputed locale-specific link if your app uses href navigation.'\n },\n {\n field: 'hreflang',\n required: 'No',\n description: 'Optional hreflang value forwarded to anchor items.'\n },\n {\n field: 'disabled',\n required: 'No',\n description: 'Disables a specific locale item.'\n }\n ] as const\n\n const integrationChecklist = [\n 'Use onLocaleChange when you do not want locale prefixes in the URL.',\n 'Use getLocaleHref only when your routing strategy intentionally includes locale-specific paths.',\n 'Pass locale from your own source of truth so the trigger always reflects the current language.',\n 'Provide shortLabel values when you want compact trigger text such as EN, TH, or JA.',\n 'Use the children snippet when your product needs a fully custom trigger design.'\n ] as const\n\n let locale = $state('en')\n let customLocale = $state('th')\n\n const paraglideSetLocaleExample =\n `<script lang=\"ts\">\n import { LocaleButton, type LocaleButtonLocale } from 'svelora'\n import { setLocale, toLocale } from '$lib/paraglide/runtime'\n \n const locales: LocaleButtonLocale[] = [\n { code: 'en', label: 'English', shortLabel: 'EN' },\n { code: 'th', label: 'Thai', shortLabel: 'TH' }\n ]\n \n let locale = 'en'\n<` +\n `/script>\n\n<LocaleButton\n {locale}\n {locales}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n const target = toLocale(nextLocale)\n if (target) {\n return setLocale(target)\n }\n }}\n/>`\n\n const paraglideCookieExample =\n `<script lang=\"ts\">\n import { LocaleButton, type LocaleButtonLocale } from 'svelora'\n import { setLocale, toLocale } from '$lib/paraglide/runtime'\n \n const locales: LocaleButtonLocale[] = [\n { code: 'en', label: 'English', shortLabel: 'EN' },\n { code: 'th', label: 'Thai', shortLabel: 'TH' }\n ]\n \n let locale = 'en'\n<` +\n `/script>\n\n<LocaleButton\n {locale}\n {locales}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n const target = toLocale(nextLocale)\n if (target) {\n return setLocale(target, { reload: false })\n }\n }}\n/>`\n\n const consumerAppExample =\n `<script lang=\"ts\">\n import { LocaleButton, type LocaleButtonLocale } from 'svelora'\n import { setLocale, toLocale } from '$lib/paraglide/runtime'\n \n const locales: LocaleButtonLocale[] = [\n { code: 'en', label: 'English', shortLabel: 'EN' },\n { code: 'th', label: 'Thai', shortLabel: 'TH' }\n ]\n \n let locale = 'en'\n<` +\n `/script>\n\n<LocaleButton\n {locales}\n {locale}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n const target = toLocale(nextLocale)\n if (target) {\n return setLocale(target, { reload: false })\n }\n }}\n/>`\n\n const hrefStrategyExample =\n `<script lang=\"ts\">\n import { LocaleButton, type LocaleButtonLocale } from 'svelora'\n import { localizeHref } from '$lib/paraglide/runtime'\n \n const locales: LocaleButtonLocale[] = [\n { code: 'en', label: 'English', shortLabel: 'EN' },\n { code: 'th', label: 'Thai', shortLabel: 'TH' }\n ]\n \n let locale = 'en'\n const pathname = '/docs/components/locale-button'\n<` +\n `/script>\n\n<LocaleButton\n {locales}\n {locale}\n getLocaleHref={(nextLocale) => localizeHref(pathname, { locale: nextLocale })}\n/>`\n\n const customI18nExample =\n `<script lang=\"ts\">\n import { LocaleButton, type LocaleButtonLocale } from 'svelora'\n \n const locales: LocaleButtonLocale[] = [\n { code: 'en', label: 'English', shortLabel: 'EN' },\n { code: 'th', label: 'Thai', shortLabel: 'TH' }\n ]\n \n let locale = 'en'\n \n function applyLocale(nextLocale: string) {\n locale = nextLocale\n localStorage.setItem('preferred-locale', nextLocale)\n }\n<` +\n `/script>\n\n<LocaleButton\n {locales}\n {locale}\n onLocaleChange={(nextLocale) => {\n applyLocale(nextLocale)\n }}\n/>`\n\n const localeShapeExample = `import type { LocaleButtonLocale } from 'svelora'\n\nconst locales: LocaleButtonLocale[] = [\n {\n code: 'en',\n label: 'English',\n shortLabel: 'EN',\n description: 'Default content language'\n },\n {\n code: 'th',\n label: 'Thai',\n shortLabel: 'TH',\n description: 'Thai translation',\n href: '/th/docs',\n hreflang: 'th'\n }\n]`\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">LocaleButton</h1>\n <p class=\"text-on-surface-variant\">\n A language switcher button designed to work nicely with Paraglide. Use\n <code class=\"rounded bg-surface-container-highest px-1\">onLocaleChange</code> for\n <code class=\"rounded bg-surface-container-highest px-1\">setLocale()</code> flows\n while keeping the current path unchanged.\n </p>\n </div>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic Usage</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <LocaleButton\n {locales}\n {locale}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n }}\n />\n <span class=\"text-sm text-on-surface-variant\">Current locale: {locale}</span>\n </div>\n </section>\n\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold\">Choose Your Strategy</h2>\n <p class=\"text-sm text-on-surface-variant\">\n <code class=\"rounded bg-surface-container-highest px-1\">LocaleButton</code> is only\n the UI layer. Your app decides how locale changes are applied.\n </p>\n <div class=\"grid gap-4 lg:grid-cols-3\">\n {#each integrationStrategies as strategy (strategy.title)}\n <div class=\"space-y-3 rounded-2xl border border-outline-variant bg-surface-container/40 p-5\">\n <div class=\"flex items-center justify-between gap-3\">\n <h3 class=\"text-base font-semibold\">{strategy.title}</h3>\n <span class=\"rounded-full bg-primary/10 px-2.5 py-1 text-xs font-medium text-primary\">\n {strategy.badge}\n </span>\n </div>\n <p class=\"text-sm text-on-surface-variant\">{strategy.description}</p>\n <ul class=\"space-y-2 text-sm text-on-surface-variant\">\n {#each strategy.bullets as bullet (bullet)}\n <li>{bullet}</li>\n {/each}\n </ul>\n </div>\n {/each}\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Paraglide with setLocale</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the selection callback when your app already manages locale changes in code.\n </p>\n <CodeBlock title=\"Paraglide setLocale()\" code={paraglideSetLocaleExample} />\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <LocaleButton\n {locales}\n {locale}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n }}\n />\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Use In Consumer Apps</h2>\n <p class=\"text-sm text-on-surface-variant\">\n <code class=\"rounded bg-surface-container-highest px-1\">LocaleButton</code> is\n exported from the\n <code class=\"rounded bg-surface-container-highest px-1\">svelora</code> package and can\n be used in any app that installs this library.\n </p>\n <p class=\"text-sm text-on-surface-variant\">\n The component does not depend on Paraglide internally. Your app provides\n <code class=\"rounded bg-surface-container-highest px-1\">locale</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">locales</code>, and the\n locale-change logic through\n <code class=\"rounded bg-surface-container-highest px-1\">onLocaleChange</code> or\n <code class=\"rounded bg-surface-container-highest px-1\">getLocaleHref</code>.\n </p>\n <CodeBlock title=\"Consumer app example\" code={consumerAppExample} />\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Keep The Same Path</h2>\n <p class=\"text-sm text-on-surface-variant\">\n With cookie-based Paraglide strategy, you can switch locale without adding\n <code class=\"rounded bg-surface-container-highest px-1\">/th</code> or other locale\n prefixes to the URL.\n </p>\n <CodeBlock title=\"Paraglide without locale prefix\" code={paraglideCookieExample} />\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <LocaleButton\n {locales}\n {locale}\n disableCurrentLocale={false}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n }}\n />\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Use Locale Prefix URLs</h2>\n <p class=\"text-sm text-on-surface-variant\">\n If your product intentionally uses locale-prefixed routes such as\n <code class=\"rounded bg-surface-container-highest px-1\">/th/docs</code>, provide\n <code class=\"rounded bg-surface-container-highest px-1\">getLocaleHref</code>. This\n keeps navigation declarative and lets the button render locale-specific links.\n </p>\n <CodeBlock title=\"Href strategy with localizeHref()\" code={hrefStrategyExample} />\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Use Without Paraglide</h2>\n <p class=\"text-sm text-on-surface-variant\">\n The component works with any locale source of truth. You can connect it to a Svelte\n store, cookies, localStorage, an API-backed user preference, or another i18n runtime.\n </p>\n <CodeBlock title=\"Custom i18n integration\" code={customI18nExample} />\n </section>\n\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold\">Locale Item Shape</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Each locale entry is just data. Start with\n <code class=\"rounded bg-surface-container-highest px-1\">code</code> and\n <code class=\"rounded bg-surface-container-highest px-1\">label</code>, then add\n optional fields only when your app needs them.\n </p>\n <CodeBlock title=\"LocaleButtonLocale[]\" code={localeShapeExample} />\n <div class=\"overflow-hidden rounded-2xl border border-outline-variant\">\n <table class=\"w-full text-left text-sm\">\n <thead class=\"bg-surface-container\">\n <tr>\n <th class=\"px-4 py-3 font-semibold\">Field</th>\n <th class=\"px-4 py-3 font-semibold\">Required</th>\n <th class=\"px-4 py-3 font-semibold\">Purpose</th>\n </tr>\n </thead>\n <tbody>\n {#each localeItemFields as field (field.field)}\n <tr class=\"border-t border-outline-variant/70\">\n <td class=\"px-4 py-3 font-mono text-xs\">{field.field}</td>\n <td class=\"px-4 py-3 text-on-surface-variant\">{field.required}</td>\n <td class=\"px-4 py-3 text-on-surface-variant\">{field.description}</td>\n </tr>\n {/each}\n </tbody>\n </table>\n </div>\n </section>\n\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold\">Integration Checklist</h2>\n <div class=\"rounded-2xl border border-outline-variant bg-surface-container/40 p-5\">\n <ul class=\"space-y-3 text-sm text-on-surface-variant\">\n {#each integrationChecklist as item (item)}\n <li>{item}</li>\n {/each}\n </ul>\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants</h2>\n <div class=\"flex flex-wrap items-center gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each variants as variant (variant)}\n <LocaleButton\n {locales}\n {locale}\n {variant}\n size=\"sm\"\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n }}\n />\n {/each}\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <div class=\"flex flex-wrap items-end gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each sizes as size (size)}\n <LocaleButton\n {locales}\n {locale}\n {size}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n }}\n />\n {/each}\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Trigger</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the\n <code class=\"rounded bg-surface-container-highest px-1\">children</code> snippet to\n fully control the trigger content while keeping the dropdown behavior.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <LocaleButton\n {locales}\n locale={customLocale}\n square={false}\n variant=\"soft\"\n color=\"primary\"\n onLocaleChange={(nextLocale) => {\n customLocale = nextLocale\n }}\n >\n {#snippet children({ currentLocale, open })}\n <span class=\"flex items-center gap-2\">\n <span>{currentLocale?.label ?? 'Language'}</span>\n <span class=\"text-xs text-on-surface-variant\">\n {open ? 'Open' : currentLocale?.code.toUpperCase()}\n </span>\n </span>\n {/snippet}\n </LocaleButton>\n </div>\n </section>\n</div>\n",
110
111
  "kbd": "<script lang=\"ts\">\n import { Kbd, useKbd } from '$lib/index.js'\n\n const colors = [\n 'primary',\n 'secondary',\n 'success',\n 'warning',\n 'error',\n 'info',\n 'surface'\n ] as const\n const variants = ['solid', 'outline', 'soft', 'subtle'] as const\n const sizes = ['sm', 'md', 'lg'] as const\n\n let shortcutLog = $state<string[]>([])\n let searchOpen = $state(false)\n\n const kbd = useKbd({\n shortcuts: {\n 'ctrl+k': () => {\n searchOpen = !searchOpen\n shortcutLog = [...shortcutLog, 'Ctrl+K → Toggle search'].slice(-5)\n },\n 'ctrl+shift+p': () => {\n shortcutLog = [...shortcutLog, 'Ctrl+Shift+P → Command palette'].slice(-5)\n },\n escape: () => {\n searchOpen = false\n shortcutLog = [...shortcutLog, 'Escape → Close'].slice(-5)\n }\n },\n captureModifiers: true\n })\n\n const modifierKeys = ['meta', 'ctrl', 'alt', 'shift'] as const\n const specialKeys = [\n 'enter',\n 'escape',\n 'tab',\n 'backspace',\n 'delete',\n 'space',\n 'capslock'\n ] as const\n const arrowKeys = ['arrowup', 'arrowdown', 'arrowleft', 'arrowright'] as const\n const navKeys = ['pageup', 'pagedown', 'home', 'end'] as const\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Kbd</h1>\n <p class=\"text-on-surface-variant\">\n Keyboard key indicator for displaying shortcuts and key combinations.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n <Kbd value=\"K\" />\n <Kbd value=\"Enter\" />\n <Kbd value=\"Escape\" />\n <Kbd value=\"Tab\" />\n </div>\n </section>\n\n <!-- Modifier Keys -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Modifier Keys</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Platform-aware: Mac shows symbols, others show text labels.\n </p>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n {#each modifierKeys as key (key)}\n <Kbd value={key} />\n {/each}\n </div>\n </section>\n\n <!-- Special Keys -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Special Keys</h2>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n {#each specialKeys as key (key)}\n <Kbd value={key} />\n {/each}\n </div>\n </section>\n\n <!-- Arrow & Navigation Keys -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Arrow & Navigation Keys</h2>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n {#each arrowKeys as key (key)}\n <Kbd value={key} />\n {/each}\n <span class=\"mx-1 text-on-surface-variant\">|</span>\n {#each navKeys as key (key)}\n <Kbd value={key} />\n {/each}\n </div>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <div class=\"flex flex-wrap items-center gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each sizes as size (size)}\n <div class=\"flex items-center gap-1\">\n <span class=\"text-sm text-on-surface-variant\">{size}:</span>\n <Kbd value=\"K\" {size} />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Variants -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants</h2>\n <div class=\"space-y-3 rounded-lg bg-surface-container-high p-4\">\n {#each variants as variant (variant)}\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"w-16 text-sm text-on-surface-variant\">{variant}</span>\n {#each colors as color (color)}\n <Kbd value=\"K\" {variant} {color} />\n {/each}\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Children Slot -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Children Slot</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the default snippet for custom key labels.\n </p>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n <Kbd>F1</Kbd>\n <Kbd>F12</Kbd>\n <Kbd>PgUp</Kbd>\n <Kbd>PgDn</Kbd>\n <Kbd>Ins</Kbd>\n <Kbd>Fn</Kbd>\n </div>\n </section>\n\n <!-- Keyboard Shortcuts -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Keyboard Shortcuts</h2>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n {#each [{ label: 'Copy', keys: ['meta', 'C'] }, { label: 'Paste', keys: ['meta', 'V'] }, { label: 'Save', keys: ['meta', 'S'] }, { label: 'Search', keys: ['meta', 'K'] }, { label: 'Undo', keys: ['meta', 'Z'] }, { label: 'Redo', keys: ['meta', 'shift', 'Z'] }] as shortcut (shortcut.label)}\n <div class=\"flex items-center justify-between\">\n <span class=\"text-sm\">{shortcut.label}</span>\n <div class=\"flex items-center gap-1\">\n {#each shortcut.keys as key, i (i)}\n {#if i > 0}\n <span class=\"text-on-surface-variant\">+</span>\n {/if}\n <Kbd value={key} />\n {/each}\n </div>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- UI Slot Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Slot Overrides</h2>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n <Kbd value=\"K\" ui={{ base: 'rounded-md' }} />\n <Kbd value=\"meta\" ui={{ base: 'rounded-full px-2' }} />\n <Kbd value=\"Enter\" ui={{ base: 'rounded-lg px-2 shadow-sm' }} variant=\"soft\" />\n </div>\n </section>\n\n <!-- Real World Examples -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n <div class=\"space-y-6 rounded-lg bg-surface-container-high p-4\">\n <!-- Command Palette -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Command Palette Trigger</p>\n <div\n class=\"flex items-center gap-2 rounded-lg border border-outline-variant bg-surface-container p-3\"\n >\n <span class=\"flex-1 text-sm text-on-surface-variant\">Search commands...</span>\n <div class=\"flex items-center gap-1\">\n <Kbd value=\"meta\" size=\"sm\" />\n <Kbd value=\"K\" size=\"sm\" />\n </div>\n </div>\n </div>\n\n <!-- Menu Item -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Menu Item with Shortcut</p>\n <div class=\"max-w-xs rounded-lg border border-outline-variant bg-surface-container\">\n {#each [{ label: 'New File', keys: ['meta', 'N'] }, { label: 'Open File', keys: ['meta', 'O'] }, { label: 'Save', keys: ['meta', 'S'] }] as item (item.label)}\n <div\n class=\"flex items-center justify-between px-3 py-2 hover:bg-surface-container-high\"\n >\n <span class=\"text-sm\">{item.label}</span>\n <div class=\"flex items-center gap-0.5\">\n {#each item.keys as key (key)}\n <Kbd value={key} size=\"sm\" variant=\"soft\" />\n {/each}\n </div>\n </div>\n {/each}\n </div>\n </div>\n\n <!-- Inline Help -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Inline Help Text</p>\n <p class=\"text-sm text-on-surface-variant\">\n Press <Kbd value=\"escape\" size=\"sm\" class=\"mx-0.5\" /> to close the modal, or\n <Kbd value=\"enter\" size=\"sm\" class=\"mx-0.5\" /> to confirm.\n </p>\n </div>\n\n <!-- Navigation Hint -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Navigation Hint</p>\n <div class=\"flex items-center gap-4 text-sm text-on-surface-variant\">\n <span class=\"flex items-center gap-1\">\n <Kbd value=\"arrowup\" size=\"sm\" />\n <Kbd value=\"arrowdown\" size=\"sm\" />\n to navigate\n </span>\n <span class=\"flex items-center gap-1\">\n <Kbd value=\"enter\" size=\"sm\" />\n to select\n </span>\n </div>\n </div>\n </div>\n </section>\n\n <!-- useKbd: Shortcut Listener -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">useKbd — Shortcut Listener</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Try pressing the shortcuts below. The hook listens for keyboard events and fires\n callbacks.\n </p>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-wrap gap-4 text-sm\">\n <span class=\"flex items-center gap-1\">\n <Kbd value=\"ctrl\" size=\"sm\" /> + <Kbd value=\"K\" size=\"sm\" /> Toggle search\n </span>\n <span class=\"flex items-center gap-1\">\n <Kbd value=\"ctrl\" size=\"sm\" /> + <Kbd value=\"shift\" size=\"sm\" /> +\n <Kbd value=\"P\" size=\"sm\" /> Command palette\n </span>\n <span class=\"flex items-center gap-1\">\n <Kbd value=\"escape\" size=\"sm\" /> Close\n </span>\n </div>\n\n {#if searchOpen}\n <div\n class=\"flex items-center gap-2 rounded-lg border border-primary/50 bg-surface-container p-3\"\n >\n <span class=\"flex-1 text-sm text-on-surface-variant\">\n Search is open! Press <Kbd value=\"escape\" size=\"sm\" class=\"mx-0.5\" /> to close.\n </span>\n </div>\n {/if}\n\n {#if shortcutLog.length > 0}\n <div class=\"space-y-1 rounded-md bg-surface-container p-3\">\n <p class=\"text-xs font-medium text-on-surface-variant\">Recent shortcuts:</p>\n {#each shortcutLog as entry, i (i)}\n <p class=\"font-mono text-xs text-on-surface\">{entry}</p>\n {/each}\n </div>\n {/if}\n </div>\n </section>\n\n <!-- useKbd: Reactive Key State -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">useKbd — Reactive Key State</h2>\n <p class=\"text-sm text-on-surface-variant\">Hold any key to see it tracked in real-time.</p>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-wrap gap-2\">\n {#each ['shift', 'ctrl', 'alt', 'meta'] as key (key)}\n <div\n class=\"rounded-lg border px-3 py-2 text-sm transition-colors {kbd.isPressed(\n key\n )\n ? 'border-primary bg-primary-container text-on-primary-container'\n : 'border-outline-variant bg-surface-container text-on-surface-variant'}\"\n >\n <Kbd\n value={key}\n size=\"sm\"\n variant={kbd.isPressed(key) ? 'solid' : 'outline'}\n color={kbd.isPressed(key) ? 'primary' : 'surface'}\n />\n <span class=\"ml-1\">{kbd.isPressed(key) ? 'Pressed' : 'Released'}</span>\n </div>\n {/each}\n </div>\n\n <div class=\"rounded-md bg-surface-container p-3\">\n <p class=\"text-xs font-medium text-on-surface-variant\">Currently pressed keys:</p>\n <p class=\"mt-1 font-mono text-sm text-on-surface\">\n {#if kbd.pressedKeys.size > 0}\n {[...kbd.pressedKeys].join(' + ')}\n {:else}\n <span class=\"text-on-surface-variant\">None</span>\n {/if}\n </p>\n </div>\n </div>\n </section>\n\n <!-- Variants x Colors Matrix -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants x Colors</h2>\n <div class=\"overflow-x-auto rounded-lg bg-surface-container-high p-4\">\n <table class=\"w-full\">\n <thead>\n <tr class=\"border-b border-outline-variant\">\n <th class=\"px-3 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >Variant</th\n >\n {#each colors as color (color)}\n <th\n class=\"px-3 py-3 text-center text-sm font-medium text-on-surface-variant capitalize\"\n >{color}</th\n >\n {/each}\n </tr>\n </thead>\n <tbody>\n {#each variants as variant (variant)}\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-3 text-sm font-medium text-on-surface-variant\"\n >{variant}</td\n >\n {#each colors as color (color)}\n <td class=\"px-3 py-3 text-center\">\n <Kbd value=\"K\" {variant} {color} />\n </td>\n {/each}\n </tr>\n {/each}\n </tbody>\n </table>\n </div>\n </section>\n</div>\n",
111
- "theme-mode-button": "<script lang=\"ts\">\n import { ThemeModeButton, mode } from '$lib/index.js'\n\n const variants = ['solid', 'outline', 'soft', 'subtle', 'ghost', 'link'] as const\n const colors = [\n 'primary',\n 'secondary',\n 'tertiary',\n 'success',\n 'warning',\n 'error',\n 'info',\n 'surface'\n ] as const\n const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">ThemeModeButton</h1>\n <p class=\"text-on-surface-variant\">\n A button to switch between light and dark mode. Built on top of the Button component\n and Svelora theme utilities.\n </p>\n </div>\n\n <!-- Basic Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic Usage</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <ThemeModeButton />\n <span class=\"text-sm text-on-surface-variant capitalize\">\n Current mode: {mode.current}\n </span>\n </div>\n </section>\n\n <!-- Variants -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants</h2>\n <div class=\"flex flex-wrap items-center gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each variants as variant (variant)}\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton {variant} color=\"primary\" />\n <span class=\"text-xs text-on-surface-variant capitalize\">{variant}</span>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Colors -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Colors</h2>\n <div class=\"overflow-x-auto\">\n <table class=\"w-full\">\n <thead>\n <tr class=\"border-b border-outline-variant\">\n <th class=\"px-2 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >Variant</th\n >\n {#each colors as color (color)}\n <th\n class=\"px-2 py-3 text-center text-sm font-medium text-on-surface-variant capitalize\"\n >{color}</th\n >\n {/each}\n </tr>\n </thead>\n <tbody>\n {#each variants as variant (variant)}\n <tr class=\"border-b border-outline-variant/50\">\n <td\n class=\"px-2 py-3 text-sm font-medium text-on-surface-variant capitalize\"\n >{variant}</td\n >\n {#each colors as color (color)}\n <td class=\"px-2 py-3 text-center\">\n <ThemeModeButton {variant} {color} />\n </td>\n {/each}\n </tr>\n {/each}\n </tbody>\n </table>\n </div>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <div class=\"flex flex-wrap items-end gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each sizes as size (size)}\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton {size} />\n <span class=\"text-xs text-on-surface-variant\">{size}</span>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Custom Icons -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Icons</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Override the default light/dark icons using the\n <code class=\"rounded bg-surface-container-highest px-1\">lightIcon</code> and\n <code class=\"rounded bg-surface-container-highest px-1\">darkIcon</code> props.\n </p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton lightIcon=\"lucide:sun-medium\" darkIcon=\"lucide:moon-star\" />\n <span class=\"text-xs text-on-surface-variant\">sun-medium / moon-star</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton lightIcon=\"lucide:sun-dim\" darkIcon=\"lucide:cloud-moon\" />\n <span class=\"text-xs text-on-surface-variant\">sun-dim / cloud-moon</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton lightIcon=\"lucide:sunrise\" darkIcon=\"lucide:sunset\" />\n <span class=\"text-xs text-on-surface-variant\">sunrise / sunset</span>\n </div>\n </div>\n </section>\n\n <!-- Non-square (with label via children) -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Content (Children Snippet)</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">children</code> snippet\n with\n <code class=\"rounded bg-surface-container-highest px-1\">{'{ isDark }'}</code> to render custom\n content.\n </p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <ThemeModeButton square={false} variant=\"outline\" color=\"secondary\">\n {#snippet children({ isDark })}\n {isDark ? 'Light Mode' : 'Dark Mode'}\n {/snippet}\n </ThemeModeButton>\n\n <ThemeModeButton square={false} variant=\"soft\" color=\"primary\">\n {#snippet children({ isDark })}\n <span class=\"flex items-center gap-2\">\n {#if isDark}\n ☀️ Switch to Light\n {:else}\n 🌙 Switch to Dark\n {/if}\n </span>\n {/snippet}\n </ThemeModeButton>\n </div>\n </section>\n\n <!-- Disabled & Loading -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Disabled & Loading</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton disabled />\n <span class=\"text-xs text-on-surface-variant\">Disabled</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton loading />\n <span class=\"text-xs text-on-surface-variant\">Loading</span>\n </div>\n </div>\n </section>\n\n <!-- UI Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Prop (Class Overrides)</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton class=\"rounded-full\" variant=\"outline\" color=\"primary\" />\n <span class=\"text-xs text-on-surface-variant\">Pill shape</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton\n variant=\"solid\"\n color=\"tertiary\"\n class=\"shadow-lg shadow-tertiary/30\"\n />\n <span class=\"text-xs text-on-surface-variant\">With shadow</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton\n variant=\"solid\"\n color=\"primary\"\n class=\"bg-linear-to-r from-primary to-tertiary hover:from-primary/90 hover:to-tertiary/90\"\n />\n <span class=\"text-xs text-on-surface-variant\">Gradient</span>\n </div>\n </div>\n </section>\n</div>\n",
112
+ "theme-mode-button": "<script lang=\"ts\">\n import { ThemeModeButton } from '$lib/index.js'\n import { mode } from 'mode-watcher'\n\n const variants = ['solid', 'outline', 'soft', 'subtle', 'ghost', 'link'] as const\n const colors = [\n 'primary',\n 'secondary',\n 'tertiary',\n 'success',\n 'warning',\n 'error',\n 'info',\n 'surface'\n ] as const\n const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">ThemeModeButton</h1>\n <p class=\"text-on-surface-variant\">\n A button to switch between light and dark mode. Built on top of the Button component\n and <code class=\"rounded bg-surface-container-highest px-1\">mode-watcher</code>.\n </p>\n <div class=\"mt-4 rounded-xl border-l-4 border-warning bg-warning/10 p-4 text-sm text-on-surface-variant\">\n <strong class=\"font-semibold text-warning\">Requirement:</strong>\n You must install <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-sm\">mode-watcher</code> as a peer dependency to use this component.\n </div>\n </div>\n\n <!-- Basic Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic Usage</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <ThemeModeButton />\n <span class=\"text-sm text-on-surface-variant capitalize\">\n Current mode: {mode.current}\n </span>\n </div>\n </section>\n\n <!-- Variants -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants</h2>\n <div class=\"flex flex-wrap items-center gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each variants as variant (variant)}\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton {variant} color=\"primary\" />\n <span class=\"text-xs text-on-surface-variant capitalize\">{variant}</span>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Colors -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Colors</h2>\n <div class=\"overflow-x-auto\">\n <table class=\"w-full\">\n <thead>\n <tr class=\"border-b border-outline-variant\">\n <th class=\"px-2 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >Variant</th\n >\n {#each colors as color (color)}\n <th\n class=\"px-2 py-3 text-center text-sm font-medium text-on-surface-variant capitalize\"\n >{color}</th\n >\n {/each}\n </tr>\n </thead>\n <tbody>\n {#each variants as variant (variant)}\n <tr class=\"border-b border-outline-variant/50\">\n <td\n class=\"px-2 py-3 text-sm font-medium text-on-surface-variant capitalize\"\n >{variant}</td\n >\n {#each colors as color (color)}\n <td class=\"px-2 py-3 text-center\">\n <ThemeModeButton {variant} {color} />\n </td>\n {/each}\n </tr>\n {/each}\n </tbody>\n </table>\n </div>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <div class=\"flex flex-wrap items-end gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each sizes as size (size)}\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton {size} />\n <span class=\"text-xs text-on-surface-variant\">{size}</span>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Custom Icons -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Icons</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Override the default light/dark icons using the\n <code class=\"rounded bg-surface-container-highest px-1\">lightIcon</code> and\n <code class=\"rounded bg-surface-container-highest px-1\">darkIcon</code> props.\n </p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton lightIcon=\"lucide:sun-medium\" darkIcon=\"lucide:moon-star\" />\n <span class=\"text-xs text-on-surface-variant\">sun-medium / moon-star</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton lightIcon=\"lucide:sun-dim\" darkIcon=\"lucide:cloud-moon\" />\n <span class=\"text-xs text-on-surface-variant\">sun-dim / cloud-moon</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton lightIcon=\"lucide:sunrise\" darkIcon=\"lucide:sunset\" />\n <span class=\"text-xs text-on-surface-variant\">sunrise / sunset</span>\n </div>\n </div>\n </section>\n\n <!-- Non-square (with label via children) -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Content (Children Snippet)</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">children</code> snippet\n with\n <code class=\"rounded bg-surface-container-highest px-1\">{'{ isDark }'}</code> to render custom\n content.\n </p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <ThemeModeButton square={false} variant=\"outline\" color=\"secondary\">\n {#snippet children({ isDark })}\n {isDark ? 'Light Mode' : 'Dark Mode'}\n {/snippet}\n </ThemeModeButton>\n\n <ThemeModeButton square={false} variant=\"soft\" color=\"primary\">\n {#snippet children({ isDark })}\n <span class=\"flex items-center gap-2\">\n {#if isDark}\n ☀️ Switch to Light\n {:else}\n 🌙 Switch to Dark\n {/if}\n </span>\n {/snippet}\n </ThemeModeButton>\n </div>\n </section>\n\n <!-- Disabled & Loading -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Disabled & Loading</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton disabled />\n <span class=\"text-xs text-on-surface-variant\">Disabled</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton loading />\n <span class=\"text-xs text-on-surface-variant\">Loading</span>\n </div>\n </div>\n </section>\n\n <!-- UI Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Prop (Class Overrides)</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton class=\"rounded-full\" variant=\"outline\" color=\"primary\" />\n <span class=\"text-xs text-on-surface-variant\">Pill shape</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton\n variant=\"solid\"\n color=\"tertiary\"\n class=\"shadow-lg shadow-tertiary/30\"\n />\n <span class=\"text-xs text-on-surface-variant\">With shadow</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton\n variant=\"solid\"\n color=\"primary\"\n class=\"bg-linear-to-r from-primary to-tertiary hover:from-primary/90 hover:to-tertiary/90\"\n />\n <span class=\"text-xs text-on-surface-variant\">Gradient</span>\n </div>\n </div>\n </section>\n</div>\n",
112
113
  "bento-grid": "<script lang=\"ts\">\n import { BentoGrid, BentoCard, Icon } from '$lib/index.js'\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">BentoGrid</h1>\n <p class=\"text-on-surface-variant\">\n A masonry-like grid layout composed of beautifully animated cards, inspired by Bento boxes.\n </p>\n </div>\n\n <!-- Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Usage</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">BentoGrid</code> as a wrapper and <code class=\"rounded bg-surface-container-highest px-1\">BentoCard</code> for the children. \n Adjust the <code class=\"rounded bg-surface-container-highest px-1\">col-span-*</code> classes on the children to make them span different columns.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4 bg-surface-50 dark:bg-surface-900\">\n <BentoGrid class=\"max-w-3xl mx-auto\">\n <BentoCard \n class=\"md:col-span-2 md:row-span-2\" \n name=\"Analytics\" \n icon=\"lucide:line-chart\"\n description=\"Dive deep into your traffic data.\"\n href=\"#\"\n cta=\"View dashboard\"\n >\n {#snippet background()}\n <div class=\"absolute right-0 top-0 opacity-10 blur-xl\">\n <Icon name=\"lucide:bar-chart-3\" size=\"200\" />\n </div>\n {/snippet}\n </BentoCard>\n\n <BentoCard \n name=\"Notifications\" \n icon=\"lucide:bell\"\n description=\"Manage your alert settings.\"\n href=\"#\"\n />\n\n <BentoCard \n name=\"Security\" \n icon=\"lucide:shield-check\"\n description=\"Keep your account safe.\"\n href=\"#\"\n />\n \n <BentoCard \n class=\"md:col-span-3\"\n name=\"Integrations\" \n icon=\"lucide:blocks\"\n description=\"Connect with your favorite tools seamlessly.\"\n href=\"#\"\n cta=\"Browse tools\"\n />\n </BentoGrid>\n </div>\n </section>\n</div>\n",
113
114
  "card": "<script lang=\"ts\">\n import { Card, Button, Icon, Avatar } from '$lib/index.js'\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Card</h1>\n <p class=\"text-on-surface-variant\">\n Container component for grouping related content with optional header and footer.\n </p>\n </div>\n\n <!-- Variants -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants</h2>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <Card variant=\"outline\">\n {#snippet header()}\n <h3 class=\"font-semibold\">Outline (Default)</h3>\n {/snippet}\n <p class=\"text-on-surface-variant\">Card with border and background.</p>\n </Card>\n\n <Card variant=\"soft\">\n {#snippet header()}\n <h3 class=\"font-semibold\">Soft</h3>\n {/snippet}\n <p class=\"text-on-surface-variant\">Card with subtle background.</p>\n </Card>\n\n <Card variant=\"subtle\">\n {#snippet header()}\n <h3 class=\"font-semibold\">Subtle</h3>\n {/snippet}\n <p class=\"text-on-surface-variant\">Card with background and border.</p>\n </Card>\n\n <Card variant=\"solid\">\n {#snippet header()}\n <h3 class=\"font-semibold\">Solid</h3>\n {/snippet}\n <p class=\"opacity-90\">Card with inverted colors.</p>\n </Card>\n </div>\n </section>\n\n <!-- With Header and Footer -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">With Header & Footer</h2>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <Card>\n {#snippet header()}\n <div class=\"flex items-center justify-between\">\n <h3 class=\"font-semibold\">Card Title</h3>\n <Button\n variant=\"ghost\"\n color=\"secondary\"\n icon=\"lucide:more-horizontal\"\n square\n size=\"sm\"\n />\n </div>\n {/snippet}\n <p class=\"text-on-surface-variant\">\n This is the card body content. You can put any content here.\n </p>\n {#snippet footer()}\n <div class=\"flex justify-end gap-2\">\n <Button variant=\"ghost\" color=\"secondary\" label=\"Cancel\" size=\"sm\" />\n <Button variant=\"solid\" color=\"primary\" label=\"Save\" size=\"sm\" />\n </div>\n {/snippet}\n </Card>\n\n <Card variant=\"soft\">\n {#snippet header()}\n <div class=\"flex items-center gap-3\">\n <Avatar src=\"https://i.pravatar.cc/150?img=5\" alt=\"John Doe\" size=\"md\" />\n <div>\n <h3 class=\"font-semibold\">John Doe</h3>\n <p class=\"text-sm text-on-surface-variant\">Software Engineer</p>\n </div>\n </div>\n {/snippet}\n <p class=\"text-on-surface-variant\">\n Building awesome things with Svelte and TypeScript.\n </p>\n {#snippet footer()}\n <div class=\"flex gap-2\">\n <Button\n variant=\"soft\"\n color=\"primary\"\n leadingIcon=\"lucide:mail\"\n label=\"Contact\"\n size=\"sm\"\n />\n <Button\n variant=\"ghost\"\n color=\"secondary\"\n leadingIcon=\"lucide:user-plus\"\n label=\"Follow\"\n size=\"sm\"\n />\n </div>\n {/snippet}\n </Card>\n </div>\n </section>\n\n <!-- Body Only -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Body Only</h2>\n <div class=\"grid gap-4 md:grid-cols-3\">\n <Card>\n <div class=\"text-center\">\n <Icon name=\"lucide:folder\" size=\"32\" class=\"mx-auto text-primary\" />\n <h4 class=\"mt-2 font-medium\">Documents</h4>\n <p class=\"text-sm text-on-surface-variant\">24 files</p>\n </div>\n </Card>\n\n <Card variant=\"soft\">\n <div class=\"text-center\">\n <Icon name=\"lucide:image\" size=\"32\" class=\"mx-auto text-success\" />\n <h4 class=\"mt-2 font-medium\">Images</h4>\n <p class=\"text-sm text-on-surface-variant\">128 files</p>\n </div>\n </Card>\n\n <Card variant=\"subtle\">\n <div class=\"text-center\">\n <Icon name=\"lucide:music\" size=\"32\" class=\"mx-auto text-tertiary\" />\n <h4 class=\"mt-2 font-medium\">Music</h4>\n <p class=\"text-sm text-on-surface-variant\">56 files</p>\n </div>\n </Card>\n </div>\n </section>\n\n <!-- Custom Styling -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Styling</h2>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <Card class=\"border-l-4 border-l-primary\">\n {#snippet header()}\n <h3 class=\"font-semibold text-primary\">Accent Border</h3>\n {/snippet}\n <p class=\"text-on-surface-variant\">Card with left accent border.</p>\n </Card>\n\n <Card\n class=\"shadow-lg\"\n ui={{ header: 'bg-primary text-on-primary', body: 'bg-primary-container' }}\n >\n {#snippet header()}\n <h3 class=\"font-semibold\">Custom Slots</h3>\n {/snippet}\n <p class=\"text-on-primary-container\">\n Card with custom header and body styles via ui prop.\n </p>\n </Card>\n </div>\n </section>\n\n <!-- As Different Element -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">As Different Element</h2>\n <Card as=\"article\" variant=\"soft\">\n {#snippet header()}\n <h3 class=\"font-semibold\">Article Card</h3>\n <p class=\"text-sm text-on-surface-variant\">Rendered as &lt;article&gt; element</p>\n {/snippet}\n <p class=\"text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">as</code> prop to render\n as different HTML elements for better semantics.\n </p>\n </Card>\n </section>\n</div>\n",
114
115
  "container": "<script lang=\"ts\">\n import { Container } from '$lib/index.js'\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Container</h1>\n <p class=\"text-on-surface-variant\">\n Layout component that centers and constrains content width with responsive padding.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Container class=\"rounded-lg bg-primary-container/30 py-4 text-center\">\n <p class=\"text-on-primary-container\">\n Content is centered with max-w-7xl and responsive padding.\n </p>\n </Container>\n </div>\n </section>\n\n <!-- Semantic Elements -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Semantic Elements</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">as</code> prop to render as\n different HTML elements.\n </p>\n <div class=\"space-y-3 rounded-lg bg-surface-container-high p-4\">\n <Container as=\"section\" class=\"rounded-lg bg-secondary-container/30 py-3 text-center\">\n <p class=\"text-sm text-on-secondary-container\">Rendered as &lt;section&gt;</p>\n </Container>\n <Container as=\"main\" class=\"rounded-lg bg-tertiary-container/30 py-3 text-center\">\n <p class=\"text-sm text-on-tertiary-container\">Rendered as &lt;main&gt;</p>\n </Container>\n <Container as=\"article\" class=\"rounded-lg bg-success-container/30 py-3 text-center\">\n <p class=\"text-sm text-on-success-container\">Rendered as &lt;article&gt;</p>\n </Container>\n <Container as=\"nav\" class=\"rounded-lg bg-info-container/30 py-3 text-center\">\n <p class=\"text-sm text-on-info-container\">Rendered as &lt;nav&gt;</p>\n </Container>\n </div>\n </section>\n\n <!-- UI Slot Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Slot Overrides</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Override the default max-width and padding using the <code\n class=\"rounded bg-surface-container-highest px-1\">ui</code\n > prop.\n </p>\n <div class=\"space-y-3 rounded-lg bg-surface-container-high p-4\">\n <Container\n ui={{ root: 'max-w-sm' }}\n class=\"rounded-lg bg-warning-container/30 py-3 text-center\"\n >\n <p class=\"text-sm text-on-warning-container\">max-w-sm</p>\n </Container>\n <Container\n ui={{ root: 'max-w-xl' }}\n class=\"rounded-lg bg-primary-container/30 py-3 text-center\"\n >\n <p class=\"text-sm text-on-primary-container\">max-w-xl</p>\n </Container>\n <Container\n ui={{ root: 'max-w-3xl' }}\n class=\"rounded-lg bg-secondary-container/30 py-3 text-center\"\n >\n <p class=\"text-sm text-on-secondary-container\">max-w-3xl</p>\n </Container>\n <Container class=\"rounded-lg bg-tertiary-container/30 py-3 text-center\">\n <p class=\"text-sm text-on-tertiary-container\">max-w-7xl (default)</p>\n </Container>\n </div>\n </section>\n\n <!-- Custom Class -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Class</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Container class=\"rounded-xl border border-outline-variant bg-surface-container p-6\">\n <h3 class=\"mb-2 font-medium\">Card-like Container</h3>\n <p class=\"text-sm text-on-surface-variant\">\n Combine Container with custom classes to create card-like layouts with\n consistent max-width.\n </p>\n </Container>\n </div>\n </section>\n\n <!-- Real World Examples -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n <div class=\"space-y-6 rounded-lg bg-surface-container-high p-4\">\n <!-- Page Layout -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Page Header</p>\n <Container\n as=\"header\"\n class=\"rounded-lg border border-outline-variant bg-surface-container py-4\"\n >\n <div class=\"flex items-center justify-between\">\n <span class=\"font-bold text-primary\">Logo</span>\n <div class=\"flex gap-4 text-sm text-on-surface-variant\">\n <span>Home</span>\n <span>About</span>\n <span>Contact</span>\n </div>\n </div>\n </Container>\n </div>\n\n <!-- Content Section -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Content Section</p>\n <Container\n as=\"section\"\n ui={{ root: 'max-w-3xl' }}\n class=\"rounded-lg border border-outline-variant bg-surface-container py-6\"\n >\n <h3 class=\"mb-2 text-lg font-semibold\">Article Title</h3>\n <p class=\"text-sm text-on-surface-variant\">\n A narrow container is ideal for long-form content like blog posts and\n articles, keeping the line length readable and comfortable.\n </p>\n </Container>\n </div>\n\n <!-- Footer -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Footer</p>\n <Container\n as=\"footer\"\n class=\"rounded-lg border border-outline-variant bg-surface-container py-4\"\n >\n <div class=\"flex items-center justify-between text-sm text-on-surface-variant\">\n <span>&copy; 2026 Svelora</span>\n <div class=\"flex gap-4\">\n <span>Privacy</span>\n <span>Terms</span>\n </div>\n </div>\n </Container>\n </div>\n </div>\n </section>\n</div>\n",
115
116
  "resizable": "<script lang=\"ts\">\n import { Resizable } from '$lib/index.js'\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Resizable</h1>\n <p class=\"text-on-surface-variant\">\n A simple container that allows users to resize its dimensions.\n </p>\n </div>\n\n <!-- Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Usage</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Wrap your content in a <code class=\"rounded bg-surface-container-highest px-1\">Resizable</code> component. By default, it can be resized in both directions.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4 flex justify-center\">\n <Resizable direction=\"both\" class=\"min-h-32 min-w-32 h-48 w-48 rounded-lg border border-outline-variant bg-surface overflow-hidden\">\n <div class=\"flex h-full items-center justify-center p-6 text-center text-sm text-on-surface-variant\">\n Drag the bottom-right corner to resize\n </div>\n </Resizable>\n </div>\n </section>\n\n <!-- Horizontal & Vertical -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Horizontal & Vertical</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">direction</code> prop to restrict resizing to either <code class=\"rounded bg-surface-container-highest px-1\">horizontal</code> or <code class=\"rounded bg-surface-container-highest px-1\">vertical</code>.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4 flex gap-4 justify-center flex-wrap\">\n <Resizable direction=\"horizontal\" class=\"min-h-32 min-w-32 h-32 w-48 rounded-lg border border-outline-variant bg-surface overflow-hidden\">\n <div class=\"flex h-full items-center justify-center p-4 font-semibold\">\n Horizontal\n </div>\n </Resizable>\n \n <Resizable direction=\"vertical\" class=\"min-h-32 min-w-32 h-48 w-32 rounded-lg border border-outline-variant bg-surface overflow-hidden\">\n <div class=\"flex h-full items-center justify-center p-4 font-semibold\">\n Vertical\n </div>\n </Resizable>\n </div>\n </section>\n</div>\n",
117
+ "modal": "<script lang=\"ts\">\n import { Modal, Button, Badge, Icon, Separator } from '$lib/index.js'\n\n let basicOpen = $state(false)\n let fullscreenOpen = $state(false)\n let scrollableOpen = $state(false)\n let scrollableFullscreenOpen = $state(false)\n let noCloseOpen = $state(false)\n let noOverlayOpen = $state(false)\n let noTransitionOpen = $state(false)\n let nonDismissibleOpen = $state(false)\n let slotsOpen = $state(false)\n let actionsOpen = $state(false)\n let customContentOpen = $state(false)\n let callbacksOpen = $state(false)\n let callbackLog = $state<string[]>([])\n let uiOverrideOpen = $state(false)\n let programmaticOpen = $state(false)\n\n let confirmOpen = $state(false)\n let formOpen = $state(false)\n let alertOpen = $state(false)\n let imageOpen = $state(false)\n\n let sizeOpens = $state<Record<string, boolean>>({\n sm: false,\n md: false,\n lg: false,\n xl: false,\n full: false\n })\n let transitionOpens = $state<Record<string, boolean>>({\n scale: false,\n fade: false,\n slide: false,\n none: false\n })\n\n function logCallback(name: string) {\n callbackLog = [...callbackLog.slice(-4), `${new Date().toLocaleTimeString()} — ${name}`]\n }\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Modal</h1>\n <p class=\"text-on-surface-variant\">\n A modal dialog component built on bits-ui Dialog. Supports transitions, fullscreen,\n scrollable mode, dismissible control, and full slot customization.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Modal\n bind:open={basicOpen}\n title=\"Basic Modal\"\n description=\"This is a basic modal with title, description, body and footer.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open Modal\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n A centered modal dialog. Click the X, press Escape, or click outside to\n close.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button label=\"Cancel\" variant=\"outline\" onclick={() => (basicOpen = false)} />\n <Button\n label=\"Confirm\"\n variant=\"solid\"\n color=\"primary\"\n onclick={() => (basicOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Fullscreen -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Fullscreen</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Modal\n bind:open={fullscreenOpen}\n fullscreen\n title=\"Fullscreen Modal\"\n description=\"This modal takes up the entire screen.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open Fullscreen\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Covers the entire viewport. Useful for complex forms or media viewers.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (fullscreenOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Scrollable -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Scrollable</h2>\n <div class=\"flex flex-wrap gap-3 rounded-lg bg-surface-container-high p-4\">\n <Modal\n bind:open={scrollableOpen}\n scrollable\n title=\"Scrollable Modal\"\n description=\"The entire modal scrolls within the overlay.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Scrollable\" />\n {/snippet}\n {#snippet body()}\n <div class=\"space-y-3\">\n {#each Array.from({ length: 20 }, (_, i) => i) as i (i)}\n <div class=\"rounded-md bg-surface-container p-3\">\n <p class=\"text-sm text-on-surface-variant\">Content item {i + 1}</p>\n </div>\n {/each}\n </div>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (scrollableOpen = false)}\n />\n {/snippet}\n </Modal>\n\n <Modal\n bind:open={scrollableFullscreenOpen}\n scrollable\n fullscreen\n title=\"Scrollable + Fullscreen\"\n description=\"Full viewport with scrollable content.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Scrollable + Fullscreen\" />\n {/snippet}\n {#snippet body()}\n <div class=\"space-y-3\">\n {#each Array.from({ length: 30 }, (_, i) => i) as i (i)}\n <div class=\"rounded-md bg-surface-container p-3\">\n <p class=\"text-sm text-on-surface-variant\">Content item {i + 1}</p>\n </div>\n {/each}\n </div>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (scrollableFullscreenOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Options -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Options</h2>\n <div class=\"flex flex-wrap gap-3 rounded-lg bg-surface-container-high p-4\">\n <Modal\n bind:open={noTransitionOpen}\n transition={false}\n title=\"No Transition\"\n description=\"Appears instantly without animation.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"No Transition\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">Modal opens and closes without animation.</p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (noTransitionOpen = false)}\n />\n {/snippet}\n </Modal>\n\n <Modal\n bind:open={noCloseOpen}\n close={false}\n title=\"No Close Button\"\n description=\"Close button is hidden.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"No Close Button\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">Use the footer button or Escape to close.</p>\n {/snippet}\n {#snippet footer()}\n <Button label=\"Close\" variant=\"outline\" onclick={() => (noCloseOpen = false)} />\n {/snippet}\n </Modal>\n\n <Modal\n bind:open={noOverlayOpen}\n overlay={false}\n title=\"No Overlay\"\n description=\"Background is visible.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"No Overlay\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">No backdrop overlay behind the modal.</p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (noOverlayOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Non-Dismissible -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Non-Dismissible</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Modal\n bind:open={nonDismissibleOpen}\n dismissible={false}\n title=\"Non-Dismissible\"\n description=\"Must use the close button.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open (Non-Dismissible)\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Clicking outside or pressing Escape won't close this modal.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"solid\"\n color=\"primary\"\n onclick={() => (nonDismissibleOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Slots -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Slots</h2>\n <div class=\"flex flex-wrap gap-3 rounded-lg bg-surface-container-high p-4\">\n <!-- Custom header -->\n <Modal bind:open={slotsOpen}>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Custom Header\" />\n {/snippet}\n {#snippet header()}\n <div class=\"flex items-center gap-3 p-4 sm:px-6\">\n <div\n class=\"flex size-10 items-center justify-center rounded-full bg-primary text-on-primary\"\n >\n <Icon name=\"lucide:settings\" size=\"20\" />\n </div>\n <div>\n <h3 class=\"font-semibold text-on-surface\">Custom Header</h3>\n <p class=\"text-sm text-on-surface-variant\">With icon and layout</p>\n </div>\n </div>\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n The header slot replaces the default title, description, and close button.\n </p>\n {/snippet}\n {#snippet footer()}\n <div class=\"flex gap-2\">\n <Button\n label=\"Cancel\"\n variant=\"outline\"\n onclick={() => (slotsOpen = false)}\n />\n <Button\n label=\"Save\"\n variant=\"solid\"\n color=\"primary\"\n onclick={() => (slotsOpen = false)}\n />\n </div>\n {/snippet}\n </Modal>\n\n <!-- Actions slot -->\n <Modal\n bind:open={actionsOpen}\n title=\"User Profile\"\n description=\"Manage your account settings.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Actions Slot\" />\n {/snippet}\n {#snippet actions()}\n <Badge variant=\"soft\" color=\"success\" size=\"xs\" label=\"Active\" />\n <Badge variant=\"soft\" color=\"info\" size=\"xs\" label=\"Pro\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n The actions slot renders between the title/description and the close button.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button label=\"Close\" variant=\"outline\" onclick={() => (actionsOpen = false)} />\n {/snippet}\n </Modal>\n\n <!-- Full content slot -->\n <Modal bind:open={customContentOpen} title=\"Custom Content\">\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Content Slot\" />\n {/snippet}\n {#snippet content()}\n <div class=\"flex flex-col items-center gap-4 p-6\">\n <div\n class=\"flex size-16 items-center justify-center rounded-full bg-success/10\"\n >\n <Icon name=\"lucide:check-circle\" size=\"32\" class=\"text-success\" />\n </div>\n <h3 class=\"text-xl font-semibold text-on-surface\">Payment Successful</h3>\n <p class=\"text-center text-on-surface-variant\">\n The content slot replaces the entire inner layout.\n </p>\n <Button\n label=\"Done\"\n variant=\"solid\"\n color=\"primary\"\n onclick={() => (customContentOpen = false)}\n />\n </div>\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Lifecycle Callbacks -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Lifecycle Callbacks</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <div class=\"mb-3 space-y-1\">\n {#if callbackLog.length === 0}\n <p class=\"text-sm text-on-surface-variant italic\">\n Open/close the modal to see callback logs...\n </p>\n {/if}\n {#each callbackLog as log, i (i)}\n <p class=\"font-mono text-xs text-on-surface-variant\">{log}</p>\n {/each}\n </div>\n <Modal\n bind:open={callbacksOpen}\n onOpenChange={(v) => logCallback(`onOpenChange(${v})`)}\n onOpenChangeComplete={(v) => logCallback(`onOpenChangeComplete(${v})`)}\n title=\"Callback Demo\"\n description=\"Check the log above.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open (With Callbacks)\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Open, close, and watch the callback log update.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (callbacksOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Programmatic Control -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Programmatic Control</h2>\n <div class=\"flex gap-3 rounded-lg bg-surface-container-high p-4\">\n <Button\n variant=\"outline\"\n label=\"Open Programmatically\"\n onclick={() => (programmaticOpen = true)}\n />\n <Modal\n bind:open={programmaticOpen}\n title=\"Programmatic Modal\"\n description=\"Opened without a trigger slot.\"\n >\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n This modal has no trigger. It was opened by setting open = true externally.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (programmaticOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- UI Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Slot Overrides</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Modal\n bind:open={uiOverrideOpen}\n title=\"Styled Modal\"\n description=\"Custom styles via the ui prop.\"\n ui={{\n content: 'bg-primary-container',\n title: 'text-on-primary-container',\n description: 'text-on-primary-container/70',\n header: 'border-on-primary-container/10'\n }}\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open Styled Modal\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-primary-container/80\">\n This modal overrides content, title, description, and header slot classes.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (uiOverrideOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <Separator />\n\n <!-- Real World Examples -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n <div class=\"grid gap-4 sm:grid-cols-2\">\n <!-- Confirmation Dialog -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Confirmation Dialog</p>\n <Modal bind:open={confirmOpen} dismissible={false} close={false}>\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n leadingIcon=\"lucide:trash-2\"\n label=\"Delete Item\"\n color=\"error\"\n class=\"w-full\"\n />\n {/snippet}\n {#snippet content()}\n <div class=\"flex flex-col items-center gap-4 p-6 text-center\">\n <div\n class=\"flex size-14 items-center justify-center rounded-full bg-error/10\"\n >\n <Icon name=\"lucide:alert-triangle\" size=\"28\" class=\"text-error\" />\n </div>\n <h3 class=\"text-lg font-semibold text-on-surface\">Delete this item?</h3>\n <p class=\"text-sm text-on-surface-variant\">\n This action is permanent and cannot be undone.\n </p>\n <div class=\"flex w-full gap-2\">\n <Button\n label=\"Cancel\"\n variant=\"outline\"\n class=\"flex-1\"\n onclick={() => (confirmOpen = false)}\n />\n <Button\n label=\"Delete\"\n variant=\"solid\"\n color=\"error\"\n class=\"flex-1\"\n onclick={() => (confirmOpen = false)}\n />\n </div>\n </div>\n {/snippet}\n </Modal>\n </div>\n\n <!-- Form Modal -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Form Modal</p>\n <Modal\n bind:open={formOpen}\n title=\"Create Project\"\n description=\"Fill in the details to create a new project.\"\n >\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n leadingIcon=\"lucide:plus\"\n label=\"New Project\"\n class=\"w-full\"\n />\n {/snippet}\n {#snippet body()}\n <div class=\"space-y-4\">\n <div>\n <label\n for=\"project-name\"\n class=\"mb-1 block text-sm font-medium text-on-surface\"\n >Project Name</label\n >\n <input\n id=\"project-name\"\n type=\"text\"\n placeholder=\"My Project\"\n class=\"w-full rounded-md border border-outline-variant bg-surface px-3 py-2 text-sm text-on-surface placeholder:text-on-surface-variant/50 focus:border-primary focus:ring-1 focus:ring-primary focus:outline-none\"\n />\n </div>\n <div>\n <label\n for=\"project-desc\"\n class=\"mb-1 block text-sm font-medium text-on-surface\"\n >Description</label\n >\n <textarea\n id=\"project-desc\"\n rows=\"3\"\n placeholder=\"Describe your project...\"\n class=\"w-full rounded-md border border-outline-variant bg-surface px-3 py-2 text-sm text-on-surface placeholder:text-on-surface-variant/50 focus:border-primary focus:ring-1 focus:ring-primary focus:outline-none\"\n ></textarea>\n </div>\n </div>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Cancel\"\n variant=\"outline\"\n onclick={() => (formOpen = false)}\n />\n <Button\n label=\"Create\"\n variant=\"solid\"\n color=\"primary\"\n onclick={() => (formOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n\n <!-- Alert Modal -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Alert Modal</p>\n <Modal\n bind:open={alertOpen}\n title=\"Session Expired\"\n description=\"Your session has timed out due to inactivity.\"\n dismissible={false}\n >\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n leadingIcon=\"lucide:clock\"\n label=\"Session Alert\"\n class=\"w-full\"\n />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Please sign in again to continue using the application.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Sign In\"\n variant=\"solid\"\n color=\"primary\"\n class=\"w-full\"\n onclick={() => (alertOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n\n <!-- Image Preview -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Image Preview</p>\n <Modal bind:open={imageOpen} close={{ color: 'surface', size: 'md' }}>\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n leadingIcon=\"lucide:image\"\n label=\"View Image\"\n class=\"w-full\"\n />\n {/snippet}\n {#snippet content()}\n <div class=\"p-2\">\n <img\n src=\"https://picsum.photos/800/600\"\n alt=\"Preview\"\n class=\"w-full rounded-md\"\n />\n <p class=\"mt-2 text-center text-sm text-on-surface-variant\">\n Photo from Picsum\n </p>\n </div>\n {/snippet}\n </Modal>\n </div>\n </div>\n </section>\n\n <Separator />\n\n <section>\n <h2 class=\"mb-3 text-lg font-semibold\">Size</h2>\n <p class=\"mb-4 text-sm text-on-surface-variant\">\n Use <code>size</code> to control the modal width: <code>sm</code> /\n <code>md</code> (default) / <code>lg</code> / <code>xl</code> /\n <code>full</code>. The legacy <code>fullscreen</code> prop is kept as an alias for\n <code>size=\"full\"</code>.\n </p>\n <div class=\"flex flex-wrap gap-2\">\n {#each ['sm', 'md', 'lg', 'xl', 'full'] as const as s (s)}\n <Modal\n bind:open={sizeOpens[s]}\n size={s}\n title={`Size: ${s}`}\n description=\"Resize your browser to see how the modal width scales.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label={`size=\"${s}\"`} />\n {/snippet}\n {#snippet body()}\n <p class=\"text-sm text-on-surface-variant\">\n Current size is <code>{s}</code>.\n </p>\n {/snippet}\n </Modal>\n {/each}\n </div>\n </section>\n\n <Separator />\n\n <section>\n <h2 class=\"mb-3 text-lg font-semibold\">Transition</h2>\n <p class=\"mb-4 text-sm text-on-surface-variant\">\n Pick how the modal animates in and out. Default is <code>scale</code>; pass\n <code>fade</code>, <code>slide</code>, or <code>none</code> to override. Boolean\n <code>true</code> / <code>false</code> still work as legacy aliases.\n </p>\n <div class=\"flex flex-wrap gap-2\">\n {#each ['scale', 'fade', 'slide', 'none'] as const as t (t)}\n <Modal\n bind:open={transitionOpens[t]}\n transition={t}\n title={`Transition: ${t}`}\n description=\"Open and close to see the animation.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label={`transition=\"${t}\"`} />\n {/snippet}\n </Modal>\n {/each}\n </div>\n </section>\n</div>\n",
118
+ "navigation-menu": "<script lang=\"ts\">\n import { NavigationMenu, Separator } from '$lib/index.js'\n import type { NavigationMenuItemType } from '$lib/index.js'\n\n // --- Basic Navbar (1D Array) ---\n const basicLinks: NavigationMenuItemType[] = [\n { label: 'Home', href: '/', icon: 'lucide:home', active: true },\n { label: 'Components', href: '/docs/components/button', icon: 'lucide:box' },\n { label: 'Changelog', href: '/changelog', badge: 'v3.0.7', badgeColor: 'info' }\n ]\n\n // --- Unified Navbar (2D Array) ---\n const unifiedLinks: NavigationMenuItemType[][] = [\n [\n { label: 'Dashboard', icon: 'lucide:layout-dashboard', href: '/dashboard' },\n {\n label: 'Products',\n icon: 'lucide:shopping-bag',\n items: [\n { type: 'item', label: 'All Products', icon: 'lucide:package' },\n { type: 'item', label: 'Categories', icon: 'lucide:tags' },\n { type: 'separator' },\n { type: 'item', label: 'Add New Product', icon: 'lucide:plus', kbds: ['meta', 'P'] }\n ]\n }\n ],\n [\n { label: 'GitHub', icon: 'simple-icons:github', href: 'https://github.com/asphum/svelora', target: '_blank', badge: 'v3' },\n {\n label: 'Settings',\n icon: 'lucide:settings',\n items: [\n { type: 'item', label: 'Profile', icon: 'lucide:user' },\n { type: 'item', label: 'Preferences', icon: 'lucide:sliders' }\n ]\n }\n ]\n ]\n\n // --- Vertical Sidebar Links ---\n const sidebarLinks: NavigationMenuItemType[] = [\n { label: 'Overview', icon: 'lucide:layout-dashboard', href: '/dashboard' },\n {\n label: 'Analytics',\n icon: 'lucide:bar-chart-2',\n defaultOpen: true,\n items: [\n { type: 'item', label: 'Reports', icon: 'lucide:file-text' },\n { type: 'item', label: 'Traffic', icon: 'lucide:activity' }\n ]\n },\n {\n label: 'Settings',\n icon: 'lucide:settings',\n items: [\n { type: 'item', label: 'Profile', icon: 'lucide:user' },\n { type: 'item', label: 'Billing', icon: 'lucide:credit-card' }\n ]\n }\n ]\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Navigation Menu</h1>\n <p class=\"text-on-surface-variant\">\n A unified navigation component that supports both horizontal and vertical orientations.\n </p>\n </div>\n\n <!-- Basic Navbar -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic Navigation</h2>\n <p class=\"text-sm text-on-surface-variant\">\n A simple 1D list of links. Use the <code class=\"rounded bg-surface-container-highest px-1\">items</code> prop to define your navigation.\n </p>\n <div class=\"rounded-lg border border-outline-variant bg-surface-container-lowest p-6 flex flex-col gap-4\">\n <div class=\"w-full bg-surface border border-outline-variant rounded-xl shadow-sm px-4 py-2 flex items-center justify-between\">\n <span class=\"font-bold text-lg mr-8\">Brand</span>\n <NavigationMenu items={basicLinks} class=\"flex-1\" />\n </div>\n </div>\n </section>\n\n <Separator />\n\n <!-- 2D Array Grouping -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Grouping (2D Arrays)</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Pass a 2D array (<code class=\"rounded bg-surface-container-highest px-1\">items=[ [leftItems], [rightItems] ]</code>) to easily group links on opposite sides of the navbar.\n </p>\n <div class=\"rounded-lg border border-outline-variant bg-surface-container-lowest p-6\">\n <div class=\"w-full bg-surface border border-outline-variant rounded-xl shadow-sm px-4 py-2 flex items-center\">\n <NavigationMenu items={unifiedLinks} />\n </div>\n </div>\n </section>\n\n <Separator />\n\n <!-- Vertical Orientation (Accordion) -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Vertical (Sidebar & Accordion)</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Set <code class=\"rounded bg-surface-container-highest px-1\">orientation=\"vertical\"</code> to render as a sidebar menu. Nested sub-menus will automatically render as smoothly expanding accordions! Add <code class=\"rounded bg-surface-container-highest px-1\">accordion=\"true\"</code> to restrict opening to one group at a time.\n </p>\n <div class=\"rounded-lg border border-outline-variant bg-surface-container-lowest p-6 flex gap-8\">\n <div class=\"w-64 bg-surface border border-outline-variant rounded-xl shadow-sm p-3 flex flex-col items-start\">\n <p class=\"text-xs font-semibold text-on-surface-variant px-3 mb-2 uppercase tracking-wider\">Multi-Open</p>\n <NavigationMenu items={sidebarLinks} orientation=\"vertical\" variant=\"ghost\" />\n </div>\n \n <div class=\"w-64 bg-surface border border-outline-variant rounded-xl shadow-sm p-3 flex flex-col items-start\">\n <p class=\"text-xs font-semibold text-on-surface-variant px-3 mb-2 uppercase tracking-wider\">Strict Accordion</p>\n <NavigationMenu items={sidebarLinks} orientation=\"vertical\" variant=\"ghost\" accordion />\n </div>\n </div>\n </section>\n</div>\n",
116
119
  "scroll-area": "<script lang=\"ts\">\n import { ScrollArea, Separator } from '$lib/index.js'\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">ScrollArea</h1>\n <p class=\"text-on-surface-variant\">\n Augments native scroll functionality for custom, cross-browser styling.\n </p>\n </div>\n\n <!-- Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Usage</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Wrap any content in a <code class=\"rounded bg-surface-container-highest px-1\">ScrollArea</code> and provide it with a fixed height.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4 flex justify-center\">\n <ScrollArea class=\"h-72 w-full max-w-sm rounded-lg border border-outline-variant bg-surface p-4\">\n <div class=\"space-y-4\">\n <h4 class=\"text-sm font-semibold\">Svelora Components</h4>\n <Separator />\n {#each Array(50) as _, i}\n <div class=\"text-sm text-on-surface-variant\">Component {i + 1}</div>\n {#if i !== 49}\n <Separator />\n {/if}\n {/each}\n </div>\n </ScrollArea>\n </div>\n </section>\n\n <!-- Horizontal -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Horizontal Scrolling</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Set <code class=\"rounded bg-surface-container-highest px-1\">orientation=\"horizontal\"</code> or <code class=\"rounded bg-surface-container-highest px-1\">orientation=\"both\"</code> to enable horizontal scrollbars.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4 flex justify-center\">\n <ScrollArea orientation=\"horizontal\" class=\"w-full max-w-lg rounded-lg border border-outline-variant bg-surface p-4 whitespace-nowrap\">\n <div class=\"flex gap-4\">\n {#each Array(10) as _, i}\n <div class=\"h-32 w-32 shrink-0 rounded-md bg-surface-container-highest flex items-center justify-center font-bold text-on-surface-variant\">\n Item {i + 1}\n </div>\n {/each}\n </div>\n </ScrollArea>\n </div>\n </section>\n</div>\n",
120
+ "search": "<script lang=\"ts\">\n import { Search, Separator, CodeBlock, Badge } from '$lib/index.js'\n import type { CommandGroup } from '$lib/index.js'\n import { quickExample } from './quick-example.js'\n\n const searchGroups: CommandGroup[] = [\n {\n id: 'pages',\n label: 'Pages',\n items: [\n { value: 'home', label: 'Home', icon: 'lucide:home', keywords: ['start', 'main'] },\n { value: 'dashboard', label: 'Dashboard', icon: 'lucide:layout-dashboard' },\n { value: 'settings', label: 'Settings', icon: 'lucide:settings', keywords: ['preferences', 'options'] }\n ]\n },\n {\n id: 'actions',\n label: 'Actions',\n items: [\n { value: 'new-file', label: 'New File', icon: 'lucide:file-plus' },\n { value: 'invite', label: 'Invite Users', icon: 'lucide:user-plus' }\n ]\n }\n ]\n\n let selectedValue = $state<string | null>(null)\n let inputValue = $state('')\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Search</h1>\n <p class=\"text-on-surface-variant\">\n A flexible search component that can act as a standard input, an icon button, or a global command palette modal (⌘K).\n </p>\n </div>\n\n <!-- Quick Example -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Quick Start</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">variant=\"modal\"</code> to create a \"fake\" input that triggers a global search modal. This is the modern best practice for application search.\n </p>\n <div class=\"rounded-lg border border-outline-variant bg-surface-container-lowest p-6 flex flex-col items-center gap-6\">\n <div class=\"w-full max-w-sm\">\n <Search \n variant=\"modal\" \n groups={searchGroups} \n kbd={['meta', 'K']} \n placeholder=\"Search documentation...\" \n onSelect={(val) => selectedValue = val}\n />\n </div>\n {#if selectedValue}\n <div class=\"flex items-center gap-2\">\n <span class=\"text-sm text-on-surface-variant\">You selected:</span>\n <Badge color=\"success\" label={selectedValue} />\n </div>\n {/if}\n </div>\n <CodeBlock code={quickExample} />\n </section>\n\n <Separator />\n\n <!-- Variant: Input -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Standard Input</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">variant=\"input\"</code> (default) for a standard text input. You can still pass <code class=\"rounded bg-surface-container-highest px-1\">kbd</code> to show a keyboard shortcut visual.\n </p>\n <div class=\"rounded-lg border border-outline-variant bg-surface-container-lowest p-6 flex flex-col items-center gap-4\">\n <div class=\"w-full max-w-sm\">\n <Search \n variant=\"input\" \n bind:value={inputValue}\n placeholder=\"Search standard input...\" \n kbd={['/']}\n />\n </div>\n <p class=\"text-sm text-on-surface-variant\">Value: {inputValue || 'empty'}</p>\n </div>\n </section>\n\n <Separator />\n\n <!-- Variant: Button -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Icon Button</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">variant=\"button\"</code> for an icon-only trigger that opens the command modal. Great for mobile navbars.\n </p>\n <div class=\"rounded-lg border border-outline-variant bg-surface-container-lowest p-6 flex justify-center\">\n <div class=\"flex items-center gap-4 bg-surface px-4 py-2 rounded-full border border-outline-variant shadow-sm\">\n <span class=\"font-bold text-lg\">My App</span>\n <div class=\"flex-1\"></div>\n <Search \n variant=\"button\" \n groups={searchGroups} \n />\n </div>\n </div>\n </section>\n</div>\n",
117
121
  "separator": "<script lang=\"ts\">\n import { Separator, Button } from '$lib/index.js'\n\n const colors = [\n 'surface',\n 'primary',\n 'secondary',\n 'tertiary',\n 'success',\n 'warning',\n 'error',\n 'info'\n ] as const\n const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const\n const types = ['solid', 'dashed', 'dotted'] as const\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Separator</h1>\n <p class=\"text-on-surface-variant\">\n Visual divider for separating content with optional label, icon, or avatar.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p>Content above</p>\n <Separator class=\"my-4\" />\n <p>Content below</p>\n </div>\n </section>\n\n <!-- Colors -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Colors</h2>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n {#each colors as color (color)}\n <Separator {color} label={color} />\n {/each}\n </div>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n {#each sizes as size (size)}\n <Separator {size} color=\"primary\" label={size} />\n {/each}\n </div>\n </section>\n\n <!-- Types -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Types</h2>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n {#each types as type (type)}\n <Separator {type} size=\"sm\" color=\"primary\" label={type} />\n {/each}\n </div>\n </section>\n\n <!-- With Label -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">With Label</h2>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n <Separator label=\"OR\" color=\"primary\" />\n <Separator label=\"Continue reading\" color=\"secondary\" size=\"sm\" />\n <Separator label=\"Section break\" color=\"tertiary\" type=\"dashed\" />\n </div>\n </section>\n\n <!-- With Icon -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">With Icon</h2>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n <Separator icon=\"lucide:star\" color=\"warning\" size=\"sm\" />\n <Separator icon=\"lucide:heart\" color=\"error\" size=\"md\" />\n <Separator icon=\"lucide:zap\" color=\"primary\" size=\"lg\" />\n </div>\n </section>\n\n <!-- With Avatar -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">With Avatar</h2>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs text-on-surface-variant\">Default avatarSize (2xs from config)</p>\n <Separator\n avatar={{ src: 'https://i.pravatar.cc/150?img=1', alt: 'Default size' }}\n color=\"primary\"\n />\n <p class=\"text-xs text-on-surface-variant\">Avatar with explicit size override (sm)</p>\n <Separator\n avatar={{ src: 'https://i.pravatar.cc/150?img=2', alt: 'Size sm', size: 'sm' }}\n color=\"secondary\"\n />\n <p class=\"text-xs text-on-surface-variant\">Avatar with explicit size override (md)</p>\n <Separator\n avatar={{ src: 'https://i.pravatar.cc/150?img=3', alt: 'Size md', size: 'md' }}\n color=\"tertiary\"\n />\n </div>\n </section>\n\n <!-- With Custom Content -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Content</h2>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n <Separator color=\"primary\">\n {#snippet content()}\n <Button size=\"sm\" variant=\"soft\" color=\"primary\">Load more</Button>\n {/snippet}\n </Separator>\n <Separator color=\"secondary\">\n {#snippet content()}\n <span\n class=\"rounded-full bg-secondary-container px-3 py-1 text-xs text-on-secondary-container\"\n >\n New messages\n </span>\n {/snippet}\n </Separator>\n </div>\n </section>\n\n <!-- Vertical Orientation -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Vertical Orientation</h2>\n <div class=\"flex h-24 items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <span>Left</span>\n <Separator orientation=\"vertical\" />\n <span>Center</span>\n <Separator orientation=\"vertical\" color=\"primary\" />\n <span>Right</span>\n </div>\n <div class=\"flex h-32 items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <span>Item 1</span>\n <Separator orientation=\"vertical\" color=\"primary\" label=\"OR\" size=\"sm\" />\n <span>Item 2</span>\n <Separator orientation=\"vertical\" color=\"secondary\" icon=\"lucide:plus\" size=\"sm\" />\n <span>Item 3</span>\n </div>\n </section>\n\n <!-- Color x Size Matrix -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Colors × Sizes</h2>\n <div class=\"overflow-x-auto\">\n <table class=\"w-full\">\n <thead>\n <tr class=\"border-b border-outline-variant\">\n <th class=\"px-3 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >Color</th\n >\n {#each sizes as size (size)}\n <th\n class=\"px-3 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >{size}</th\n >\n {/each}\n </tr>\n </thead>\n <tbody>\n {#each colors as color (color)}\n <tr class=\"border-b border-outline-variant/50\">\n <td\n class=\"px-3 py-3 text-sm font-medium text-on-surface-variant capitalize\"\n >{color}</td\n >\n {#each sizes as size (size)}\n <td class=\"px-3 py-3\">\n <div class=\"w-24\">\n <Separator {color} {size} />\n </div>\n </td>\n {/each}\n </tr>\n {/each}\n </tbody>\n </table>\n </div>\n </section>\n\n <!-- Real World Examples -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n <div class=\"space-y-6 rounded-lg bg-surface-container-high p-4\">\n <!-- Login Form Divider -->\n <div>\n <p class=\"mb-3 text-sm font-medium text-on-surface-variant\">Login Form</p>\n <div class=\"mx-auto max-w-sm space-y-4 rounded-lg bg-surface p-4\">\n <Button block variant=\"outline\">Continue with Google</Button>\n <Separator label=\"or continue with email\" size=\"sm\" />\n <Button block>Sign in</Button>\n </div>\n </div>\n\n <!-- Card Sections -->\n <div>\n <p class=\"mb-3 text-sm font-medium text-on-surface-variant\">Card Sections</p>\n <div class=\"mx-auto max-w-sm rounded-lg bg-surface p-4\">\n <h3 class=\"font-semibold\">Order Summary</h3>\n <p class=\"text-sm text-on-surface-variant\">2 items</p>\n <Separator class=\"my-3\" />\n <div class=\"flex justify-between text-sm\">\n <span>Subtotal</span>\n <span>$99.00</span>\n </div>\n <div class=\"flex justify-between text-sm\">\n <span>Shipping</span>\n <span>$5.00</span>\n </div>\n <Separator class=\"my-3\" type=\"dashed\" />\n <div class=\"flex justify-between font-semibold\">\n <span>Total</span>\n <span>$104.00</span>\n </div>\n </div>\n </div>\n\n <!-- Timeline -->\n <div>\n <p class=\"mb-3 text-sm font-medium text-on-surface-variant\">Timeline</p>\n <div class=\"mx-auto max-w-sm space-y-2\">\n <div class=\"flex items-center gap-3\">\n <div class=\"size-2 rounded-full bg-success\"></div>\n <span class=\"text-sm\">Order placed</span>\n <span class=\"ml-auto text-xs text-on-surface-variant\">Today</span>\n </div>\n <Separator color=\"success\" size=\"xs\" class=\"ml-1\" />\n <div class=\"flex items-center gap-3\">\n <div class=\"size-2 rounded-full bg-success\"></div>\n <span class=\"text-sm\">Processing</span>\n <span class=\"ml-auto text-xs text-on-surface-variant\">Today</span>\n </div>\n <Separator color=\"primary\" size=\"xs\" type=\"dashed\" class=\"ml-1\" />\n <div class=\"flex items-center gap-3\">\n <div class=\"size-2 rounded-full bg-outline-variant\"></div>\n <span class=\"text-sm text-on-surface-variant\">Shipped</span>\n <span class=\"ml-auto text-xs text-on-surface-variant\">Pending</span>\n </div>\n </div>\n </div>\n </div>\n </section>\n\n <!-- UI Slot Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Slot Overrides</h2>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n <Separator\n label=\"Custom label style\"\n color=\"primary\"\n ui={{ label: 'font-bold uppercase tracking-wider text-xs' }}\n />\n <Separator\n icon=\"lucide:sparkles\"\n color=\"warning\"\n size=\"md\"\n ui={{ icon: 'animate-pulse' }}\n />\n <Separator\n label=\"Gradient border\"\n ui={{\n border: 'bg-gradient-to-r from-primary via-secondary to-tertiary h-0.5 border-none'\n }}\n />\n </div>\n </section>\n\n <!-- Position -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Position</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">position</code> prop to\n place the label/icon/avatar at the start, center, or end. Defaults to\n <code class=\"rounded bg-surface-container-highest px-1\">center</code>.\n </p>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n <Separator label=\"Start\" position=\"start\" />\n <Separator label=\"Center\" position=\"center\" />\n <Separator label=\"End\" position=\"end\" />\n </div>\n </section>\n</div>\n",
118
122
  "accordion": "<script lang=\"ts\">\n import { Accordion, Button, Badge, Icon, Separator } from '$lib/index.js'\n import type { AccordionItem } from '$lib/index.js'\n\n // --- Basic items ---\n const basicItems: AccordionItem[] = [\n {\n label: 'What is Svelte?',\n content:\n 'Svelte is a modern JavaScript compiler that generates highly efficient vanilla JavaScript at build time, resulting in faster runtime performance and smaller bundle sizes.'\n },\n {\n label: 'Why use SvelteKit?',\n content:\n 'SvelteKit is the official framework for building Svelte apps. It provides routing, server-side rendering, code splitting, and other production-ready features out of the box.'\n },\n {\n label: 'How does reactivity work?',\n content:\n 'Svelte uses a compile-time approach to reactivity. Variables declared with let are automatically reactive, and the compiler generates efficient update code.'\n }\n ]\n\n // --- Items with icons ---\n const iconItems: AccordionItem[] = [\n {\n label: 'Account Settings',\n icon: 'lucide:user',\n content:\n 'Manage your profile information, email preferences, and account security settings.'\n },\n {\n label: 'Notifications',\n icon: 'lucide:bell',\n content:\n 'Configure push notifications, email alerts, and in-app notification preferences.'\n },\n {\n label: 'Privacy & Security',\n icon: 'lucide:shield',\n content:\n 'Control your privacy settings, two-factor authentication, and data sharing preferences.'\n }\n ]\n\n // --- Disabled items ---\n const disabledItems: AccordionItem[] = [\n { label: 'Available Feature', content: 'This feature is available for all users.' },\n {\n label: 'Premium Feature',\n content: 'This feature requires a premium subscription.',\n disabled: true\n },\n { label: 'Another Feature', content: 'This feature is also available.' }\n ]\n\n // --- Custom trailing icons ---\n const trailingItems: AccordionItem[] = [\n { label: 'Add Item', content: 'Click to add a new item.', trailingIcon: 'lucide:plus' },\n { label: 'Edit Item', content: 'Click to edit this item.', trailingIcon: 'lucide:pencil' },\n {\n label: 'Delete Item',\n content: 'Click to delete this item.',\n trailingIcon: 'lucide:trash-2'\n }\n ]\n\n // --- Controlled value ---\n let singleValue = $state<string>('0')\n let multipleValue = $state<string[]>(['0', '2'])\n\n // --- Callback demo ---\n let lastChange = $state<string>('')\n\n // --- FAQ items ---\n const faqItems: AccordionItem[] = [\n {\n label: 'How do I reset my password?',\n content:\n 'Click on \"Forgot Password\" on the login page, enter your email address, and follow the instructions sent to your inbox.'\n },\n {\n label: 'Can I change my username?',\n content:\n 'Yes, you can change your username once every 30 days from Account Settings > Profile > Edit Username.'\n },\n {\n label: 'What payment methods are accepted?',\n content:\n 'We accept all major credit cards (Visa, MasterCard, American Express), PayPal, and bank transfers for annual plans.'\n },\n {\n label: 'How do I cancel my subscription?',\n content:\n 'Go to Account Settings > Billing > Cancel Subscription. Your access will continue until the end of your current billing period.'\n },\n {\n label: 'Is my data secure?',\n content:\n 'Yes, we use industry-standard encryption (AES-256) and follow SOC 2 compliance guidelines to protect your data.'\n }\n ]\n\n // --- Slot demo items ---\n const slotItems: AccordionItem[] = [\n {\n label: 'Pro Plan',\n content: 'Access all features with priority support.',\n value: 'pro'\n },\n {\n label: 'Enterprise Plan',\n content: 'Custom solutions with dedicated account manager.',\n value: 'enterprise'\n },\n {\n label: 'Free Plan',\n content: 'Basic features for personal use.',\n value: 'free'\n }\n ]\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Accordion</h1>\n <p class=\"text-on-surface-variant\">\n A vertically stacked set of interactive headings that reveal or hide associated content.\n Built on top of bits-ui Accordion.\n </p>\n </div>\n\n <!-- ==================== BASIC ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic Usage</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Pass an array of items with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">label</code\n >\n and\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">content</code> properties.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Accordion items={basicItems} />\n </div>\n </section>\n\n <!-- ==================== SINGLE VS MULTIPLE ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Single vs Multiple</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >type=\"single\"</code\n >\n to allow only one item open at a time, or\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >type=\"multiple\"</code\n >\n for multiple.\n </p>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Single (default)</p>\n <Accordion type=\"single\" items={basicItems} />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Multiple</p>\n <Accordion type=\"multiple\" items={basicItems} />\n </div>\n </div>\n </section>\n\n <!-- ==================== ICONS ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">With Icons</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Add leading icons via the <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">icon</code\n >\n property on each item.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Accordion type=\"single\" items={iconItems} />\n </div>\n </section>\n\n <!-- ==================== TRAILING ICON ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Trailing Icon</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Override the default chevron with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >trailingIcon</code\n >\n globally or per-item.\n </p>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Global trailing icon</p>\n <Accordion type=\"single\" items={basicItems} trailingIcon=\"lucide:plus\" />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Per-item trailing icons</p>\n <Accordion type=\"single\" items={trailingItems} />\n </div>\n </div>\n </section>\n\n <!-- ==================== DISABLED ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Disabled State</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Disable the entire accordion or individual items.\n </p>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Entire accordion disabled</p>\n <Accordion type=\"single\" items={basicItems} disabled />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Individual item disabled</p>\n <Accordion type=\"single\" items={disabledItems} />\n </div>\n </div>\n </section>\n\n <!-- ==================== CONTROLLED ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Controlled Value</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Bind the <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >value</code\n >\n prop to control which items are open.\n </p>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">\n Single mode: <Badge variant=\"soft\" color=\"info\" label=\"value={singleValue}\" />\n </p>\n <div class=\"mb-3 flex gap-2\">\n <Button\n size=\"xs\"\n variant={singleValue === '0' ? 'solid' : 'outline'}\n label=\"Item 1\"\n onclick={() => (singleValue = '0')}\n />\n <Button\n size=\"xs\"\n variant={singleValue === '1' ? 'solid' : 'outline'}\n label=\"Item 2\"\n onclick={() => (singleValue = '1')}\n />\n <Button\n size=\"xs\"\n variant={singleValue === '2' ? 'solid' : 'outline'}\n label=\"Item 3\"\n onclick={() => (singleValue = '2')}\n />\n </div>\n <Accordion type=\"single\" items={basicItems} bind:value={singleValue} />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">\n Multiple mode: <Badge\n variant=\"soft\"\n color=\"info\"\n label=\"value=[{multipleValue.join(',')}]\"\n />\n </p>\n <div class=\"mb-3 flex gap-2\">\n <Button\n size=\"xs\"\n variant={multipleValue.includes('0') ? 'solid' : 'outline'}\n label=\"Item 1\"\n onclick={() =>\n (multipleValue = multipleValue.includes('0')\n ? multipleValue.filter((v) => v !== '0')\n : [...multipleValue, '0'])}\n />\n <Button\n size=\"xs\"\n variant={multipleValue.includes('1') ? 'solid' : 'outline'}\n label=\"Item 2\"\n onclick={() =>\n (multipleValue = multipleValue.includes('1')\n ? multipleValue.filter((v) => v !== '1')\n : [...multipleValue, '1'])}\n />\n <Button\n size=\"xs\"\n variant={multipleValue.includes('2') ? 'solid' : 'outline'}\n label=\"Item 3\"\n onclick={() =>\n (multipleValue = multipleValue.includes('2')\n ? multipleValue.filter((v) => v !== '2')\n : [...multipleValue, '2'])}\n />\n </div>\n <Accordion type=\"multiple\" items={basicItems} bind:value={multipleValue} />\n </div>\n </div>\n </section>\n\n <!-- ==================== CALLBACK ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Value Change Callback</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >onValueChange</code\n >\n to react to value changes.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm\">\n Last change: <Badge\n variant=\"soft\"\n color={lastChange ? 'success' : 'surface'}\n label={lastChange || 'None'}\n />\n </p>\n <Accordion\n type=\"single\"\n items={basicItems}\n onValueChange={(v) => (lastChange = v ? `Opened: ${v}` : 'Closed')}\n />\n </div>\n </section>\n\n <!-- ==================== CUSTOM VALUES ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Item Values</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Assign custom <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >value</code\n >\n to items instead of using index.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Accordion\n type=\"single\"\n items={[\n { label: 'Introduction', content: 'Welcome to the guide.', value: 'intro' },\n {\n label: 'Getting Started',\n content: \"Let's begin with the basics.\",\n value: 'start'\n },\n {\n label: 'Advanced Topics',\n content: 'Deep dive into advanced features.',\n value: 'advanced'\n }\n ]}\n value=\"start\"\n />\n </div>\n </section>\n\n <!-- ==================== LOOP ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Keyboard Navigation (Loop)</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Set <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">loop</code> to\n cycle keyboard focus at boundaries.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm text-on-surface-variant\">\n Use ↑↓ arrow keys to navigate. Focus cycles from last to first (and vice versa).\n </p>\n <Accordion type=\"single\" items={basicItems} loop />\n </div>\n </section>\n\n <!-- ==================== ORIENTATION ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Orientation</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Set <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >orientation</code\n >\n for keyboard navigation direction. Use ←→ for horizontal, ↑↓ for vertical.\n </p>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Vertical (default) - ↑↓ keys</p>\n <Accordion type=\"single\" items={basicItems} orientation=\"vertical\" />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Horizontal - ←→ keys</p>\n <Accordion type=\"single\" items={basicItems} orientation=\"horizontal\" />\n </div>\n </div>\n </section>\n\n <!-- ==================== FORCE MOUNT ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Force Mount</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >forceMount</code\n >\n to keep content in the DOM even when collapsed. Useful for SEO or preserving form state.\n </p>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Default (unmount on close)</p>\n <p class=\"mb-3 text-xs text-on-surface-variant\">\n Content is removed from DOM when closed\n </p>\n <Accordion type=\"single\" items={basicItems} />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Force mount enabled</p>\n <p class=\"mb-3 text-xs text-on-surface-variant\">\n Content stays in DOM (inspect element)\n </p>\n <Accordion type=\"single\" items={basicItems} forceMount />\n </div>\n </div>\n </section>\n\n <Separator />\n\n <!-- ==================== SLOTS ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Slots</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use snippets for custom rendering: <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">leading</code\n >,\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">label</code>,\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">trailing</code\n >,\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">content</code>,\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">body</code>.\n </p>\n\n <div class=\"grid gap-4 lg:grid-cols-2\">\n <!-- Leading slot -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Custom leading</p>\n <Accordion type=\"single\" items={slotItems}>\n {#snippet leading({ open })}\n <div\n class=\"flex size-8 items-center justify-center rounded-full {open\n ? 'bg-primary text-on-primary'\n : 'bg-surface-container-highest'}\"\n >\n <Icon name={open ? 'lucide:check' : 'lucide:star'} size=\"16\" />\n </div>\n {/snippet}\n </Accordion>\n </div>\n\n <!-- Label slot -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Custom label</p>\n <Accordion type=\"single\" items={slotItems}>\n {#snippet label({ item, open })}\n <span class=\"flex items-center gap-2\">\n {item.label}\n {#if item.value === 'pro'}\n <Badge size=\"xs\" variant=\"soft\" color=\"primary\" label=\"Popular\" />\n {/if}\n {#if open}\n <Icon name=\"lucide:eye\" size=\"14\" class=\"text-on-surface-variant\" />\n {/if}\n </span>\n {/snippet}\n </Accordion>\n </div>\n\n <!-- Trailing slot -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Custom trailing</p>\n <Accordion type=\"single\" items={slotItems}>\n {#snippet trailing({ item, open })}\n <div class=\"flex items-center gap-2\">\n {#if item.value === 'enterprise'}\n <Badge\n size=\"xs\"\n variant=\"outline\"\n color=\"warning\"\n label=\"Contact us\"\n />\n {/if}\n <Icon\n name={open ? 'lucide:minus' : 'lucide:plus'}\n size=\"18\"\n class=\"transition-transform\"\n />\n </div>\n {/snippet}\n </Accordion>\n </div>\n\n <!-- Body slot -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Custom body</p>\n <Accordion type=\"single\" items={slotItems}>\n {#snippet body({ item })}\n <div class=\"flex items-start gap-3\">\n <Icon\n name=\"lucide:info\"\n size=\"18\"\n class=\"mt-0.5 shrink-0 text-primary\"\n />\n <div>\n <p class=\"text-sm\">{item.content}</p>\n <Button\n size=\"xs\"\n variant=\"link\"\n label=\"Learn more\"\n class=\"mt-2 h-auto p-0\"\n />\n </div>\n </div>\n {/snippet}\n </Accordion>\n </div>\n </div>\n\n <!-- Content slot (full custom) -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Custom content (full control)</p>\n <Accordion type=\"single\" items={slotItems}>\n {#snippet content({ item })}\n <div class=\"rounded-lg bg-surface-container p-4\">\n <div class=\"flex items-center gap-3\">\n <div\n class=\"flex size-10 items-center justify-center rounded-full bg-primary/10 text-primary\"\n >\n <Icon name=\"lucide:package\" size=\"20\" />\n </div>\n <div class=\"flex-1\">\n <p class=\"font-medium\">{item.label}</p>\n <p class=\"text-sm text-on-surface-variant\">{item.content}</p>\n </div>\n <Button size=\"sm\" variant=\"solid\" label=\"Select\" />\n </div>\n </div>\n {/snippet}\n </Accordion>\n </div>\n </section>\n\n <Separator />\n\n <!-- ==================== UI OVERRIDES ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Prop (Style Overrides)</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Override slot styles via the <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">ui</code\n >\n prop. Available slots: root, item, header, trigger, content, body, label, leadingIcon, trailingIcon.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Accordion\n type=\"single\"\n items={basicItems}\n ui={{\n root: 'divide-y divide-outline',\n item: 'border-none',\n trigger: 'py-4 hover:bg-surface-container rounded-lg px-3 -mx-3',\n label: 'text-primary font-semibold',\n body: 'px-3 text-on-surface-variant'\n }}\n />\n </div>\n </section>\n\n <!-- ==================== ITEM UI OVERRIDES ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Per-Item Style Overrides</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Each item can have its own <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">ui</code\n >\n and\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">class</code> overrides.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Accordion\n type=\"single\"\n items={[\n { label: 'Normal Item', content: 'Standard styling.' },\n {\n label: 'Highlighted Item',\n content: 'This item has custom styling.',\n class: 'bg-primary/5 rounded-lg',\n ui: { trigger: 'text-primary', label: 'font-bold' }\n },\n {\n label: 'Warning Item',\n content: 'This item indicates a warning.',\n class: 'bg-warning/5 rounded-lg',\n ui: { trigger: 'text-warning', trailingIcon: 'text-warning' }\n },\n { label: 'Another Normal', content: 'Standard styling again.' }\n ]}\n />\n </div>\n </section>\n\n <Separator />\n\n <!-- ==================== REAL WORLD EXAMPLE: FAQ ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World Example: FAQ</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <div class=\"mb-4 flex items-center gap-3\">\n <div class=\"flex size-10 items-center justify-center rounded-full bg-primary/10\">\n <Icon name=\"lucide:help-circle\" size=\"20\" class=\"text-primary\" />\n </div>\n <div>\n <h3 class=\"font-semibold text-on-surface\">Frequently Asked Questions</h3>\n <p class=\"text-sm text-on-surface-variant\">Find answers to common questions</p>\n </div>\n </div>\n <Accordion\n type=\"single\"\n items={faqItems}\n ui={{\n item: 'border-outline-variant/50',\n trigger: 'py-4',\n label: 'text-on-surface',\n body: 'text-on-surface-variant leading-relaxed'\n }}\n />\n </div>\n </section>\n\n <!-- ==================== REAL WORLD EXAMPLE: SETTINGS ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World Example: Settings Sections</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Accordion\n type=\"multiple\"\n items={[\n {\n label: 'General Settings',\n icon: 'lucide:settings-2',\n content: 'Configure language, timezone, and display preferences.',\n value: 'general'\n },\n {\n label: 'Notification Preferences',\n icon: 'lucide:bell-ring',\n content: 'Manage email, push, and SMS notification settings.',\n value: 'notifications'\n },\n {\n label: 'Security & Privacy',\n icon: 'lucide:lock',\n content: 'Set up two-factor authentication and manage privacy controls.',\n value: 'security'\n },\n {\n label: 'Billing & Subscription',\n icon: 'lucide:credit-card',\n content: 'View invoices, update payment methods, and manage your plan.',\n value: 'billing'\n }\n ]}\n value={['general']}\n ui={{\n item: 'bg-surface-container rounded-lg mb-2 last:mb-0 border-none overflow-hidden',\n header: 'bg-surface-container-low',\n trigger: 'px-4',\n body: 'px-4 bg-surface-container-lowest'\n }}\n />\n </div>\n </section>\n\n <!-- ==================== REAL WORLD EXAMPLE: SIDEBAR NAV ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World Example: Sidebar Navigation</h2>\n <div class=\"max-w-xs rounded-lg bg-surface-container-high p-4\">\n <Accordion\n type=\"multiple\"\n items={[\n {\n label: 'Dashboard',\n icon: 'lucide:layout-dashboard',\n content: '',\n value: 'dashboard'\n },\n {\n label: 'Products',\n icon: 'lucide:package',\n content: '',\n value: 'products'\n },\n {\n label: 'Analytics',\n icon: 'lucide:bar-chart-3',\n content: '',\n value: 'analytics'\n }\n ]}\n value={['products']}\n trailingIcon=\"lucide:chevron-right\"\n ui={{\n root: 'space-y-1',\n item: 'border-none',\n trigger: 'py-2 px-3 rounded-lg hover:bg-surface-container',\n trailingIcon: 'group-data-[state=open]:rotate-90',\n content: 'pl-6'\n }}\n >\n {#snippet body({ item })}\n <div class=\"space-y-1 py-1\">\n {#if item.value === 'products'}\n <a\n href=\"#all\"\n class=\"block rounded-md px-3 py-1.5 text-sm hover:bg-surface-container\"\n >\n All Products\n </a>\n <a\n href=\"#categories\"\n class=\"block rounded-md px-3 py-1.5 text-sm hover:bg-surface-container\"\n >\n Categories\n </a>\n <a\n href=\"#inventory\"\n class=\"block rounded-md px-3 py-1.5 text-sm hover:bg-surface-container\"\n >\n Inventory\n </a>\n {:else if item.value === 'analytics'}\n <a\n href=\"#overview\"\n class=\"block rounded-md px-3 py-1.5 text-sm hover:bg-surface-container\"\n >\n Overview\n </a>\n <a\n href=\"#reports\"\n class=\"block rounded-md px-3 py-1.5 text-sm hover:bg-surface-container\"\n >\n Reports\n </a>\n {:else}\n <a\n href=\"#home\"\n class=\"block rounded-md px-3 py-1.5 text-sm hover:bg-surface-container\"\n >\n Home\n </a>\n {/if}\n </div>\n {/snippet}\n </Accordion>\n </div>\n </section>\n\n <!-- ==================== REAL WORLD EXAMPLE: FEATURE COMPARISON ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World Example: Feature Comparison</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Accordion\n type=\"single\"\n items={[\n { label: 'Storage', value: 'storage' },\n { label: 'Users', value: 'users' },\n { label: 'Support', value: 'support' }\n ]}\n ui={{\n item: 'border-outline-variant/30',\n trigger: 'py-3'\n }}\n >\n {#snippet leading({ open })}\n <div\n class=\"flex size-6 items-center justify-center rounded {open\n ? 'bg-primary text-on-primary'\n : 'bg-surface-container-highest'}\"\n >\n <Icon name={open ? 'lucide:minus' : 'lucide:plus'} size=\"14\" />\n </div>\n {/snippet}\n {#snippet trailing()}\n <div class=\"flex gap-8 text-center text-xs\">\n <div class=\"w-16\">\n <p class=\"font-medium\">Free</p>\n </div>\n <div class=\"w-16\">\n <p class=\"font-medium text-primary\">Pro</p>\n </div>\n <div class=\"w-16\">\n <p class=\"font-medium\">Enterprise</p>\n </div>\n </div>\n {/snippet}\n {#snippet body({ item })}\n <div class=\"flex justify-end gap-8 text-center text-sm\">\n {#if item.value === 'storage'}\n <div class=\"w-16\">5 GB</div>\n <div class=\"w-16 font-medium text-primary\">100 GB</div>\n <div class=\"w-16\">Unlimited</div>\n {:else if item.value === 'users'}\n <div class=\"w-16\">1</div>\n <div class=\"w-16 font-medium text-primary\">10</div>\n <div class=\"w-16\">Unlimited</div>\n {:else}\n <div class=\"w-16\">Email</div>\n <div class=\"w-16 font-medium text-primary\">Priority</div>\n <div class=\"w-16\">24/7 Phone</div>\n {/if}\n </div>\n {/snippet}\n </Accordion>\n </div>\n </section>\n\n <!-- ==================== ADVANCED: UNIQUE UI PER ITEM ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Advanced: Unique UI Per Item</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >body</code\n >\n or\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">content</code> snippet\n with conditional rendering to create completely different layouts for each item.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Accordion\n type=\"single\"\n items={[\n { label: 'User Profile', icon: 'lucide:user', value: 'profile' },\n { label: 'Statistics', icon: 'lucide:bar-chart-2', value: 'stats' },\n { label: 'Recent Activity', icon: 'lucide:activity', value: 'activity' },\n { label: 'Quick Actions', icon: 'lucide:zap', value: 'actions' }\n ]}\n ui={{\n item: 'border-outline-variant/30',\n trigger: 'py-3'\n }}\n >\n {#snippet body({ item })}\n {#if item.value === 'profile'}\n <!-- Profile Card UI -->\n <div class=\"flex items-center gap-4 rounded-lg bg-surface-container p-4\">\n <div\n class=\"flex size-16 items-center justify-center rounded-full bg-primary/10\"\n >\n <Icon name=\"lucide:user\" size=\"32\" class=\"text-primary\" />\n </div>\n <div class=\"flex-1\">\n <h4 class=\"font-semibold\">John Doe</h4>\n <p class=\"text-sm text-on-surface-variant\">john.doe@example.com</p>\n <div class=\"mt-2 flex gap-2\">\n <Badge\n size=\"xs\"\n variant=\"soft\"\n color=\"success\"\n label=\"Active\"\n />\n <Badge\n size=\"xs\"\n variant=\"outline\"\n color=\"primary\"\n label=\"Pro Plan\"\n />\n </div>\n </div>\n <Button\n size=\"sm\"\n variant=\"outline\"\n leadingIcon=\"lucide:pencil\"\n label=\"Edit\"\n />\n </div>\n {:else if item.value === 'stats'}\n <!-- Statistics Grid UI -->\n <div class=\"grid grid-cols-3 gap-3\">\n <div class=\"rounded-lg bg-surface-container p-3 text-center\">\n <p class=\"text-2xl font-bold text-primary\">1,234</p>\n <p class=\"text-xs text-on-surface-variant\">Total Views</p>\n </div>\n <div class=\"rounded-lg bg-surface-container p-3 text-center\">\n <p class=\"text-2xl font-bold text-success\">89%</p>\n <p class=\"text-xs text-on-surface-variant\">Success Rate</p>\n </div>\n <div class=\"rounded-lg bg-surface-container p-3 text-center\">\n <p class=\"text-2xl font-bold text-warning\">42</p>\n <p class=\"text-xs text-on-surface-variant\">Pending</p>\n </div>\n </div>\n {:else if item.value === 'activity'}\n <!-- Activity Timeline UI -->\n <div class=\"space-y-3\">\n {#each [{ time: '2 min ago', text: 'Updated profile picture', icon: 'lucide:image', color: 'text-primary' }, { time: '1 hour ago', text: 'Completed task #123', icon: 'lucide:check-circle', color: 'text-success' }, { time: '3 hours ago', text: 'Added new comment', icon: 'lucide:message-circle', color: 'text-info' }] as activity (activity.text)}\n <div class=\"flex items-center gap-3\">\n <div\n class=\"flex size-8 shrink-0 items-center justify-center rounded-full bg-surface-container\"\n >\n <Icon\n name={activity.icon}\n size=\"16\"\n class={activity.color}\n />\n </div>\n <div class=\"flex-1\">\n <p class=\"text-sm\">{activity.text}</p>\n <p class=\"text-xs text-on-surface-variant\">\n {activity.time}\n </p>\n </div>\n </div>\n {/each}\n </div>\n {:else if item.value === 'actions'}\n <!-- Quick Actions Grid UI -->\n <div class=\"grid grid-cols-2 gap-2\">\n <Button\n variant=\"outline\"\n leadingIcon=\"lucide:plus\"\n label=\"New Item\"\n class=\"justify-start\"\n />\n <Button\n variant=\"outline\"\n leadingIcon=\"lucide:upload\"\n label=\"Upload\"\n class=\"justify-start\"\n />\n <Button\n variant=\"outline\"\n leadingIcon=\"lucide:download\"\n label=\"Export\"\n class=\"justify-start\"\n />\n <Button\n variant=\"outline\"\n leadingIcon=\"lucide:share-2\"\n label=\"Share\"\n class=\"justify-start\"\n />\n </div>\n {/if}\n {/snippet}\n </Accordion>\n </div>\n </section>\n\n <!-- ==================== ADVANCED: MIXED CONTENT TYPES ==================== -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Advanced: Mixed Content Types</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Combine different content types like forms, images, code blocks, and interactive\n elements.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Accordion\n type=\"multiple\"\n items={[\n { label: 'Contact Form', icon: 'lucide:mail', value: 'form' },\n { label: 'Image Gallery', icon: 'lucide:image', value: 'gallery' },\n { label: 'Code Example', icon: 'lucide:code', value: 'code' }\n ]}\n value={['form']}\n ui={{\n item: 'bg-surface-container rounded-lg mb-2 last:mb-0 border-none overflow-hidden',\n trigger: 'px-4 py-3',\n body: 'px-4 pb-4'\n }}\n >\n {#snippet body({ item })}\n {#if item.value === 'form'}\n <!-- Form UI -->\n <div class=\"space-y-3\">\n <div class=\"grid gap-3 sm:grid-cols-2\">\n <label class=\"block\">\n <span class=\"mb-1 block text-xs font-medium\">Name</span>\n <input\n type=\"text\"\n placeholder=\"Your name\"\n class=\"w-full rounded-lg border border-outline-variant bg-surface px-3 py-2 text-sm focus:border-primary focus:outline-none\"\n />\n </label>\n <label class=\"block\">\n <span class=\"mb-1 block text-xs font-medium\">Email</span>\n <input\n type=\"email\"\n placeholder=\"your@email.com\"\n class=\"w-full rounded-lg border border-outline-variant bg-surface px-3 py-2 text-sm focus:border-primary focus:outline-none\"\n />\n </label>\n </div>\n <label class=\"block\">\n <span class=\"mb-1 block text-xs font-medium\">Message</span>\n <textarea\n placeholder=\"Your message...\"\n rows=\"3\"\n class=\"w-full rounded-lg border border-outline-variant bg-surface px-3 py-2 text-sm focus:border-primary focus:outline-none\"\n ></textarea>\n </label>\n <Button\n variant=\"solid\"\n label=\"Send Message\"\n leadingIcon=\"lucide:send\"\n />\n </div>\n {:else if item.value === 'gallery'}\n <!-- Image Gallery UI -->\n <div class=\"grid grid-cols-3 gap-2\">\n {#each Array.from({ length: 6 }, (_, i) => i) as i (i)}\n <div\n class=\"flex aspect-square items-center justify-center rounded-lg bg-linear-to-br from-primary/20 to-secondary/20\"\n >\n <Icon\n name=\"lucide:image\"\n size=\"24\"\n class=\"text-on-surface-variant/50\"\n />\n </div>\n {/each}\n </div>\n <p class=\"mt-2 text-center text-xs text-on-surface-variant\">\n Click to view full size\n </p>\n {:else if item.value === 'code'}\n <!-- Code Block UI -->\n <div class=\"overflow-hidden rounded-lg bg-surface-container-highest\">\n <div\n class=\"flex items-center justify-between border-b border-outline-variant/30 px-3 py-2\"\n >\n <span class=\"text-xs text-on-surface-variant\">accordion.svelte</span\n >\n <Button\n size=\"xs\"\n variant=\"ghost\"\n leadingIcon=\"lucide:copy\"\n label=\"Copy\"\n />\n </div>\n <pre class=\"overflow-x-auto p-3 text-xs\"><code\n class=\"text-on-surface-variant\"\n >&lt;Accordion\n type=\"single\"\n items=&#123;items&#125;\n bind:value\n&gt;\n &#123;#snippet body(&#123; item &#125;)&#125;\n &lt;p&gt;&#123;item.content&#125;&lt;/p&gt;\n &#123;/snippet&#125;\n&lt;/Accordion&gt;</code\n ></pre>\n </div>\n {/if}\n {/snippet}\n </Accordion>\n </div>\n </section>\n</div>\n",
119
- "chart": "<script lang=\"ts\">\n import { Chart } from '$lib/index.js'\n \n // Sample data for various charts\n const barData = {\n labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],\n datasets: [{\n label: 'Sales ($)',\n data: [12000, 19000, 15000, 22000, 18000, 25000],\n backgroundColor: 'rgba(59, 130, 246, 0.5)',\n borderColor: 'rgb(59, 130, 246)',\n borderWidth: 1\n }]\n }\n\n const lineData = {\n labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],\n datasets: [{\n label: 'Active Users',\n data: [65, 59, 80, 81, 56, 55, 40],\n fill: false,\n borderColor: 'rgb(16, 185, 129)',\n tension: 0.1\n }]\n }\n\n const pieData = {\n labels: ['Desktop', 'Mobile', 'Tablet'],\n datasets: [{\n data: [300, 500, 100],\n backgroundColor: [\n 'rgb(59, 130, 246)',\n 'rgb(16, 185, 129)',\n 'rgb(245, 158, 11)'\n ],\n hoverOffset: 4\n }]\n }\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Chart</h1>\n <p class=\"text-on-surface-variant\">\n A flexible wrapper around <code class=\"rounded bg-surface-container-highest px-1\">chart.js</code> to render beautiful, responsive charts.\n </p>\n </div>\n\n <!-- Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Usage</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Pass the <code class=\"rounded bg-surface-container-highest px-1\">type</code> prop (e.g. <code class=\"rounded bg-surface-container-highest px-1\">bar</code>, <code class=\"rounded bg-surface-container-highest px-1\">line</code>, <code class=\"rounded bg-surface-container-highest px-1\">pie</code>) and the standard Chart.js <code class=\"rounded bg-surface-container-highest px-1\">data</code> object.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <div class=\"h-[300px] w-full\">\n <Chart type=\"bar\" data={barData} />\n </div>\n </div>\n </section>\n\n <!-- Line Chart -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Line Chart</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Set <code class=\"rounded bg-surface-container-highest px-1\">type=\"line\"</code> to render a line chart.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <div class=\"h-[300px] w-full\">\n <Chart type=\"line\" data={lineData} />\n </div>\n </div>\n </section>\n\n <!-- Pie Chart -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Pie Chart</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Set <code class=\"rounded bg-surface-container-highest px-1\">type=\"pie\"</code> to render a pie chart. Ensure the parent container has adequate width/height constraints.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4 flex justify-center\">\n <div class=\"h-[300px] w-full max-w-sm\">\n <Chart type=\"pie\" data={pieData} />\n </div>\n </div>\n </section>\n</div>\n",
123
+ "chart": "<script lang=\"ts\">\n import { Chart } from '$lib/index.js'\n import type { ApexOptions } from 'apexcharts'\n \n // 1. Bar Chart (Basic)\n const barOptions: ApexOptions = {\n chart: { type: 'bar', height: 320, toolbar: { show: false } },\n series: [{ name: 'Sales', data: [30, 40, 45, 50, 49, 60] }],\n xaxis: { categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'] },\n colors: ['var(--color-primary)'],\n plotOptions: { bar: { borderRadius: 4, columnWidth: '60%' } }\n }\n\n // 2. Area Chart (Smooth Curve + Gradient)\n const areaOptions: ApexOptions = {\n chart: { type: 'area', height: 320, toolbar: { show: false } },\n series: [{ name: 'Active Users', data: [65, 59, 80, 81, 56, 55, 40] }],\n xaxis: { categories: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] },\n stroke: { curve: 'smooth', width: 3 },\n fill: { type: 'gradient', gradient: { shadeIntensity: 1, opacityFrom: 0.4, opacityTo: 0.1, stops: [0, 90, 100] } },\n colors: ['var(--color-secondary)']\n }\n\n // 3. Donut Chart (Proportions)\n const donutOptions: ApexOptions = {\n chart: { type: 'donut', height: 320 },\n series: [44, 55, 13, 33],\n labels: ['Apple', 'Mango', 'Orange', 'Watermelon'],\n colors: ['var(--color-primary)', 'var(--color-secondary)', 'var(--color-tertiary)', 'var(--color-warning)'],\n plotOptions: { pie: { donut: { size: '65%' } } },\n stroke: { show: true, colors: ['transparent'], width: 2 }\n }\n\n // 4. Stacked Column Chart (Composition over time)\n const stackedOptions: ApexOptions = {\n chart: { type: 'bar', height: 320, stacked: true, toolbar: { show: false } },\n series: [\n { name: 'Product A', data: [44, 55, 41, 67, 22, 43] },\n { name: 'Product B', data: [13, 23, 20, 8, 13, 27] },\n { name: 'Product C', data: [11, 17, 15, 15, 21, 14] }\n ],\n xaxis: { categories: ['Q1', 'Q2', 'Q3', 'Q4', 'Q5', 'Q6'] },\n colors: ['var(--color-primary)', 'var(--color-secondary)', 'var(--color-tertiary)'],\n plotOptions: { bar: { borderRadius: 4 } },\n fill: { opacity: 1 },\n legend: { position: 'top', horizontalAlign: 'right' }\n }\n\n // 5. Mixed Chart (Line + Column for Multi-metric)\n const mixedOptions: ApexOptions = {\n chart: { height: 320, type: 'line', toolbar: { show: false } },\n series: [\n { name: 'Revenue', type: 'column', data: [23, 11, 22, 27, 13, 22, 37, 21, 44, 22, 30] },\n { name: 'Profit Margin', type: 'line', data: [44, 55, 41, 67, 22, 43, 21, 41, 56, 27, 43] }\n ],\n stroke: { width: [0, 4], curve: 'smooth' },\n colors: ['var(--color-surface-container-highest)', 'var(--color-primary)'],\n labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov'],\n xaxis: { type: 'category' }\n }\n\n // 6. Radar Chart (Multi-dimensional Analysis)\n const radarOptions: ApexOptions = {\n chart: { type: 'radar', height: 350, toolbar: { show: false } },\n series: [{ name: 'Series 1', data: [80, 50, 30, 40, 100, 20] }],\n labels: ['Design', 'Development', 'Marketing', 'Sales', 'Support', 'IT'],\n colors: ['var(--color-primary)'],\n stroke: { width: 2 },\n fill: { opacity: 0.2 },\n markers: { size: 4, hover: { size: 6 } }\n }\n\n // 7. Radial Bar (Gauge/Score)\n const radialOptions: ApexOptions = {\n chart: { type: 'radialBar', height: 350 },\n series: [76],\n colors: ['var(--color-success)'],\n plotOptions: {\n radialBar: {\n hollow: { size: '65%' },\n dataLabels: {\n name: { offsetY: -10, color: 'var(--color-on-surface-variant)', fontSize: '13px' },\n value: { color: 'var(--color-on-surface)', fontSize: '30px', show: true }\n }\n }\n },\n labels: ['Performance']\n }\n</script>\n\n<div class=\"space-y-12\">\n <div class=\"space-y-2\">\n <h1 class=\"text-3xl font-bold tracking-tight\">Chart</h1>\n <p class=\"text-lg text-on-surface-variant max-w-3xl\">\n A beautiful, fully interactive charting wrapper built on top of <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5\">ApexCharts</code>. Extremely flexible to cover any data visualization use case you need.\n </p>\n </div>\n\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8\">\n \n <!-- Bar Chart -->\n <section class=\"space-y-3\">\n <h2 class=\"text-xl font-semibold\">Bar Chart</h2>\n <p class=\"text-sm text-on-surface-variant\">Simple comparisons with rounded corners.</p>\n <div class=\"rounded-xl bg-surface-container-low border border-outline-variant/60 p-6 shadow-sm\">\n <Chart options={barOptions} />\n </div>\n </section>\n\n <!-- Area Chart -->\n <section class=\"space-y-3\">\n <h2 class=\"text-xl font-semibold\">Area Chart</h2>\n <p class=\"text-sm text-on-surface-variant\">Smooth curves with beautiful gradients for trends.</p>\n <div class=\"rounded-xl bg-surface-container-low border border-outline-variant/60 p-6 shadow-sm\">\n <Chart options={areaOptions} />\n </div>\n </section>\n\n <!-- Stacked Column Chart -->\n <section class=\"space-y-3\">\n <h2 class=\"text-xl font-semibold\">Stacked Column Chart</h2>\n <p class=\"text-sm text-on-surface-variant\">Perfect for visualizing composition and parts-to-whole over time.</p>\n <div class=\"rounded-xl bg-surface-container-low border border-outline-variant/60 p-6 shadow-sm\">\n <Chart options={stackedOptions} />\n </div>\n </section>\n\n <!-- Mixed Chart -->\n <section class=\"space-y-3\">\n <h2 class=\"text-xl font-semibold\">Mixed Chart (Line + Column)</h2>\n <p class=\"text-sm text-on-surface-variant\">Combine different types to compare multiple metrics (e.g. Revenue vs Margin).</p>\n <div class=\"rounded-xl bg-surface-container-low border border-outline-variant/60 p-6 shadow-sm\">\n <Chart options={mixedOptions} />\n </div>\n </section>\n\n <!-- Donut Chart -->\n <section class=\"space-y-3\">\n <h2 class=\"text-xl font-semibold\">Donut Chart</h2>\n <p class=\"text-sm text-on-surface-variant\">Clear proportional breakdown with hover expansions.</p>\n <div class=\"rounded-xl bg-surface-container-low border border-outline-variant/60 p-6 shadow-sm flex items-center justify-center\">\n <div class=\"w-full max-w-[320px]\">\n <Chart options={donutOptions} />\n </div>\n </div>\n </section>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-8 col-span-1 xl:col-span-2\">\n <!-- Radar Chart -->\n <section class=\"space-y-3\">\n <h2 class=\"text-xl font-semibold\">Radar Chart</h2>\n <p class=\"text-sm text-on-surface-variant\">Analyze multiple variables simultaneously.</p>\n <div class=\"rounded-xl bg-surface-container-low border border-outline-variant/60 p-6 shadow-sm flex items-center justify-center\">\n <Chart options={radarOptions} />\n </div>\n </section>\n\n <!-- Radial Bar -->\n <section class=\"space-y-3\">\n <h2 class=\"text-xl font-semibold\">Radial Bar Gauge</h2>\n <p class=\"text-sm text-on-surface-variant\">Ideal for scorecards and KPI dashboard indicators.</p>\n <div class=\"rounded-xl bg-surface-container-low border border-outline-variant/60 p-6 shadow-sm flex items-center justify-center\">\n <Chart options={radialOptions} />\n </div>\n </section>\n </div>\n\n </div>\n</div>\n",
120
124
  "avatar": "<script lang=\"ts\">\n import { Avatar, AvatarGroup } from '$lib/index.js'\n\n const sizes = ['3xs', '2xs', 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'] as const\n\n const groupAvatars = [\n { src: 'https://i.pravatar.cc/150?img=20', alt: 'User 1' },\n { src: 'https://i.pravatar.cc/150?img=21', alt: 'User 2' },\n { src: 'https://i.pravatar.cc/150?img=22', alt: 'User 3' },\n { src: 'https://i.pravatar.cc/150?img=23', alt: 'User 4' },\n { src: 'https://i.pravatar.cc/150?img=24', alt: 'User 5' },\n { src: 'https://i.pravatar.cc/150?img=25', alt: 'User 6' },\n { src: 'https://i.pravatar.cc/150?img=26', alt: 'User 7' }\n ]\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Avatar</h1>\n <p class=\"text-on-surface-variant\">\n Display user profile images with fallback to initials, icons, or custom content.\n </p>\n </div>\n\n <!-- Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Usage</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <Avatar src=\"https://i.pravatar.cc/150?img=1\" alt=\"John Doe\" />\n <Avatar src=\"https://i.pravatar.cc/150?img=2\" alt=\"Jane Smith\" />\n <Avatar src=\"https://i.pravatar.cc/150?img=3\" alt=\"Bob Wilson\" />\n <Avatar alt=\"No Image\" />\n <Avatar text=\"AB\" />\n <Avatar icon=\"lucide:user\" />\n </div>\n </section>\n\n <!-- Size -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Size</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">size</code> prop to\n control dimensions. Available sizes:\n <code class=\"rounded bg-surface-container-highest px-1\">3xs</code>\n to <code class=\"rounded bg-surface-container-highest px-1\">3xl</code>.\n </p>\n <div class=\"flex flex-wrap items-end gap-4 rounded-lg bg-surface-container-high p-4\">\n {#each sizes as size (size)}\n <div class=\"flex flex-col items-center gap-2\">\n <Avatar src=\"https://i.pravatar.cc/150?img=5\" alt=\"User\" {size} />\n <span class=\"text-xs text-on-surface-variant\">{size}</span>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Rounded -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Rounded</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">rounded</code> prop to\n control the border radius. Use\n <code class=\"rounded bg-surface-container-highest px-1\">lg</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">md</code>, or\n <code class=\"rounded bg-surface-container-highest px-1\">none</code> for square-ish avatars\n (e.g. organization logos).\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n {#each ['full', 'lg', 'md', 'sm', 'none'] as r (r)}\n <div class=\"flex flex-col items-center gap-2\">\n <Avatar\n src=\"https://i.pravatar.cc/150?img=8\"\n alt=\"User\"\n size=\"xl\"\n rounded={r as 'full' | 'lg' | 'md' | 'sm' | 'none'}\n />\n <span class=\"text-xs text-on-surface-variant\">{r}</span>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Fallback Initials -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Fallback Initials</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Auto-generates initials from <code class=\"rounded bg-surface-container-highest px-1\"\n >alt</code\n >\n text when no image. Use\n <code class=\"rounded bg-surface-container-highest px-1\">text</code> to override.\n </p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <Avatar alt=\"John Doe\" size=\"lg\" />\n <Avatar alt=\"Jane Smith\" size=\"lg\" />\n <Avatar alt=\"Bob\" size=\"lg\" />\n <Avatar alt=\"Alice Brown Carter\" size=\"lg\" />\n <Avatar text=\"XY\" size=\"lg\" />\n </div>\n </section>\n\n <!-- Icon Fallback -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Icon Fallback</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">icon</code> prop to display\n an Iconify icon as fallback when no image or text is available.\n </p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <Avatar icon=\"lucide:user\" size=\"lg\" />\n <Avatar icon=\"lucide:users\" size=\"lg\" />\n <Avatar icon=\"lucide:building-2\" size=\"lg\" rounded=\"lg\" />\n <Avatar\n icon=\"lucide:bot\"\n size=\"lg\"\n class=\"bg-primary\"\n ui={{ icon: 'text-on-primary' }}\n />\n </div>\n </section>\n\n <!-- Chip -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Chip</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">chip</code> prop to add\n a status indicator. Pass\n <code class=\"rounded bg-surface-container-highest px-1\">true</code> for default or an object\n to customize.\n </p>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Default</p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Avatar src=\"https://i.pravatar.cc/150?img=10\" alt=\"User\" size=\"lg\" chip />\n </div>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Color</p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n {#each ['primary', 'secondary', 'success', 'warning', 'error', 'info', 'surface'] as color (color)}\n <div class=\"flex flex-col items-center gap-2\">\n <Avatar\n src=\"https://i.pravatar.cc/150?img=12\"\n alt={color}\n size=\"lg\"\n chip={{ color: color as 'primary' }}\n />\n <span class=\"text-xs text-on-surface-variant\">{color}</span>\n </div>\n {/each}\n </div>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Position</p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n {#each ['top-right', 'top-left', 'bottom-right', 'bottom-left'] as pos (pos)}\n <div class=\"flex flex-col items-center gap-2\">\n <Avatar\n src=\"https://i.pravatar.cc/150?img=16\"\n alt=\"User\"\n size=\"xl\"\n chip={{ color: 'success', position: pos as 'top-right' }}\n />\n <span class=\"text-xs text-on-surface-variant\">{pos}</span>\n </div>\n {/each}\n </div>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">With text</p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Avatar\n src=\"https://i.pravatar.cc/150?img=18\"\n alt=\"User\"\n size=\"3xl\"\n chip={{ color: 'error', text: 3, size: '3xl' }}\n />\n <Avatar\n src=\"https://i.pravatar.cc/150?img=19\"\n alt=\"User\"\n size=\"3xl\"\n chip={{ color: 'success', text: '99+', size: '3xl' }}\n />\n </div>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Show / Hide</p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col items-center gap-2\">\n <Avatar\n src=\"https://i.pravatar.cc/150?img=20\"\n alt=\"Visible\"\n size=\"lg\"\n chip={{ color: 'success', show: true }}\n />\n <span class=\"text-xs text-on-surface-variant\">show: true</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <Avatar\n src=\"https://i.pravatar.cc/150?img=21\"\n alt=\"Hidden\"\n size=\"lg\"\n chip={{ color: 'success', show: false }}\n />\n <span class=\"text-xs text-on-surface-variant\">show: false</span>\n </div>\n </div>\n </section>\n\n <!-- Avatar Group -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Avatar Group</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">AvatarGroup</code> to display\n multiple avatars with overlap.\n </p>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Usage</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <AvatarGroup avatars={groupAvatars.slice(0, 5)} />\n </div>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Max</p>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">max</code> to limit visible avatars.\n Excess is shown as a \"+N\" indicator.\n </p>\n <div class=\"flex flex-col gap-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col gap-1\">\n <span class=\"text-xs text-on-surface-variant\">max=3</span>\n <AvatarGroup avatars={groupAvatars} max={3} />\n </div>\n <div class=\"flex flex-col gap-1\">\n <span class=\"text-xs text-on-surface-variant\">max=5</span>\n <AvatarGroup avatars={groupAvatars} max={5} />\n </div>\n </div>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Size</p>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">size</code> to control dimensions\n of all avatars in the group.\n </p>\n <div class=\"flex flex-col gap-4 rounded-lg bg-surface-container-high p-4\">\n {#each ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'] as s (s)}\n <div class=\"flex flex-col gap-1\">\n <span class=\"text-xs text-on-surface-variant\">{s}</span>\n <AvatarGroup avatars={groupAvatars.slice(0, 4)} size={s as 'md'} />\n </div>\n {/each}\n </div>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Rounded</p>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">rounded</code> to control the\n border radius of all avatars.\n </p>\n <div class=\"flex flex-col gap-4 rounded-lg bg-surface-container-high p-4\">\n {#each ['full', 'lg', 'md', 'sm', 'none'] as r (r)}\n <div class=\"flex flex-col gap-1\">\n <span class=\"text-xs text-on-surface-variant\">{r}</span>\n <AvatarGroup\n avatars={groupAvatars.slice(0, 4)}\n size=\"xl\"\n rounded={r as 'full'}\n />\n </div>\n {/each}\n </div>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">With initials fallback</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <AvatarGroup\n avatars={[\n { alt: 'Alice Johnson' },\n { alt: 'Bob Williams' },\n { alt: 'Carol Davis' },\n { alt: 'David Lee' },\n { alt: 'Emma Wilson' }\n ]}\n max={3}\n size=\"lg\"\n />\n </div>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">With chip</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <AvatarGroup\n avatars={[\n {\n src: 'https://i.pravatar.cc/150?img=40',\n alt: 'Online',\n chip: { color: 'success' }\n },\n {\n src: 'https://i.pravatar.cc/150?img=41',\n alt: 'Away',\n chip: { color: 'warning' }\n },\n {\n src: 'https://i.pravatar.cc/150?img=42',\n alt: 'Offline',\n chip: { color: 'error' }\n },\n { src: 'https://i.pravatar.cc/150?img=43', alt: 'User 4' },\n { src: 'https://i.pravatar.cc/150?img=44', alt: 'User 5' }\n ]}\n max={4}\n size=\"lg\"\n />\n </div>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Custom styling</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <AvatarGroup\n avatars={groupAvatars.slice(0, 5)}\n max={3}\n size=\"xl\"\n class=\"gap-1\"\n ui={{ base: 'ring-primary' }}\n />\n </div>\n </section>\n\n <!-- Custom Styling -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Styling</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">class</code> and\n <code class=\"rounded bg-surface-container-highest px-1\">ui</code> to customize individual\n slots.\n </p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <Avatar\n src=\"https://i.pravatar.cc/150?img=10\"\n alt=\"User\"\n size=\"xl\"\n class=\"ring-2 ring-primary ring-offset-2 ring-offset-surface\"\n />\n <Avatar\n src=\"https://i.pravatar.cc/150?img=11\"\n alt=\"User\"\n size=\"xl\"\n class=\"ring-2 ring-success\"\n />\n <Avatar alt=\"VIP\" size=\"xl\" class=\"bg-primary\" ui={{ fallback: 'text-on-primary' }} />\n <Avatar\n alt=\"Pro\"\n size=\"xl\"\n class=\"bg-linear-to-br from-primary to-tertiary\"\n ui={{ fallback: 'text-white font-bold' }}\n />\n </div>\n </section>\n\n <!-- Examples -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Examples</h2>\n\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">\n User list with status\n </p>\n <div class=\"flex flex-col gap-3\">\n {#each [{ name: 'Alice Johnson', color: 'success' as const, img: 1 }, { name: 'Bob Williams', color: 'error' as const, img: 2 }, { name: 'Carol Davis', color: 'warning' as const, img: 3 }] as user (user.name)}\n <div class=\"flex items-center gap-3\">\n <Avatar\n src=\"https://i.pravatar.cc/150?img={user.img}\"\n alt={user.name}\n chip={{ color: user.color }}\n />\n <div>\n <p class=\"text-sm font-medium\">{user.name}</p>\n <p class=\"text-xs text-on-surface-variant\">Member</p>\n </div>\n </div>\n {/each}\n </div>\n </div>\n\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Organization logos</p>\n <div class=\"flex flex-wrap items-center gap-4\">\n <Avatar\n icon=\"lucide:building-2\"\n size=\"xl\"\n rounded=\"lg\"\n class=\"bg-primary\"\n ui={{ icon: 'text-on-primary' }}\n />\n <Avatar\n icon=\"lucide:code-2\"\n size=\"xl\"\n rounded=\"md\"\n class=\"bg-secondary\"\n ui={{ icon: 'text-on-secondary' }}\n />\n <Avatar\n icon=\"lucide:globe\"\n size=\"xl\"\n rounded=\"lg\"\n class=\"bg-tertiary\"\n ui={{ icon: 'text-on-tertiary' }}\n />\n </div>\n </div>\n </section>\n</div>\n",
121
125
  "avatar-group": "<script lang=\"ts\">\n import { Avatar, AvatarGroup } from '$lib/index.js'\n\n const sizes = ['3xs', '2xs', 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'] as const\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Avatar Group</h1>\n <p class=\"text-on-surface-variant\">\n Display a stack of overlapping avatars with optional overflow indicator.\n </p>\n </div>\n\n <!-- Basic Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic Usage</h2>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <AvatarGroup\n avatars={[\n { src: 'https://i.pravatar.cc/150?img=1', alt: 'User 1' },\n { src: 'https://i.pravatar.cc/150?img=2', alt: 'User 2' },\n { src: 'https://i.pravatar.cc/150?img=3', alt: 'User 3' },\n { src: 'https://i.pravatar.cc/150?img=4', alt: 'User 4' }\n ]}\n />\n </div>\n </section>\n\n <!-- Max Limit -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Max Limit</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">max</code> to limit visible avatars.\n Excess shown as \"+N\".\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <AvatarGroup\n max={3}\n avatars={[\n { src: 'https://i.pravatar.cc/150?img=1', alt: 'User 1' },\n { src: 'https://i.pravatar.cc/150?img=2', alt: 'User 2' },\n { src: 'https://i.pravatar.cc/150?img=3', alt: 'User 3' },\n { src: 'https://i.pravatar.cc/150?img=4', alt: 'User 4' },\n { src: 'https://i.pravatar.cc/150?img=5', alt: 'User 5' },\n { src: 'https://i.pravatar.cc/150?img=6', alt: 'User 6' }\n ]}\n />\n </div>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <div class=\"flex flex-wrap items-end gap-6 rounded-lg bg-surface-container-high p-4\">\n {#each sizes as size (size)}\n <div class=\"flex flex-col items-center gap-2\">\n <AvatarGroup\n {size}\n avatars={[\n { src: 'https://i.pravatar.cc/150?img=1', alt: 'User 1' },\n { src: 'https://i.pravatar.cc/150?img=2', alt: 'User 2' },\n { src: 'https://i.pravatar.cc/150?img=3', alt: 'User 3' }\n ]}\n />\n <span class=\"text-xs text-on-surface-variant\">{size}</span>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- With Children -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">With Children</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use slot content for full control over child avatars.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <AvatarGroup size=\"lg\">\n <Avatar src=\"https://i.pravatar.cc/150?img=10\" alt=\"User A\" />\n <Avatar src=\"https://i.pravatar.cc/150?img=11\" alt=\"User B\" />\n <Avatar alt=\"New\" />\n </AvatarGroup>\n </div>\n </section>\n</div>\n",
122
126
  "badge": "<script lang=\"ts\">\n import { Badge } from '$lib/index.js'\n\n const colors = [\n 'primary',\n 'secondary',\n 'tertiary',\n 'success',\n 'warning',\n 'error',\n 'info',\n 'surface'\n ] as const\n const variants = ['solid', 'outline', 'soft', 'subtle'] as const\n const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Badge</h1>\n <p class=\"text-on-surface-variant\">\n Small status indicator for labeling and categorization.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"flex flex-wrap gap-2 rounded-lg bg-surface-container-high p-4\">\n <Badge label=\"Badge\" />\n <Badge label=\"New\" color=\"success\" />\n <Badge label=\"Warning\" color=\"warning\" />\n <Badge label=\"Error\" color=\"error\" />\n </div>\n </section>\n\n <!-- Variants -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants</h2>\n <div class=\"space-y-3 rounded-lg bg-surface-container-high p-4\">\n {#each variants as variant (variant)}\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"w-16 text-sm text-on-surface-variant\">{variant}</span>\n {#each colors as color (color)}\n <Badge label={color} {variant} {color} />\n {/each}\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <div class=\"flex flex-wrap items-center gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each sizes as size (size)}\n <Badge label={size} {size} />\n {/each}\n </div>\n </section>\n\n <!-- With Icons -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">With Icons</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Add leading or trailing icons alongside the label.\n </p>\n <div class=\"flex flex-wrap gap-2 rounded-lg bg-surface-container-high p-4\">\n <Badge label=\"Star\" leadingIcon=\"lucide:star\" color=\"warning\" />\n <Badge label=\"Check\" leadingIcon=\"lucide:check\" color=\"success\" />\n <Badge label=\"Close\" trailingIcon=\"lucide:x\" color=\"error\" />\n <Badge\n label=\"Info\"\n leadingIcon=\"lucide:info\"\n trailingIcon=\"lucide:chevron-right\"\n color=\"info\"\n />\n </div>\n </section>\n\n <!-- Icon Only -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Icon Only</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the icon prop for square icon-only badges.\n </p>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n {#each sizes as size (size)}\n <Badge icon=\"lucide:star\" color=\"warning\" {size} />\n {/each}\n </div>\n <div class=\"flex flex-wrap gap-2 rounded-lg bg-surface-container-high p-4\">\n <Badge icon=\"lucide:check\" color=\"success\" />\n <Badge icon=\"lucide:x\" color=\"error\" />\n <Badge icon=\"lucide:heart\" color=\"error\" variant=\"soft\" />\n <Badge icon=\"lucide:bell\" color=\"info\" variant=\"outline\" />\n <Badge icon=\"lucide:lock\" color=\"surface\" variant=\"subtle\" />\n </div>\n </section>\n\n <!-- With Avatar -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">With Avatar</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Display an avatar on the leading side of the badge.\n </p>\n <div class=\"flex flex-wrap gap-2 rounded-lg bg-surface-container-high p-4\">\n <Badge label=\"John\" avatar={{ alt: 'John', src: 'https://i.pravatar.cc/32?u=1' }} />\n <Badge\n label=\"Jane\"\n avatar={{ alt: 'Jane', src: 'https://i.pravatar.cc/32?u=2' }}\n color=\"secondary\"\n />\n <Badge\n label=\"Admin\"\n avatar={{ alt: 'Admin' }}\n color=\"tertiary\"\n variant=\"soft\"\n size=\"lg\"\n />\n </div>\n </section>\n\n <!-- Children Slot -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Children Slot</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the default snippet for custom content instead of the label prop.\n </p>\n <div class=\"flex flex-wrap gap-2 rounded-lg bg-surface-container-high p-4\">\n <Badge color=\"success\" variant=\"soft\">\n <span class=\"flex items-center gap-1\">\n <span class=\"size-1.5 rounded-full bg-success\"></span>\n Online\n </span>\n </Badge>\n <Badge color=\"error\" variant=\"soft\">\n <span class=\"flex items-center gap-1\">\n <span class=\"size-1.5 rounded-full bg-error\"></span>\n Offline\n </span>\n </Badge>\n <Badge color=\"warning\" variant=\"outline\">\n <span class=\"font-mono\">v2.0.0-beta</span>\n </Badge>\n </div>\n </section>\n\n <!-- Custom Leading/Trailing Slots -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Slots</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Override leading and trailing content with custom snippets.\n </p>\n <div class=\"flex flex-wrap gap-2 rounded-lg bg-surface-container-high p-4\">\n <Badge label=\"Custom Leading\" color=\"tertiary\" variant=\"soft\">\n {#snippet leading()}\n <span class=\"size-2 rounded-full bg-tertiary\"></span>\n {/snippet}\n </Badge>\n <Badge label=\"Custom Trailing\" color=\"info\" variant=\"outline\">\n {#snippet trailing()}\n <span\n class=\"flex size-4 items-center justify-center rounded-full bg-info text-[8px] text-on-info\"\n >\n 3\n </span>\n {/snippet}\n </Badge>\n </div>\n </section>\n\n <!-- UI Slot Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Slot Overrides</h2>\n <div class=\"flex flex-wrap gap-2 rounded-lg bg-surface-container-high p-4\">\n <Badge label=\"Rounded Full\" ui={{ base: 'rounded-full px-3' }} />\n <Badge\n label=\"Gradient\"\n ui={{\n base: 'bg-gradient-to-r from-primary to-tertiary text-on-primary rounded-full px-3'\n }}\n />\n <Badge\n label=\"BOLD\"\n ui={{ label: 'font-bold uppercase tracking-wider' }}\n color=\"error\"\n variant=\"outline\"\n />\n </div>\n </section>\n\n <!-- Real World Examples -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n <div class=\"space-y-6 rounded-lg bg-surface-container-high p-4\">\n <!-- Status Labels -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Status Labels</p>\n <div class=\"flex flex-wrap gap-2\">\n <Badge label=\"Active\" color=\"success\" leadingIcon=\"lucide:circle-check\" />\n <Badge label=\"Pending\" color=\"warning\" leadingIcon=\"lucide:clock\" />\n <Badge label=\"Inactive\" color=\"error\" leadingIcon=\"lucide:circle-x\" />\n <Badge label=\"Draft\" color=\"surface\" leadingIcon=\"lucide:file-edit\" />\n </div>\n </div>\n\n <!-- Tags -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Tags</p>\n <div class=\"flex flex-wrap gap-2\">\n <Badge label=\"Svelte\" variant=\"soft\" color=\"tertiary\" />\n <Badge label=\"TypeScript\" variant=\"soft\" color=\"info\" />\n <Badge label=\"Tailwind\" variant=\"soft\" color=\"primary\" />\n <Badge label=\"Vite\" variant=\"soft\" color=\"warning\" />\n </div>\n </div>\n\n <!-- Notification Count -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Counts</p>\n <div class=\"flex flex-wrap gap-3\">\n <Badge label={3} color=\"primary\" square />\n <Badge label={12} color=\"error\" square />\n <Badge label=\"99+\" color=\"info\" size=\"sm\" />\n <Badge label=\"NEW\" color=\"success\" size=\"xs\" />\n </div>\n </div>\n\n <!-- Card with Badge -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">In Context</p>\n <div\n class=\"max-w-sm rounded-lg border border-outline-variant bg-surface-container p-4\"\n >\n <div class=\"mb-2 flex items-center justify-between\">\n <h3 class=\"font-medium\">Feature Request</h3>\n <Badge label=\"Open\" color=\"success\" variant=\"soft\" size=\"sm\" />\n </div>\n <p class=\"mb-3 text-sm text-on-surface-variant\">\n Add dark mode toggle to the settings panel.\n </p>\n <div class=\"flex gap-1.5\">\n <Badge label=\"enhancement\" variant=\"outline\" color=\"tertiary\" size=\"xs\" />\n <Badge label=\"ui\" variant=\"outline\" color=\"info\" size=\"xs\" />\n <Badge label=\"p2\" variant=\"outline\" color=\"warning\" size=\"xs\" />\n </div>\n </div>\n </div>\n </div>\n </section>\n\n <!-- Variants x Colors Matrix -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants x Colors</h2>\n <div class=\"overflow-x-auto rounded-lg bg-surface-container-high p-4\">\n <table class=\"w-full\">\n <thead>\n <tr class=\"border-b border-outline-variant\">\n <th class=\"px-3 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >Variant</th\n >\n {#each colors as color (color)}\n <th\n class=\"px-3 py-3 text-center text-sm font-medium text-on-surface-variant capitalize\"\n >{color}</th\n >\n {/each}\n </tr>\n </thead>\n <tbody>\n {#each variants as variant (variant)}\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-3 text-sm font-medium text-on-surface-variant\"\n >{variant}</td\n >\n {#each colors as color (color)}\n <td class=\"px-3 py-3 text-center\">\n <Badge label={color} {variant} {color} />\n </td>\n {/each}\n </tr>\n {/each}\n </tbody>\n </table>\n </div>\n </section>\n</div>\n",
@@ -158,14 +162,12 @@
158
162
  "spotlight": "<script lang=\"ts\">\n import { Spotlight } from '$lib/index.js'\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Spotlight</h1>\n <p class=\"text-on-surface-variant\">\n A hover effect that follows your mouse cursor around the container.\n </p>\n </div>\n\n <!-- Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Usage</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Wrap your content in a <code class=\"rounded bg-surface-container-highest px-1\">Spotlight</code> component. Hover over the card to see the effect.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4 flex justify-center\">\n <Spotlight class=\"w-full max-w-sm rounded-xl border border-outline bg-surface-50 dark:bg-surface-900 p-8\">\n <h3 class=\"text-xl font-bold mb-2\">Interactive Card</h3>\n <p class=\"text-surface-500\">\n The spotlight follows your cursor, creating a subtle, premium look for modern interfaces.\n </p>\n </Spotlight>\n </div>\n </section>\n \n <!-- Custom Color -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Color & Size</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">color</code> and <code class=\"rounded bg-surface-container-highest px-1\">size</code> props to adjust the spotlight appearance.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4 flex gap-4 justify-center flex-wrap\">\n <Spotlight \n color=\"rgba(59, 130, 246, 0.2)\" \n size={300}\n class=\"w-full max-w-[200px] rounded-xl border border-outline bg-surface-900 text-white p-6\"\n >\n <div class=\"font-semibold text-primary-300\">Blue Spotlight</div>\n </Spotlight>\n \n <Spotlight \n color=\"rgba(16, 185, 129, 0.2)\" \n size={500}\n class=\"w-full max-w-[200px] rounded-xl border border-outline bg-surface-900 text-white p-6\"\n >\n <div class=\"font-semibold text-success-400\">Large Green Spotlight</div>\n </Spotlight>\n </div>\n </section>\n</div>\n",
159
163
  "breadcrumb": "<script lang=\"ts\">\n import { Breadcrumb, Icon, Link, Separator } from '$lib/index.js'\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Breadcrumb</h1>\n <p class=\"text-on-surface-variant\">\n Display a hierarchy of navigation links to show the user's current location within a\n site.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n items={[\n { label: 'Home', href: '/' },\n { label: 'Products', href: '/products' },\n { label: 'Laptops', href: '/products/laptops' },\n { label: 'MacBook Pro' }\n ]}\n />\n </div>\n </section>\n\n <!-- With Icons -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">With Icons</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n items={[\n { label: 'Home', href: '/', icon: 'lucide:home' },\n { label: 'Settings', href: '/settings', icon: 'lucide:settings' },\n { label: 'Profile', icon: 'lucide:user' }\n ]}\n />\n </div>\n </section>\n\n <!-- Separator Icon -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Separator Icon</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Customize the separator between items via the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >separatorIcon</code\n > prop.\n </p>\n <div class=\"grid gap-4 sm:grid-cols-2\">\n {#each [{ icon: 'lucide:chevron-right', name: 'Chevron (default)' }, { icon: 'lucide:slash', name: 'Slash' }, { icon: 'lucide:arrow-right', name: 'Arrow' }, { icon: 'lucide:dot', name: 'Dot' }] as sep (sep.icon)}\n <div class=\"space-y-1 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant\">{sep.name}</p>\n <Breadcrumb\n separatorIcon={sep.icon}\n items={[\n { label: 'Home', href: '/' },\n { label: 'Docs', href: '/docs' },\n { label: 'API' }\n ]}\n />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Separator Snippet -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Separator Snippet</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">separator</code\n > snippet for fully custom separator content.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n items={[\n { label: 'Home', href: '/' },\n { label: 'Category', href: '/category' },\n { label: 'Current Page' }\n ]}\n >\n {#snippet separator()}\n <span class=\"text-sm text-on-surface-variant/40\">/</span>\n {/snippet}\n </Breadcrumb>\n </div>\n </section>\n\n <!-- Disabled Items -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Disabled Items</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n items={[\n { label: 'Home', href: '/' },\n { label: 'Archived', href: '/archived', disabled: true },\n { label: 'Old Post', href: '/archived/old-post', disabled: true },\n { label: 'Detail' }\n ]}\n />\n </div>\n </section>\n\n <!-- Custom Item Snippet -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Item Snippet</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">item</code>\n snippet for fully custom item rendering.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n items={[\n { label: 'Home', href: '/', icon: 'lucide:home' },\n { label: 'Projects', href: '/projects', icon: 'lucide:folder' },\n { label: 'svelora', icon: 'lucide:package' }\n ]}\n >\n {#snippet item({ item: crumb, active })}\n {#if active}\n <span\n class=\"inline-flex items-center gap-1.5 rounded-full bg-primary/10 px-3 py-1 text-sm font-semibold text-primary\"\n >\n {#if crumb.icon}\n <Icon name={crumb.icon} size=\"14\" />\n {/if}\n {crumb.label}\n </span>\n {:else}\n <Link\n href={crumb.href ?? ''}\n raw\n class=\"inline-flex items-center gap-1.5 rounded-full px-3 py-1 text-sm text-on-surface-variant transition-colors hover:bg-surface-container-highest\"\n >\n {#if crumb.icon}\n <Icon name={crumb.icon} size=\"14\" />\n {/if}\n {crumb.label}\n </Link>\n {/if}\n {/snippet}\n </Breadcrumb>\n </div>\n </section>\n\n <!-- UI Slot Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Slot Overrides</h2>\n <div class=\"grid gap-4 lg:grid-cols-2\">\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Custom active color</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n ui={{ link: 'text-on-surface font-semibold' }}\n items={[\n { label: 'Dashboard', href: '/' },\n { label: 'Analytics', href: '/analytics' },\n { label: 'Revenue' }\n ]}\n />\n </div>\n </div>\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Larger separator</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n ui={{ separatorIcon: 'size-6 text-primary/40' }}\n items={[\n { label: 'Home', href: '/' },\n { label: 'Blog', href: '/blog' },\n { label: 'Latest Post' }\n ]}\n />\n </div>\n </div>\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">With background container</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n ui={{ root: 'bg-surface-container rounded-lg px-4 py-2' }}\n items={[\n { label: 'Home', href: '/' },\n { label: 'Shop', href: '/shop' },\n { label: 'Electronics', href: '/shop/electronics' },\n { label: 'Phones' }\n ]}\n />\n </div>\n </div>\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Wider gap</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n ui={{ list: 'gap-3' }}\n items={[\n { label: 'Home', href: '/' },\n { label: 'Team', href: '/team' },\n { label: 'Members' }\n ]}\n />\n </div>\n </div>\n </div>\n </section>\n\n <Separator />\n\n <!-- Real World Examples -->\n <section class=\"space-y-6\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <!-- File Browser -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">File Browser</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n items={[\n { label: 'Root', href: '/', icon: 'lucide:hard-drive' },\n { label: 'Users', href: '/users', icon: 'lucide:users' },\n { label: 'Documents', href: '/documents', icon: 'lucide:folder' },\n { label: 'README.md', icon: 'lucide:file-text' }\n ]}\n />\n </div>\n </div>\n\n <!-- E-commerce -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">E-commerce</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n items={[\n { label: 'Store', href: '/' },\n { label: 'Electronics', href: '/electronics' },\n { label: 'Laptops', href: '/electronics/laptops' },\n { label: 'ASUS ROG Strix' }\n ]}\n />\n </div>\n </div>\n\n <!-- Admin Dashboard -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">Admin Dashboard</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n ui={{ root: 'bg-surface-container rounded-lg px-4 py-2.5' }}\n items={[\n { label: 'Admin', href: '/admin', icon: 'lucide:shield' },\n { label: 'Users', href: '/admin/users', icon: 'lucide:users' },\n { label: 'Permissions', icon: 'lucide:lock' }\n ]}\n />\n </div>\n </div>\n\n <!-- Documentation -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">Documentation</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Breadcrumb\n separatorIcon=\"lucide:slash\"\n items={[\n { label: 'Docs', href: '/docs', icon: 'lucide:book-open' },\n { label: 'Components', href: '/docs/components' },\n { label: 'Breadcrumb' }\n ]}\n />\n </div>\n </div>\n </div>\n </section>\n</div>\n",
160
164
  "pagination": "<script lang=\"ts\">\n import { Pagination, Button, Separator } from '$lib/index.js'\n\n const colors = [\n 'primary',\n 'secondary',\n 'tertiary',\n 'success',\n 'warning',\n 'error',\n 'info',\n 'surface'\n ] as const\n const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const\n const activeVariants = ['solid', 'outline', 'soft', 'subtle', 'ghost'] as const\n const navVariants = ['ghost', 'outline', 'soft', 'subtle', 'solid', 'link'] as const\n\n let controlledPage = $state(5)\n let callbackPage = $state(1)\n let callbackLog = $state('')\n</script>\n\n<div class=\"space-y-8\">\n <h1 class=\"text-2xl font-bold text-on-surface\">Pagination</h1>\n\n <!-- Basic -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Basic Usage</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Simple pagination with previous/next controls and page numbers.\n </p>\n <Pagination total={100} itemsPerPage={10} />\n </section>\n\n <!-- Default Page -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Default Page</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Set the initial page with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">defaultPage</code\n >.\n </p>\n <Pagination total={100} itemsPerPage={10} defaultPage={5} />\n </section>\n\n <!-- Show Edges -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Show Edges</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Display first/last page buttons with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">showEdges</code\n >.\n </p>\n <Pagination total={100} itemsPerPage={10} showEdges />\n </section>\n\n <!-- Without Controls -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Without Controls</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Hide prev/next buttons with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >showControls={'{false}'}</code\n >.\n </p>\n <div class=\"space-y-3\">\n <div>\n <p class=\"mb-1 text-xs text-on-surface-variant\">Pages only</p>\n <Pagination total={100} itemsPerPage={10} showControls={false} />\n </div>\n <div>\n <p class=\"mb-1 text-xs text-on-surface-variant\">With edges, no prev/next</p>\n <Pagination total={100} itemsPerPage={10} showEdges showControls={false} />\n </div>\n </div>\n </section>\n\n <!-- Sibling Count -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Sibling Count</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Control visible siblings around current page with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >siblingCount</code\n >.\n </p>\n <div class=\"space-y-3\">\n {#each [0, 1, 2] as count (count)}\n <div>\n <p class=\"mb-1 text-xs text-on-surface-variant\">\n siblingCount={count}{count === 1 ? ' (default)' : ''}\n </p>\n <Pagination total={100} itemsPerPage={10} page={5} siblingCount={count} />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Items Per Page -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Items Per Page</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Same total (100) with different <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >itemsPerPage</code\n > values.\n </p>\n <div class=\"space-y-3\">\n {#each [5, 10, 25, 50] as perPage (perPage)}\n <div>\n <p class=\"mb-1 text-xs text-on-surface-variant\">\n {perPage} items/page ({Math.ceil(100 / perPage)} pages)\n </p>\n <Pagination total={100} itemsPerPage={perPage} />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Controlled State -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Controlled State</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >bind:page</code\n >\n for two-way binding. Current page:\n <strong class=\"text-on-surface\">{controlledPage}</strong>\n </p>\n <Pagination total={200} itemsPerPage={10} bind:page={controlledPage} showEdges />\n <div class=\"flex gap-2\">\n {#each [1, 10, 20] as p (p)}\n <Button\n variant=\"solid\"\n color=\"primary\"\n size=\"sm\"\n label=\"Go to page {p}\"\n onclick={() => (controlledPage = p)}\n />\n {/each}\n </div>\n </section>\n\n <!-- Active Colors -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Active Colors</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Customize the active page color with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">activeColor</code\n >.\n </p>\n <div class=\"space-y-3\">\n {#each colors as color (color)}\n <div class=\"flex items-center gap-4\">\n <span class=\"w-20 text-sm text-on-surface-variant\">{color}</span>\n <Pagination total={100} itemsPerPage={10} page={3} activeColor={color} />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Active Variant -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Active Variant</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Change the selected page style with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >activeVariant</code\n >.\n </p>\n <div class=\"space-y-3\">\n {#each activeVariants as av (av)}\n <div class=\"flex items-center gap-4\">\n <span class=\"w-16 text-sm text-on-surface-variant\">{av}</span>\n <Pagination total={100} itemsPerPage={10} page={3} activeVariant={av} />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Nav Button Variant -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Nav Button Variant</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Change navigation button style with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">variant</code\n >\n and\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">color</code>.\n </p>\n <div class=\"space-y-3\">\n {#each navVariants as v (v)}\n <div class=\"flex items-center gap-4\">\n <span class=\"w-16 text-sm text-on-surface-variant\">{v}</span>\n <Pagination\n total={100}\n itemsPerPage={10}\n page={3}\n variant={v}\n color=\"primary\"\n showEdges\n />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Sizes</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Control the pagination size with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">size</code\n >.\n </p>\n <div class=\"space-y-4\">\n {#each sizes as size (size)}\n <div class=\"flex items-center gap-4\">\n <span class=\"w-8 text-sm text-on-surface-variant\">{size}</span>\n <Pagination total={100} itemsPerPage={10} {size} showEdges />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Disabled -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Disabled</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Disable all controls with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">disabled</code\n >.\n </p>\n <Pagination total={100} itemsPerPage={10} page={3} disabled showEdges />\n </section>\n\n <!-- Page Change Callback -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Page Change Callback</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Listen for page changes with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >onPageChange</code\n >. Current page: <strong class=\"text-on-surface\">{callbackPage}</strong>\n </p>\n <Pagination\n total={100}\n itemsPerPage={10}\n bind:page={callbackPage}\n onPageChange={(p) => (callbackLog = `Navigated to page ${p}`)}\n showEdges\n />\n {#if callbackLog}\n <p class=\"text-xs text-on-surface-variant\">{callbackLog}</p>\n {/if}\n </section>\n\n <!-- Custom Icons -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Custom Icons</h2>\n <p class=\"text-sm text-on-surface-variant\">Customize navigation icons with icon props.</p>\n <Pagination\n total={100}\n itemsPerPage={10}\n page={5}\n showEdges\n prevIcon=\"lucide:arrow-left\"\n nextIcon=\"lucide:arrow-right\"\n ellipsisIcon=\"lucide:more-horizontal\"\n />\n </section>\n\n <!-- UI Slot Overrides -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">UI Slot Overrides</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Customize individual parts with <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">ui</code\n >.\n </p>\n <div class=\"space-y-4\">\n <div>\n <p class=\"mb-2 text-xs text-on-surface-variant\">Rounded buttons</p>\n <Pagination\n total={100}\n itemsPerPage={10}\n page={3}\n showEdges\n ui={{\n item: 'rounded-full',\n first: 'rounded-full',\n prev: 'rounded-full',\n next: 'rounded-full',\n last: 'rounded-full'\n }}\n />\n </div>\n <div>\n <p class=\"mb-2 text-xs text-on-surface-variant\">Custom gap &amp; root</p>\n <Pagination\n total={100}\n itemsPerPage={10}\n page={3}\n class=\"rounded-lg border border-outline-variant bg-surface-container p-3\"\n ui={{ list: 'gap-2' }}\n />\n </div>\n </div>\n </section>\n\n <!-- Custom Snippet Slots -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Custom Snippet Slots</h2>\n <p class=\"text-sm text-on-surface-variant\">Override individual parts with snippet slots.</p>\n <div class=\"space-y-4\">\n <div>\n <p class=\"mb-2 text-xs text-on-surface-variant\">Custom item slot (rounded)</p>\n <Pagination total={50} itemsPerPage={10} page={2}>\n {#snippet itemSlot({ page, selected })}\n <span\n class=\"inline-flex size-9 items-center justify-center rounded-full text-sm font-bold {selected\n ? 'bg-primary text-on-primary'\n : 'text-on-surface-variant'}\"\n >\n {page}\n </span>\n {/snippet}\n </Pagination>\n </div>\n <div>\n <p class=\"mb-2 text-xs text-on-surface-variant\">Custom prev/next text</p>\n <Pagination total={100} itemsPerPage={10} page={3}>\n {#snippet prevSlot({ disabled })}\n <span\n class=\"text-sm font-medium {disabled\n ? 'text-on-surface-variant/50'\n : 'text-primary'}\"\n >\n Previous\n </span>\n {/snippet}\n {#snippet nextSlot({ disabled })}\n <span\n class=\"text-sm font-medium {disabled\n ? 'text-on-surface-variant/50'\n : 'text-primary'}\"\n >\n Next\n </span>\n {/snippet}\n </Pagination>\n </div>\n <div>\n <p class=\"mb-2 text-xs text-on-surface-variant\">Custom ellipsis</p>\n <Pagination total={100} itemsPerPage={10} page={5}>\n {#snippet ellipsisSlot()}\n <span class=\"text-on-surface-variant\">---</span>\n {/snippet}\n </Pagination>\n </div>\n </div>\n </section>\n\n <!-- Edge Cases -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Edge Cases</h2>\n <p class=\"text-sm text-on-surface-variant\">Handling special scenarios.</p>\n <div class=\"space-y-3\">\n <div>\n <p class=\"mb-1 text-xs text-on-surface-variant\">Single page (5 items, 10/page)</p>\n <Pagination total={5} itemsPerPage={10} showEdges />\n </div>\n <div>\n <p class=\"mb-1 text-xs text-on-surface-variant\">Few pages (30 items, 10/page)</p>\n <Pagination total={30} itemsPerPage={10} showEdges />\n </div>\n <div>\n <p class=\"mb-1 text-xs text-on-surface-variant\">Many pages (1000 items, 10/page)</p>\n <Pagination total={1000} itemsPerPage={10} page={50} showEdges />\n </div>\n <div>\n <p class=\"mb-1 text-xs text-on-surface-variant\">Zero total</p>\n <Pagination total={0} itemsPerPage={10} />\n </div>\n </div>\n </section>\n\n <Separator />\n\n <!-- Real World Example -->\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold text-on-surface\">Real World Examples</h2>\n\n <div class=\"space-y-6\">\n <div>\n <p class=\"mb-2 text-xs text-on-surface-variant\">Table-style pagination</p>\n <div class=\"rounded-lg border border-outline-variant bg-surface-container-low p-4\">\n <div class=\"mb-3 text-sm text-on-surface-variant\">\n Showing <strong class=\"text-on-surface\">41-50</strong> of\n <strong class=\"text-on-surface\">200</strong> results\n </div>\n <Pagination\n total={200}\n itemsPerPage={10}\n page={5}\n showEdges\n size=\"sm\"\n activeColor=\"primary\"\n />\n </div>\n </div>\n\n <div>\n <p class=\"mb-2 text-xs text-on-surface-variant\">Minimal blog pagination</p>\n <div class=\"flex items-center justify-center\">\n <Pagination\n total={50}\n itemsPerPage={5}\n page={3}\n showControls={false}\n activeColor=\"surface\"\n ui={{ item: 'rounded-full' }}\n />\n </div>\n </div>\n\n <div>\n <p class=\"mb-2 text-xs text-on-surface-variant\">Combined features</p>\n <Pagination\n total={200}\n itemsPerPage={10}\n bind:page={controlledPage}\n activeColor=\"success\"\n size=\"lg\"\n showEdges\n siblingCount={2}\n ui={{\n item: 'rounded-full',\n first: 'rounded-full',\n prev: 'rounded-full',\n next: 'rounded-full',\n last: 'rounded-full',\n list: 'gap-1.5'\n }}\n />\n <p class=\"mt-2 text-xs text-on-surface-variant\">\n Page <strong class=\"text-on-surface\">{controlledPage}</strong> | Size: lg | Color:\n success | Edges | Siblings: 2 | Rounded\n </p>\n </div>\n </div>\n </section>\n</div>\n",
161
- "menu": "<script lang=\"ts\">\n import { Menu } from '$lib/index.js'\n import type { MenuItemType } from '$lib/index.js'\n \n const menuItems: MenuItemType[] = [\n { type: 'item', label: 'Dashboard', icon: 'lucide:layout-dashboard', active: true },\n { type: 'item', label: 'Analytics', icon: 'lucide:bar-chart' },\n {\n type: 'group',\n label: 'Workspace',\n icon: 'lucide:folder',\n open: true,\n items: [\n { type: 'item', label: 'Projects', icon: 'lucide:briefcase' },\n { type: 'item', label: 'Team Members', icon: 'lucide:users' }\n ]\n },\n { type: 'item', label: 'Settings', icon: 'lucide:settings' }\n ]\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Menu</h1>\n <p class=\"text-on-surface-variant\">\n A flexible navigation menu system driven by a data array.\n </p>\n </div>\n\n <!-- Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Usage</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Pass an array of <code class=\"rounded bg-surface-container-highest px-1\">MenuItemType</code> objects to the <code class=\"rounded bg-surface-container-highest px-1\">items</code> prop. Items can be links, buttons, or collapsible groups.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4 flex justify-center\">\n <div class=\"w-full max-w-xs bg-surface border border-outline-variant rounded-lg p-2 shadow-sm\">\n <Menu items={menuItems} />\n </div>\n </div>\n </section>\n</div>\n",
162
- "sidebar": "<script lang=\"ts\">\n import { Sidebar, Button } from '$lib/index.js'\n \n let collapsed = $state(false)\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Sidebar</h1>\n <p class=\"text-on-surface-variant\">\n A layout component for application sidebars with built-in collapsible state.\n </p>\n </div>\n\n <!-- Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Usage</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">Sidebar</code> with <code class=\"rounded bg-surface-container-highest px-1\">header</code> and <code class=\"rounded bg-surface-container-highest px-1\">footer</code> snippets. Pass <code class=\"rounded bg-surface-container-highest px-1\">collapsed</code> prop to toggle the expanded state.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4 flex justify-center overflow-hidden\">\n <div class=\"w-full max-w-3xl h-[400px] border border-outline-variant rounded-lg flex overflow-hidden bg-surface-50 dark:bg-surface-900\">\n <Sidebar {collapsed}>\n {#snippet header()}\n <div class=\"p-4 flex items-center justify-between border-b border-outline-variant\">\n {#if !collapsed}\n <span class=\"font-bold text-lg\">Acme Corp</span>\n {/if}\n <Button \n icon={collapsed ? \"lucide:chevron-right\" : \"lucide:chevron-left\"} \n variant=\"ghost\" \n size=\"sm\" \n square \n onclick={() => collapsed = !collapsed} \n class={collapsed ? \"mx-auto\" : \"\"}\n />\n </div>\n {/snippet}\n \n <div class=\"flex-1 overflow-y-auto p-4 space-y-2\">\n {#each Array(4) as _, i}\n <div class=\"h-10 rounded-md bg-surface-container flex items-center px-3\">\n <div class=\"w-5 h-5 bg-surface-300 dark:bg-surface-600 rounded-sm shrink-0\"></div>\n {#if !collapsed}\n <div class=\"ml-3 h-4 bg-surface-300 dark:bg-surface-600 rounded-sm w-24\"></div>\n {/if}\n </div>\n {/each}\n </div>\n \n {#snippet footer()}\n <div class=\"p-4 border-t border-outline-variant flex items-center gap-3\">\n <div class=\"w-8 h-8 rounded-full bg-primary flex items-center justify-center text-primary-content font-bold shrink-0\">\n JD\n </div>\n {#if !collapsed}\n <div class=\"flex-1 overflow-hidden\">\n <div class=\"font-semibold text-sm truncate\">John Doe</div>\n </div>\n {/if}\n </div>\n {/snippet}\n </Sidebar>\n \n <main class=\"flex-1 p-6\">\n <h2 class=\"text-xl font-semibold mb-4\">Main Content Area</h2>\n <p class=\"text-on-surface-variant\">Toggle the sidebar to see it collapse.</p>\n </main>\n </div>\n </div>\n </section>\n</div>\n",
165
+ "sidebar": "<script lang=\"ts\">\n import { Sidebar, Button, NavigationMenu, Avatar, Badge, DropdownMenu } from '$lib/index.js'\n import type { NavigationMenuItemType } from '$lib/NavigationMenu/navigation-menu.types.js'\n \n let isCollapsed = $state(false)\n\n const basicItems: NavigationMenuItemType[] = [\n { label: 'Inbox', icon: 'lucide:inbox', href: '#inbox', badge: 12 },\n { label: 'Sent', icon: 'lucide:send', href: '#sent' },\n { label: 'Drafts', icon: 'lucide:file-text', href: '#drafts' },\n { label: 'Trash', icon: 'lucide:trash-2', href: '#trash' }\n ]\n\n const groupedItems: NavigationMenuItemType[][] = [\n [\n { label: 'Dashboard', icon: 'lucide:home', href: '#home', active: true },\n { label: 'Analytics', icon: 'lucide:bar-chart-2', href: '#analytics' }\n ],\n [\n { label: 'Customers', icon: 'lucide:users', href: '#customers' },\n { label: 'Orders', icon: 'lucide:shopping-cart', href: '#orders', badge: 'New', badgeColor: 'success' },\n { label: 'Products', icon: 'lucide:package', href: '#products' }\n ],\n [\n { label: 'Settings', icon: 'lucide:settings', href: '#settings' },\n { label: 'Help', icon: 'lucide:help-circle', href: '#help' }\n ]\n ]\n</script>\n\n<div class=\"space-y-12 pb-20\">\n <div class=\"space-y-2 border-b border-outline-variant/60 pb-8\">\n <h1 class=\"text-3xl font-bold tracking-tight\">Sidebar</h1>\n <p class=\"text-lg text-on-surface-variant max-w-3xl\">\n A premium layout component with built-in collapsible states, perfect for application shells and dashboards. Integrates seamlessly with <code class=\"rounded bg-surface-container px-1 text-sm\">NavigationMenu</code>.\n </p>\n </div>\n\n <!-- Basic Usage -->\n <section class=\"space-y-4\">\n <h2 class=\"text-xl font-semibold\">Basic</h2>\n <p class=\"text-on-surface-variant text-sm\">A simple sidebar with a header, navigation links, and a footer.</p>\n <div class=\"rounded-xl bg-surface-container-high p-6 flex justify-center overflow-hidden border border-outline-variant/50\">\n <div class=\"w-full max-w-[280px] h-[500px] border border-outline-variant/50 rounded-xl flex overflow-hidden bg-surface dark:bg-surface-900 shadow-sm\">\n <Sidebar>\n {#snippet header()}\n <div class=\"w-full flex items-center gap-3\">\n <div class=\"w-8 h-8 rounded-lg bg-primary text-on-primary flex items-center justify-center font-bold\">A</div>\n <span class=\"font-semibold text-lg\">Acme Corp</span>\n </div>\n {/snippet}\n \n {#snippet children()}\n <div class=\"space-y-1\">\n <NavigationMenu items={basicItems} orientation=\"vertical\" variant=\"ghost\" />\n </div>\n {/snippet}\n \n {#snippet footer()}\n <Button variant=\"soft\" color=\"surface\" class=\"w-full justify-start text-on-surface-variant\">\n {#snippet children()}\n <div class=\"flex items-center gap-3 w-full\">\n <Avatar src=\"https://i.pravatar.cc/150?u=a042581f4e29026704d\" alt=\"User\" size=\"sm\" />\n <span class=\"font-medium text-sm truncate flex-1 text-left\">Alex Doe</span>\n </div>\n {/snippet}\n </Button>\n {/snippet}\n </Sidebar>\n </div>\n </div>\n </section>\n\n <!-- Grouped Sections -->\n <section class=\"space-y-4\">\n <h2 class=\"text-xl font-semibold\">Grouped Sections</h2>\n <p class=\"text-on-surface-variant text-sm\">Pass an array of arrays to <code class=\"rounded bg-surface-container px-1 text-sm\">NavigationMenu</code> inside the sidebar to create distinct groupings.</p>\n <div class=\"rounded-xl bg-surface-container-high p-6 flex justify-center overflow-hidden border border-outline-variant/50\">\n <div class=\"w-full max-w-[280px] h-[600px] border border-outline-variant/50 rounded-xl flex overflow-hidden bg-surface dark:bg-surface-900 shadow-sm\">\n <Sidebar>\n {#snippet children()}\n <div class=\"space-y-6 mt-2\">\n <div>\n <p class=\"px-3 mb-2 text-xs font-semibold text-on-surface-variant uppercase tracking-wider\">Overview</p>\n <NavigationMenu items={groupedItems[0]} orientation=\"vertical\" variant=\"ghost\" />\n </div>\n <div>\n <p class=\"px-3 mb-2 text-xs font-semibold text-on-surface-variant uppercase tracking-wider\">Business</p>\n <NavigationMenu items={groupedItems[1]} orientation=\"vertical\" variant=\"ghost\" />\n </div>\n <div>\n <p class=\"px-3 mb-2 text-xs font-semibold text-on-surface-variant uppercase tracking-wider\">System</p>\n <NavigationMenu items={groupedItems[2]} orientation=\"vertical\" variant=\"ghost\" />\n </div>\n </div>\n {/snippet}\n </Sidebar>\n </div>\n </div>\n </section>\n\n <!-- Collapsible App Shell -->\n <section class=\"space-y-4\">\n <h2 class=\"text-xl font-semibold\">Collapsible App Shell</h2>\n <p class=\"text-on-surface-variant text-sm\">\n Pass <code class=\"rounded bg-surface-container px-1 text-sm\">collapsed</code> to the Sidebar. When collapsed, <code class=\"rounded bg-surface-container px-1 text-sm\">NavigationMenu</code> items instantly convert to perfectly proportioned tooltips! Use the <code class=\"rounded bg-surface-container px-1 text-sm\">{\"{ collapsed }\"}</code> snippet props to conditionally render the header/footer.\n </p>\n <div class=\"rounded-xl bg-surface-container-high p-6 flex justify-center overflow-hidden border border-outline-variant/50\">\n <div class=\"w-full max-w-4xl h-[600px] border border-outline-variant/50 rounded-xl flex overflow-hidden bg-surface dark:bg-surface-900 shadow-xl\">\n <Sidebar collapsed={isCollapsed}>\n {#snippet header({ collapsed: isCol })}\n <div class=\"w-full flex items-center justify-between\">\n {#if !isCol}\n <span class=\"font-bold text-lg flex items-center gap-2\">\n <div class=\"w-7 h-7 rounded-lg bg-primary text-on-primary flex items-center justify-center text-sm\">S</div>\n Svelora\n </span>\n {:else}\n <div class=\"w-8 h-8 rounded-lg bg-primary text-on-primary flex items-center justify-center text-sm font-bold\">S</div>\n {/if}\n </div>\n {/snippet}\n \n {#snippet children()}\n <div class=\"space-y-6\">\n <div>\n {#if !isCollapsed}\n <p class=\"px-3 mb-2 text-xs font-semibold text-on-surface-variant uppercase tracking-wider\">Main Menu</p>\n {/if}\n <NavigationMenu items={basicItems} orientation=\"vertical\" variant=\"ghost\" />\n </div>\n <div>\n {#if !isCollapsed}\n <p class=\"px-3 mb-2 text-xs font-semibold text-on-surface-variant uppercase tracking-wider\">Settings</p>\n {/if}\n <NavigationMenu items={groupedItems[2]} orientation=\"vertical\" variant=\"ghost\" />\n </div>\n </div>\n {/snippet}\n \n {#snippet footer({ collapsed: isCol })}\n <div class=\"w-full flex flex-col gap-3 items-center\">\n <Button \n icon={isCol ? \"lucide:chevron-right\" : \"lucide:chevron-left\"} \n variant=\"outline\" \n color=\"surface\"\n size={isCol ? \"md\" : \"sm\"} \n class={isCol ? \"w-10 h-10 aspect-square p-0\" : \"w-full justify-center\"}\n onclick={() => isCollapsed = !isCollapsed} \n >\n {#if !isCol} Collapse Sidebar {/if}\n </Button>\n\n {#if !isCol}\n <DropdownMenu \n items={[\n { label: 'Profile', icon: 'lucide:user' },\n { label: 'Billing', icon: 'lucide:credit-card' },\n { type: 'separator' },\n { label: 'Log out', icon: 'lucide:log-out' }\n ]}\n align=\"center\"\n >\n {#snippet children({ props })}\n <button {...props} class=\"w-full flex items-center gap-3 p-2 rounded-lg hover:bg-surface-container transition-colors text-left focus:outline-none focus-visible:ring-2 ring-primary\">\n <Avatar src=\"https://i.pravatar.cc/150?u=a042581f4e29026704d\" alt=\"User\" size=\"sm\" />\n <div class=\"flex-1 overflow-hidden\">\n <div class=\"font-semibold text-sm truncate text-on-surface\">Alex Doe</div>\n <div class=\"text-xs text-on-surface-variant truncate\">alex@svelora.com</div>\n </div>\n <div class=\"text-on-surface-variant opacity-50\">\n <iconify-icon icon=\"lucide:chevron-up\" class=\"text-sm\"></iconify-icon>\n </div>\n </button>\n {/snippet}\n </DropdownMenu>\n {:else}\n <Avatar src=\"https://i.pravatar.cc/150?u=a042581f4e29026704d\" alt=\"User\" size=\"sm\" class=\"cursor-pointer\" />\n {/if}\n </div>\n {/snippet}\n </Sidebar>\n \n <main class=\"flex-1 p-8 bg-surface-50 dark:bg-surface-950 flex flex-col\">\n <header class=\"h-10 flex items-center justify-between border-b border-outline-variant/30 mb-8 pb-4\">\n <h2 class=\"text-2xl font-bold\">Dashboard</h2>\n <div class=\"flex gap-2\">\n <Button variant=\"soft\" icon=\"lucide:bell\" square />\n <Button variant=\"solid\" color=\"primary\" label=\"New Project\" icon=\"lucide:plus\" />\n </div>\n </header>\n \n <div class=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\n {#each Array(3) as _, i}\n <div class=\"h-32 rounded-xl bg-surface dark:bg-surface-900 border border-outline-variant/40 shadow-sm p-6 flex flex-col justify-between\">\n <div class=\"w-8 h-8 rounded-full bg-primary/10 text-primary flex items-center justify-center\">\n <iconify-icon icon=\"lucide:activity\"></iconify-icon>\n </div>\n <div>\n <div class=\"text-2xl font-bold\">{(i + 1) * 124}</div>\n <div class=\"text-sm text-on-surface-variant\">Total views</div>\n </div>\n </div>\n {/each}\n </div>\n \n <div class=\"mt-6 flex-1 rounded-xl bg-surface dark:bg-surface-900 border border-outline-variant/40 shadow-sm flex items-center justify-center text-on-surface-variant\">\n Main content area\n </div>\n </main>\n </div>\n </div>\n </section>\n\n <!-- Right Positioned (AI Chat Panel) -->\n <section class=\"space-y-4\">\n <h2 class=\"text-xl font-semibold\">Right Positioned & Responsive</h2>\n <p class=\"text-on-surface-variant text-sm\">\n Pass <code class=\"rounded bg-surface-container px-1 text-sm\">position=\"right\"</code> to dock the sidebar on the right side. The borders and Tooltips automatically adapt! \n <br/><br/>\n <strong>Responsive Design:</strong> Sidebar is purely structural. To hide it on small screens, simply use Tailwind classes like <code class=\"rounded bg-surface-container px-1 text-sm\">hidden md:flex</code> on the Sidebar, and use a <code class=\"rounded bg-surface-container px-1 text-sm\">Drawer</code> component for mobile navigation.\n </p>\n <div class=\"rounded-xl bg-surface-container-high p-6 flex justify-center overflow-hidden border border-outline-variant/50\">\n <div class=\"w-full max-w-4xl h-[500px] border border-outline-variant/50 rounded-xl flex overflow-hidden bg-surface dark:bg-surface-900 shadow-xl relative\">\n \n <main class=\"flex-1 p-8 bg-surface-50 dark:bg-surface-950 flex flex-col\">\n <header class=\"h-10 flex items-center justify-between border-b border-outline-variant/30 mb-8 pb-4\">\n <h2 class=\"text-2xl font-bold\">Workspace</h2>\n <div class=\"flex gap-2\">\n <!-- Mobile toggle button (hidden on desktop) -->\n <Button variant=\"soft\" icon=\"lucide:menu\" class=\"md:hidden\" />\n </div>\n </header>\n <div class=\"flex-1 border-2 border-dashed border-outline-variant/30 rounded-xl flex items-center justify-center text-on-surface-variant\">\n Main Canvas Area\n </div>\n </main>\n\n <!-- Sidebar on the right, hidden on mobile -->\n <Sidebar position=\"right\" collapsed={isCollapsed} class=\"hidden md:flex\">\n {#snippet header({ collapsed: isCol })}\n <div class=\"w-full flex items-center justify-between\">\n {#if !isCol}\n <span class=\"font-bold text-lg\">AI Chat</span>\n <Button variant=\"ghost\" icon=\"lucide:x\" size=\"sm\" square />\n {:else}\n <div class=\"w-8 h-8 rounded-lg bg-surface-container-high flex items-center justify-center\">\n <iconify-icon icon=\"lucide:bot\" class=\"text-xl\"></iconify-icon>\n </div>\n {/if}\n </div>\n {/snippet}\n \n {#snippet children({ collapsed: isCol })}\n {#if !isCol}\n <div class=\"flex-1 flex flex-col justify-end p-4\">\n <div class=\"bg-surface-container-high rounded-lg p-3 text-sm text-on-surface mb-4 self-end max-w-[85%]\">\n What is Nuxt UI?\n </div>\n <div class=\"text-sm text-on-surface-variant leading-relaxed\">\n Nuxt UI is a Vue component library built on Tailwind CSS... But Svelora is the Svelte equivalent with premium aesthetics!\n </div>\n </div>\n {:else}\n <div class=\"flex-1 flex flex-col gap-4 mt-4\">\n <NavigationMenu items={[\n { label: 'Chat History', icon: 'lucide:message-square' },\n { label: 'Summarize', icon: 'lucide:file-text' },\n { label: 'Code Gen', icon: 'lucide:code' }\n ]} orientation=\"vertical\" variant=\"ghost\" />\n </div>\n {/if}\n {/snippet}\n \n {#snippet footer({ collapsed: isCol })}\n <div class=\"w-full flex gap-2\">\n {#if !isCol}\n <div class=\"flex-1 flex items-center bg-surface-container rounded-lg px-3 py-2 border border-outline-variant/50\">\n <input type=\"text\" placeholder=\"Ask AI...\" class=\"bg-transparent border-none outline-none text-sm w-full\" />\n <iconify-icon icon=\"lucide:arrow-up-circle\" class=\"text-primary text-xl ml-2\"></iconify-icon>\n </div>\n {:else}\n <Button \n icon=\"lucide:chevron-left\" \n variant=\"outline\" \n size=\"md\" \n class=\"w-10 h-10 aspect-square p-0\"\n onclick={() => isCollapsed = !isCollapsed} \n />\n {/if}\n </div>\n {/snippet}\n </Sidebar>\n </div>\n </div>\n </section>\n</div>\n",
163
166
  "stepper": "<script lang=\"ts\">\n import {\n Stepper,\n Badge,\n Button,\n Icon,\n Separator,\n Form,\n FormField,\n Input,\n Textarea,\n Checkbox,\n type StepperItem,\n type StepperApi,\n type FormApi\n } from '$lib/index.js'\n\n const basicItems: StepperItem[] = [\n { value: 'address', title: 'Address', description: 'Enter shipping address' },\n { value: 'shipping', title: 'Shipping', description: 'Pick a carrier' },\n { value: 'payment', title: 'Payment', description: 'Add a card' },\n { value: 'review', title: 'Review', description: 'Confirm and place order' }\n ]\n\n const iconItems: StepperItem[] = [\n { value: 'cart', title: 'Cart', icon: 'lucide:shopping-cart' },\n { value: 'address', title: 'Address', icon: 'lucide:map-pin' },\n { value: 'shipping', title: 'Shipping', icon: 'lucide:truck' },\n { value: 'payment', title: 'Payment', icon: 'lucide:credit-card' },\n { value: 'done', title: 'Done', icon: 'lucide:check' }\n ]\n\n const compactItems: StepperItem[] = [\n { value: 1, title: 'Plan' },\n { value: 2, title: 'Build' },\n { value: 3, title: 'Ship' }\n ]\n\n const colors = [\n 'primary',\n 'secondary',\n 'tertiary',\n 'success',\n 'warning',\n 'error',\n 'info',\n 'surface'\n ] as const\n\n // Controlled with bind:value\n let controlledValue = $state<string | number>('address')\n let lastChange = $state('')\n\n // Imperative API wizard\n let apiValue = $state<string | number>('address')\n let api = $state<StepperApi>()\n\n // Linear vs free\n let linearValue = $state<string | number>('address')\n let freeValue = $state<string | number>('address')\n\n // Custom snippet demos\n let snippetValue = $state<string | number>('shipping')\n\n // -----------------------------------------------------------------\n // Form-driven wizard — each step validates before advancing.\n // -----------------------------------------------------------------\n type WizardData = {\n // step 1\n firstName: string\n lastName: string\n email: string\n // step 2\n address: string\n city: string\n zip: string\n // step 3\n notes: string\n consent: boolean\n }\n\n const wizardSteps: StepperItem[] = [\n {\n value: 'account',\n title: 'Account',\n description: 'Who is ordering',\n icon: 'lucide:user'\n },\n {\n value: 'shipping',\n title: 'Shipping',\n description: 'Where to deliver',\n icon: 'lucide:map-pin'\n },\n {\n value: 'review',\n title: 'Review',\n description: 'Confirm and submit',\n icon: 'lucide:clipboard-check'\n }\n ]\n\n const wizardState = $state<WizardData>({\n firstName: '',\n lastName: '',\n email: '',\n address: '',\n city: '',\n zip: '',\n notes: '',\n consent: false\n })\n\n let wizardValue = $state<string | number>('account')\n let wizardApi = $state<StepperApi>()\n let wizardForm = $state<FormApi<unknown>>()\n let wizardSubmitted = $state<string | null>(null)\n\n const STEP_FIELDS: Record<string, (keyof WizardData)[]> = {\n account: ['firstName', 'lastName', 'email'],\n shipping: ['address', 'city', 'zip'],\n review: ['consent']\n }\n\n function validateRequired(field: keyof WizardData) {\n const value = wizardState[field]\n if (typeof value === 'boolean') return value ? null : 'Required'\n if (typeof value === 'string' && value.trim().length === 0) return 'Required'\n if (field === 'email' && typeof value === 'string' && !/.+@.+\\..+/.test(value)) {\n return 'Invalid email'\n }\n return null\n }\n\n function validateCurrentStep(): boolean {\n const fields = STEP_FIELDS[String(wizardValue)] ?? []\n const errors: { name: string; message: string }[] = []\n for (const f of fields) {\n const err = validateRequired(f)\n if (err) errors.push({ name: String(f), message: err })\n else wizardForm?.clear(String(f))\n }\n if (errors.length > 0) {\n wizardForm?.setErrors(errors)\n return false\n }\n return true\n }\n\n function handleWizardNext() {\n if (!validateCurrentStep()) return\n wizardApi?.next()\n }\n\n function handleWizardSubmit() {\n if (!validateCurrentStep()) return\n wizardSubmitted = JSON.stringify(wizardState, null, 2)\n }\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Stepper</h1>\n <p class=\"text-on-surface-variant\">\n A wizard-style progress indicator for multi-step flows. Renders a sequential list of\n steps with <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >pending</code\n >\n /\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">active</code> /\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">completed</code\n >\n states. Pure custom build — no bits-ui primitive.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Pass <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >items</code\n >\n and the Stepper renders progress with sensible defaults.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <Stepper items={basicItems} />\n </div>\n </section>\n\n <!-- Orientation -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Orientation</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Switch between\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >horizontal</code\n >\n (default) and\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">vertical</code> layout.\n </p>\n <div class=\"grid gap-4 lg:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-4 text-sm font-medium\">Horizontal</p>\n <Stepper items={basicItems} value=\"shipping\" content={false} />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-4 text-sm font-medium\">Vertical</p>\n <Stepper\n items={basicItems}\n orientation=\"vertical\"\n value=\"shipping\"\n content={false}\n />\n </div>\n </div>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Five sizes scale indicator and typography together.\n </p>\n <div class=\"space-y-4\">\n {#each ['xs', 'sm', 'md', 'lg', 'xl'] as const as size (size)}\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-xs font-medium tracking-wide uppercase\">{size}</p>\n <Stepper items={compactItems} value={2} {size} content={false} linear={false} />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Colors -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Colors</h2>\n <p class=\"text-sm text-on-surface-variant\">\n The <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">color</code\n >\n prop tints the indicator, separator, and active title.\n </p>\n <div class=\"grid gap-4 md:grid-cols-2\">\n {#each colors as color (color)}\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-xs font-medium capitalize\">{color}</p>\n <Stepper\n items={compactItems}\n value={2}\n {color}\n content={false}\n linear={false}\n />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Icons -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Icons</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Set <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">icon</code>\n on an item to replace the default number indicator. Completed steps automatically show a check\n icon when no\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">icon</code> is set.\n </p>\n <div class=\"grid gap-4 lg:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">Per-item icons (horizontal)</p>\n <Stepper items={iconItems} value=\"shipping\" content={false} linear={false} />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">Per-item icons (vertical)</p>\n <Stepper\n items={iconItems}\n value=\"shipping\"\n content={false}\n orientation=\"vertical\"\n linear={false}\n />\n </div>\n </div>\n </section>\n\n <!-- Linear vs Free -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Linear vs Free Navigation</h2>\n <p class=\"text-sm text-on-surface-variant\">\n By default Stepper is <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">linear</code\n >: a click can only advance one step ahead. Set\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >linear={'{false}'}</code\n >\n to allow jumping anywhere.\n </p>\n <div class=\"grid gap-4 lg:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">\n Linear (default) · Current: <Badge variant=\"soft\" label={String(linearValue)} />\n </p>\n <Stepper items={basicItems} bind:value={linearValue} content={false} />\n <p class=\"mt-3 text-xs text-on-surface-variant\">\n Click any step — only the immediate next one (and prior ones) responds.\n </p>\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">\n Free · Current: <Badge variant=\"soft\" color=\"info\" label={String(freeValue)} />\n </p>\n <Stepper items={basicItems} bind:value={freeValue} content={false} linear={false} />\n <p class=\"mt-3 text-xs text-on-surface-variant\">\n Click any step to jump there directly.\n </p>\n </div>\n </div>\n </section>\n\n <!-- Disabled -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Disabled</h2>\n <div class=\"grid gap-4 lg:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">All steps disabled</p>\n <Stepper items={basicItems} disabled content={false} />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">Per-item disabled</p>\n <Stepper\n items={[\n { value: 'a', title: 'Open', description: 'Free' },\n {\n value: 'b',\n title: 'Locked',\n description: 'Premium only',\n disabled: true\n },\n { value: 'c', title: 'Open', description: 'Free' }\n ]}\n linear={false}\n content={false}\n />\n </div>\n </div>\n </section>\n\n <!-- Imperative API -->\n <section class=\"space-y-3\">\n <div class=\"flex flex-wrap items-baseline justify-between gap-2\">\n <h2 class=\"text-lg font-semibold\">Imperative API — bind:api</h2>\n <p class=\"text-xs text-on-surface-variant\">\n Drive the Stepper from outside with Back / Next buttons.\n </p>\n </div>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-6\">\n <Stepper items={basicItems} bind:api bind:value={apiValue}>\n {#snippet body({ item })}\n <div\n class=\"flex items-start gap-3 rounded-lg border border-outline-variant bg-surface-container p-4\"\n >\n <Icon name=\"lucide:info\" size=\"18\" class=\"mt-0.5 shrink-0 text-primary\" />\n <div>\n <p class=\"text-sm font-medium\">{item.title}</p>\n <p class=\"text-sm text-on-surface-variant\">\n {item.description}\n </p>\n </div>\n </div>\n {/snippet}\n </Stepper>\n <div class=\"flex flex-wrap items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n leadingIcon=\"lucide:chevron-left\"\n label=\"Back\"\n disabled={!api?.hasPrev}\n onclick={() => api?.prev()}\n />\n <Button\n color=\"primary\"\n size=\"sm\"\n trailingIcon=\"lucide:chevron-right\"\n label={api?.hasNext ? 'Next' : 'Done'}\n disabled={!api?.hasNext}\n onclick={() => api?.next()}\n />\n <span class=\"ms-auto text-xs text-on-surface-variant\">\n Step {(api?.activeIndex ?? 0) + 1} of {basicItems.length}\n </span>\n </div>\n </div>\n </section>\n\n <!-- Controlled -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Controlled — bind:value</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Two-way bind to drive Stepper from any UI; useful when navigation lives elsewhere on the\n page.\n </p>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-6\">\n <p class=\"text-sm font-medium\">\n Active: <Badge variant=\"soft\" color=\"info\" label={String(controlledValue)} />\n </p>\n <div class=\"flex flex-wrap gap-2\">\n {#each basicItems as item (item.value)}\n <Button\n size=\"xs\"\n variant={controlledValue === item.value ? 'solid' : 'outline'}\n label={item.title}\n onclick={() => (controlledValue = item.value ?? '')}\n />\n {/each}\n </div>\n <Stepper items={basicItems} bind:value={controlledValue} content={false} />\n </div>\n </section>\n\n <!-- Callback -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">onValueChange Callback</h2>\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm\">\n Last change:\n <Badge\n variant=\"soft\"\n color={lastChange ? 'success' : 'surface'}\n label={lastChange || 'None'}\n />\n </p>\n <Stepper\n items={basicItems}\n onValueChange={(v) => (lastChange = `Switched to: ${v}`)}\n content={false}\n />\n </div>\n </section>\n\n <!-- Custom Snippets -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Snippets</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Override\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">indicator</code\n >,\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">titleSlot</code\n >,\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >descriptionSlot</code\n >, or\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">body</code> for custom\n rendering.\n </p>\n <div class=\"grid gap-4 lg:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">Custom indicator</p>\n <Stepper items={basicItems} value=\"shipping\" content={false} linear={false}>\n {#snippet indicator({ number, state })}\n <span\n class=\"inline-flex size-8 items-center justify-center rounded-full text-sm font-bold {state ===\n 'completed'\n ? 'bg-success text-on-success'\n : state === 'active'\n ? 'bg-primary text-on-primary ring-4 ring-primary/20'\n : 'border-2 border-dashed border-outline-variant text-on-surface-variant'}\"\n aria-hidden=\"true\"\n >\n {#if state === 'completed'}\n <Icon name=\"lucide:check\" size=\"16\" />\n {:else}\n {number}\n {/if}\n </span>\n {/snippet}\n </Stepper>\n </div>\n\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">Custom title with badge</p>\n <Stepper items={basicItems} value=\"shipping\" content={false} linear={false}>\n {#snippet titleSlot({ item, state })}\n <span class=\"inline-flex items-center gap-1.5 text-sm font-medium\">\n {item.title}\n {#if state === 'active'}\n <Badge size=\"xs\" variant=\"soft\" color=\"primary\" label=\"Now\" />\n {:else if state === 'completed'}\n <Badge size=\"xs\" variant=\"soft\" color=\"success\" label=\"Done\" />\n {/if}\n </span>\n {/snippet}\n </Stepper>\n </div>\n\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">Custom body</p>\n <Stepper items={basicItems} bind:value={snippetValue}>\n {#snippet body({ item, number })}\n <div\n class=\"flex items-start gap-3 rounded-lg border border-outline-variant bg-surface-container p-4\"\n >\n <div\n class=\"flex size-10 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary\"\n >\n <Icon name=\"lucide:sparkles\" size=\"20\" />\n </div>\n <div>\n <p class=\"text-sm font-semibold\">\n Step {number}: {item.title}\n </p>\n <p class=\"text-sm text-on-surface-variant\">\n Body snippet renders anywhere below the progress bar.\n </p>\n </div>\n </div>\n {/snippet}\n </Stepper>\n </div>\n\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">Custom description</p>\n <Stepper items={basicItems} value=\"shipping\" content={false} linear={false}>\n {#snippet descriptionSlot({ item, state })}\n <span\n class=\"text-xs {state === 'pending'\n ? 'text-on-surface-variant/60 italic'\n : 'text-on-surface-variant'}\"\n >\n {state === 'completed' ? '✓ ' : ''}{item.description}\n </span>\n {/snippet}\n </Stepper>\n </div>\n </div>\n </section>\n\n <!-- UI Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Overrides</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Override slot styles via the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">ui</code> prop,\n or per-item via\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >items[i].ui</code\n >.\n </p>\n <div class=\"grid gap-4 lg:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">Square indicators</p>\n <Stepper\n items={compactItems}\n value={2}\n content={false}\n linear={false}\n ui={{ indicator: 'rounded-md' }}\n />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">Thicker separator</p>\n <Stepper\n items={compactItems}\n value={2}\n content={false}\n linear={false}\n ui={{ separator: 'h-1' }}\n />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">Bold titles</p>\n <Stepper\n items={basicItems}\n value=\"shipping\"\n content={false}\n linear={false}\n ui={{ title: 'font-bold uppercase tracking-wider' }}\n />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <p class=\"mb-3 text-sm font-medium\">Per-item override</p>\n <Stepper\n items={[\n { value: 'a', title: 'Standard', description: 'Normal item' },\n {\n value: 'b',\n title: 'Spotlight',\n description: 'Highlighted',\n ui: { indicator: 'ring-4 ring-warning/40' }\n },\n { value: 'c', title: 'Standard', description: 'Normal item' }\n ]}\n value=\"b\"\n content={false}\n linear={false}\n />\n </div>\n </div>\n </section>\n\n <Separator />\n\n <!-- Real World Example: Form Wizard -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World — Form Wizard</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Multi-step form with per-step validation. The Next button calls a custom validator\n before invoking\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >api.next()</code\n >.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <Stepper\n items={wizardSteps}\n bind:api={wizardApi}\n bind:value={wizardValue}\n color=\"primary\"\n >\n {#snippet body({ item })}\n <Form\n bind:api={wizardForm}\n state={wizardState}\n onsubmit={handleWizardSubmit}\n class=\"space-y-4 rounded-lg border border-outline-variant bg-surface-container p-5\"\n >\n {#if item.value === 'account'}\n <div class=\"space-y-4\">\n <h3 class=\"text-base font-semibold\">Tell us about yourself</h3>\n <div class=\"grid gap-3 sm:grid-cols-2\">\n <FormField name=\"firstName\" label=\"First name\" required>\n <Input bind:value={wizardState.firstName} />\n </FormField>\n <FormField name=\"lastName\" label=\"Last name\" required>\n <Input bind:value={wizardState.lastName} />\n </FormField>\n </div>\n <FormField name=\"email\" label=\"Email\" required>\n <Input type=\"email\" bind:value={wizardState.email} />\n </FormField>\n </div>\n {:else if item.value === 'shipping'}\n <div class=\"space-y-4\">\n <h3 class=\"text-base font-semibold\">Shipping address</h3>\n <FormField name=\"address\" label=\"Street address\" required>\n <Input bind:value={wizardState.address} />\n </FormField>\n <div class=\"grid gap-3 sm:grid-cols-2\">\n <FormField name=\"city\" label=\"City\" required>\n <Input bind:value={wizardState.city} />\n </FormField>\n <FormField name=\"zip\" label=\"ZIP\" required>\n <Input bind:value={wizardState.zip} />\n </FormField>\n </div>\n <FormField name=\"notes\" label=\"Delivery notes (optional)\">\n <Textarea bind:value={wizardState.notes} rows={2} />\n </FormField>\n </div>\n {:else}\n <div class=\"space-y-4\">\n <h3 class=\"text-base font-semibold\">Review</h3>\n <div\n class=\"space-y-2 rounded-lg bg-surface-container-highest p-3 text-sm\"\n >\n <div>\n <span class=\"text-on-surface-variant\">Name:</span>\n <span class=\"font-medium\"\n >{wizardState.firstName}\n {wizardState.lastName}</span\n >\n </div>\n <div>\n <span class=\"text-on-surface-variant\">Email:</span>\n <span class=\"font-medium\">{wizardState.email}</span>\n </div>\n <div>\n <span class=\"text-on-surface-variant\">Address:</span>\n <span class=\"font-medium\"\n >{wizardState.address}, {wizardState.city}\n {wizardState.zip}</span\n >\n </div>\n {#if wizardState.notes}\n <div>\n <span class=\"text-on-surface-variant\">Notes:</span>\n <span class=\"font-medium\">{wizardState.notes}</span>\n </div>\n {/if}\n </div>\n <FormField name=\"consent\" required>\n <label class=\"flex items-start gap-2 text-sm\">\n <Checkbox bind:checked={wizardState.consent} />\n I confirm the details above are correct.\n </label>\n </FormField>\n </div>\n {/if}\n\n <div class=\"flex flex-wrap items-center gap-2 pt-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n leadingIcon=\"lucide:chevron-left\"\n label=\"Back\"\n disabled={!wizardApi?.hasPrev}\n onclick={() => wizardApi?.prev()}\n />\n {#if wizardApi?.hasNext}\n <Button\n color=\"primary\"\n size=\"sm\"\n trailingIcon=\"lucide:chevron-right\"\n label=\"Next\"\n onclick={handleWizardNext}\n />\n {:else}\n <Button\n color=\"success\"\n size=\"sm\"\n leadingIcon=\"lucide:check\"\n label=\"Submit\"\n type=\"submit\"\n />\n {/if}\n <span class=\"ms-auto text-xs text-on-surface-variant\">\n Step {(wizardApi?.activeIndex ?? 0) + 1} of {wizardSteps.length}\n </span>\n </div>\n </Form>\n {/snippet}\n </Stepper>\n\n {#if wizardSubmitted}\n <div class=\"mt-4 rounded-lg border border-success/40 bg-success/10 p-4 text-sm\">\n <div class=\"mb-2 flex items-center gap-2 font-semibold text-success\">\n <Icon name=\"lucide:party-popper\" size=\"18\" />\n Submitted!\n </div>\n <pre\n class=\"overflow-x-auto text-xs whitespace-pre-wrap text-on-surface-variant\">{wizardSubmitted}</pre>\n </div>\n {/if}\n </div>\n </section>\n\n <!-- Real World Example: Onboarding -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World — Onboarding Checklist</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Vertical Stepper with rich descriptions and inline actions per step.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-6\">\n <Stepper\n items={[\n {\n value: 'profile',\n title: 'Complete your profile',\n description: 'Add a photo and bio so teammates recognize you.',\n icon: 'lucide:user-circle'\n },\n {\n value: 'team',\n title: 'Invite your team',\n description: 'Bring teammates so you can collaborate from day one.',\n icon: 'lucide:users'\n },\n {\n value: 'integrate',\n title: 'Connect your tools',\n description: 'GitHub, Slack, Linear — wire everything in one click.',\n icon: 'lucide:plug'\n },\n {\n value: 'done',\n title: 'You are ready',\n description: 'Explore the dashboard or start your first project.',\n icon: 'lucide:rocket'\n }\n ]}\n orientation=\"vertical\"\n value=\"team\"\n color=\"success\"\n linear={false}\n >\n {#snippet body({ item, state, active })}\n {#if active}\n <div\n class=\"mt-2 flex items-center gap-2 rounded-lg border border-outline-variant bg-surface-container p-3\"\n >\n <Icon name={item.icon ?? 'lucide:zap'} size=\"18\" class=\"text-primary\" />\n <span class=\"text-sm\">Continue with this step</span>\n <Button\n class=\"ms-auto\"\n size=\"xs\"\n color=\"primary\"\n label={state === 'completed' ? 'Revisit' : 'Continue'}\n />\n </div>\n {/if}\n {/snippet}\n </Stepper>\n </div>\n </section>\n</div>\n",
164
167
  "tabs": "<script lang=\"ts\">\n import { Tabs, Badge, Button, Icon, Separator } from '$lib/index.js'\n import type { TabsItem } from '$lib/index.js'\n\n const basicItems: TabsItem[] = [\n {\n label: 'Account',\n content: 'Manage your account settings and preferences.',\n value: 'account'\n },\n {\n label: 'Password',\n content: 'Change your password and security keys.',\n value: 'password'\n },\n {\n label: 'Notifications',\n content: 'Configure notification preferences.',\n value: 'notifications'\n }\n ]\n\n const iconItems: TabsItem[] = [\n {\n label: 'Profile',\n icon: 'lucide:user',\n content: 'Update your profile information.',\n value: 'profile'\n },\n {\n label: 'Security',\n icon: 'lucide:shield',\n content: 'Manage security settings.',\n value: 'security'\n },\n {\n label: 'Billing',\n icon: 'lucide:credit-card',\n content: 'View invoices and payments.',\n value: 'billing'\n },\n {\n label: 'Integrations',\n icon: 'lucide:plug',\n content: 'Connect third-party services.',\n value: 'integrations'\n }\n ]\n\n const disabledItems: TabsItem[] = [\n { label: 'General', content: 'General settings.', value: 'general' },\n { label: 'Advanced', content: 'Requires premium.', value: 'advanced', disabled: true },\n { label: 'About', content: 'Version and license info.', value: 'about' }\n ]\n\n const colors = [\n 'primary',\n 'secondary',\n 'tertiary',\n 'success',\n 'warning',\n 'error',\n 'info',\n 'surface'\n ] as const\n\n let controlledValue = $state('account')\n let lastChange = $state('')\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Tabs</h1>\n <p class=\"text-on-surface-variant\">\n A set of layered panels of content, where only one panel is visible at a time. Built on\n bits-ui Tabs primitive.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Tabs items={basicItems} />\n </div>\n </section>\n\n <!-- Variants -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >variant</code\n >\n to switch between pill and link styles.\n </p>\n <div class=\"grid gap-4 md:grid-cols-2\">\n {#each [{ variant: 'pill' as const, label: 'Pill (default)' }, { variant: 'link' as const, label: 'Link' }] as item (item.variant)}\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">{item.label}</p>\n <Tabs items={basicItems} variant={item.variant} />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Colors -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Colors</h2>\n <p class=\"text-sm text-on-surface-variant\">\n The <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">color</code\n >\n prop controls the indicator and active text color.\n </p>\n <div class=\"space-y-4\">\n {#each ['pill', 'link'] as variant (variant)}\n <div>\n <p class=\"mb-3 text-sm font-medium capitalize\">{variant} variant</p>\n <div class=\"grid gap-4 md:grid-cols-2\">\n {#each colors as color (color)}\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-2 text-xs font-medium capitalize\">{color}</p>\n <Tabs\n items={basicItems}\n {color}\n variant={variant as 'pill' | 'link'}\n content={false}\n />\n </div>\n {/each}\n </div>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <div class=\"space-y-4\">\n {#each ['xs', 'sm', 'md', 'lg', 'xl'] as const as size (size)}\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-2 text-xs font-medium uppercase\">{size}</p>\n <Tabs items={basicItems} {size} content={false} />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- With Icons -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">With Icons</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Add leading icons via the <code\n class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">icon</code\n >\n property on each item.\n </p>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Pill</p>\n <Tabs items={iconItems} />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Link</p>\n <Tabs items={iconItems} variant=\"link\" />\n </div>\n </div>\n </section>\n\n <!-- Orientation -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Orientation</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Set <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >orientation=\"vertical\"</code\n >\n for vertical layout.\n </p>\n <div class=\"grid gap-4 lg:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Vertical - Pill</p>\n <Tabs items={iconItems} orientation=\"vertical\" />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Vertical - Link</p>\n <Tabs items={iconItems} orientation=\"vertical\" variant=\"link\" />\n </div>\n </div>\n </section>\n\n <!-- Disabled -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Disabled</h2>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">All disabled</p>\n <Tabs items={basicItems} disabled />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Individual disabled</p>\n <Tabs items={disabledItems} />\n </div>\n </div>\n </section>\n\n <!-- Content -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">No Content</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Set <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >content={'{false}'}</code\n >\n to use tabs purely for navigation.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Tabs\n items={[\n { label: 'Overview', value: 'overview' },\n { label: 'Tasks', value: 'tasks' },\n { label: 'Files', value: 'files' },\n { label: 'Members', value: 'members' },\n { label: 'Settings', value: 'settings' },\n { label: 'Activity', value: 'activity' }\n ]}\n content={false}\n />\n </div>\n </section>\n\n <!-- Controlled -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Controlled</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Bind <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >value</code\n >\n to control the active tab programmatically.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">\n Active: <Badge variant=\"soft\" color=\"info\" label={controlledValue} />\n </p>\n <div class=\"mb-3 flex gap-2\">\n {#each basicItems as item (item.value)}\n <Button\n size=\"xs\"\n variant={controlledValue === item.value ? 'solid' : 'outline'}\n label={item.label}\n onclick={() => (controlledValue = item.value ?? '')}\n />\n {/each}\n </div>\n <Tabs items={basicItems} bind:value={controlledValue} />\n </div>\n </section>\n\n <!-- Callback -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Value Change Callback</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >onValueChange</code\n >\n to react to tab changes.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm\">\n Last change: <Badge\n variant=\"soft\"\n color={lastChange ? 'success' : 'surface'}\n label={lastChange || 'None'}\n />\n </p>\n <Tabs items={basicItems} onValueChange={(v) => (lastChange = `Switched to: ${v}`)} />\n </div>\n </section>\n\n <!-- Custom Slots -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Slots</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use snippets for custom rendering:\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">leading</code>,\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">label</code>,\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">trailing</code\n >,\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">body</code>.\n </p>\n <div class=\"grid gap-4 lg:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Custom leading</p>\n <Tabs items={basicItems} variant=\"link\">\n {#snippet leading({ active })}\n <div\n class=\"flex size-6 items-center justify-center rounded-full {active\n ? 'bg-primary text-on-primary'\n : 'bg-surface-container-highest'}\"\n >\n <Icon name={active ? 'lucide:check' : 'lucide:circle'} size=\"14\" />\n </div>\n {/snippet}\n </Tabs>\n </div>\n\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Custom label with badge</p>\n <Tabs items={basicItems}>\n {#snippet label({ item })}\n <span class=\"flex items-center gap-1.5\">\n {item.label}\n {#if item.value === 'account'}\n <Badge size=\"xs\" variant=\"soft\" color=\"primary\" label=\"New\" />\n {/if}\n </span>\n {/snippet}\n </Tabs>\n </div>\n\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Custom trailing</p>\n <Tabs items={basicItems} variant=\"link\">\n {#snippet trailing({ item })}\n {#if item.value === 'notifications'}\n <Badge size=\"xs\" variant=\"soft\" color=\"error\" label=\"3\" />\n {/if}\n {/snippet}\n </Tabs>\n </div>\n\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Custom body</p>\n <Tabs items={basicItems}>\n {#snippet body({ item })}\n <div class=\"flex items-start gap-3 rounded-lg bg-surface-container p-4\">\n <Icon\n name=\"lucide:info\"\n size=\"18\"\n class=\"mt-0.5 shrink-0 text-primary\"\n />\n <div>\n <p class=\"text-sm font-medium\">{item.label}</p>\n <p class=\"text-sm text-on-surface-variant\">{item.content}</p>\n </div>\n </div>\n {/snippet}\n </Tabs>\n </div>\n </div>\n </section>\n\n <!-- Per-Item Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Per-Item Overrides</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Each item supports\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">class</code>\n and\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">ui</code>\n overrides.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Tabs\n items={[\n { label: 'Normal', content: 'Standard styling.', value: 'normal' },\n { label: 'Bold', content: 'Custom class.', value: 'bold', class: 'font-bold' },\n {\n label: 'Italic',\n content: 'Custom ui.',\n value: 'italic',\n ui: { trigger: 'italic' }\n }\n ]}\n variant=\"link\"\n />\n </div>\n </section>\n\n <!-- UI Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Overrides</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Override slot styles via the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">ui</code> prop.\n </p>\n <div class=\"grid gap-4 sm:grid-cols-2\">\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-2 text-sm font-medium text-on-surface-variant\">\n Custom list background\n </p>\n <Tabs\n items={basicItems}\n ui={{ list: 'bg-surface-container-highest rounded-xl' }}\n content={false}\n />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-2 text-sm font-medium text-on-surface-variant\">Rounded indicator</p>\n <Tabs items={basicItems} ui={{ indicator: 'rounded-full' }} content={false} />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-2 text-sm font-medium text-on-surface-variant\">Bold triggers</p>\n <Tabs\n items={basicItems}\n ui={{ trigger: 'font-bold uppercase tracking-wide' }}\n content={false}\n />\n </div>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-2 text-sm font-medium text-on-surface-variant\">Custom content</p>\n <Tabs\n items={basicItems}\n ui={{\n content:\n 'mt-3 p-4 bg-surface-container rounded-lg border border-outline-variant'\n }}\n />\n </div>\n </div>\n </section>\n\n <Separator />\n\n <!-- Real World Examples -->\n <section class=\"space-y-6\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n\n <div class=\"space-y-4\">\n <!-- Settings Page -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">Settings Page</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <div class=\"mb-4\">\n <h3 class=\"font-semibold text-on-surface\">Settings</h3>\n <p class=\"text-sm text-on-surface-variant\">\n Manage your account settings and preferences.\n </p>\n </div>\n <Tabs items={iconItems} variant=\"link\" color=\"primary\">\n {#snippet body({ item })}\n <div class=\"space-y-4 rounded-lg bg-surface-container p-4\">\n {#if item.value === 'profile'}\n <div class=\"flex items-center gap-4\">\n <div\n class=\"flex size-16 items-center justify-center rounded-full bg-primary/10\"\n >\n <Icon\n name=\"lucide:user\"\n size=\"32\"\n class=\"text-primary\"\n />\n </div>\n <div class=\"flex-1\">\n <h4 class=\"font-semibold\">John Doe</h4>\n <p class=\"text-sm text-on-surface-variant\">\n john.doe@example.com\n </p>\n </div>\n <Button\n size=\"sm\"\n variant=\"outline\"\n leadingIcon=\"lucide:pencil\"\n label=\"Edit\"\n />\n </div>\n {:else if item.value === 'security'}\n <div class=\"space-y-3\">\n <div\n class=\"flex items-center justify-between rounded-lg bg-surface-container-highest p-3\"\n >\n <div class=\"flex items-center gap-3\">\n <Icon\n name=\"lucide:shield-check\"\n size=\"20\"\n class=\"text-success\"\n />\n <div>\n <p class=\"text-sm font-medium\">\n Two-Factor Authentication\n </p>\n <p class=\"text-xs text-on-surface-variant\">\n Add an extra layer of security\n </p>\n </div>\n </div>\n <Badge\n variant=\"soft\"\n color=\"success\"\n size=\"xs\"\n label=\"Enabled\"\n />\n </div>\n <div\n class=\"flex items-center justify-between rounded-lg bg-surface-container-highest p-3\"\n >\n <div class=\"flex items-center gap-3\">\n <Icon\n name=\"lucide:key\"\n size=\"20\"\n class=\"text-warning\"\n />\n <div>\n <p class=\"text-sm font-medium\">Password</p>\n <p class=\"text-xs text-on-surface-variant\">\n Last changed 30 days ago\n </p>\n </div>\n </div>\n <Button size=\"xs\" variant=\"outline\" label=\"Change\" />\n </div>\n </div>\n {:else if item.value === 'billing'}\n <div class=\"grid grid-cols-3 gap-3\">\n {#each [{ value: 'Pro', label: 'Current Plan', color: 'text-primary' }, { value: '$29', label: 'Monthly', color: 'text-success' }, { value: 'Mar 15', label: 'Next Billing', color: 'text-on-surface' }] as stat (stat.label)}\n <div\n class=\"rounded-lg bg-surface-container-highest p-3 text-center\"\n >\n <p class=\"text-2xl font-bold {stat.color}\">\n {stat.value}\n </p>\n <p class=\"text-xs text-on-surface-variant\">\n {stat.label}\n </p>\n </div>\n {/each}\n </div>\n {:else}\n <div class=\"space-y-2\">\n {#each [{ name: 'GitHub', icon: 'lucide:github', connected: true }, { name: 'Slack', icon: 'lucide:slack', connected: false }] as svc (svc.name)}\n <div\n class=\"flex items-center justify-between rounded-lg bg-surface-container-highest p-3\"\n >\n <div class=\"flex items-center gap-3\">\n <Icon name={svc.icon} size=\"20\" />\n <span class=\"text-sm font-medium\"\n >{svc.name}</span\n >\n </div>\n {#if svc.connected}\n <Badge\n variant=\"soft\"\n color=\"success\"\n size=\"xs\"\n label=\"Connected\"\n />\n {:else}\n <Button\n size=\"xs\"\n variant=\"outline\"\n label=\"Connect\"\n />\n {/if}\n </div>\n {/each}\n </div>\n {/if}\n </div>\n {/snippet}\n </Tabs>\n </div>\n </div>\n\n <!-- Dashboard -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">Dashboard Tabs</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Tabs\n items={[\n {\n label: 'Overview',\n icon: 'lucide:layout-dashboard',\n value: 'overview'\n },\n { label: 'Analytics', icon: 'lucide:bar-chart-3', value: 'analytics' },\n { label: 'Reports', icon: 'lucide:file-text', value: 'reports' }\n ]}\n color=\"primary\"\n >\n {#snippet body({ item })}\n {#if item.value === 'overview'}\n <div class=\"grid gap-3 sm:grid-cols-3\">\n {#each [{ label: 'Users', value: '12,345', change: '+12.5%', icon: 'lucide:users', iconColor: 'text-primary', changeColor: 'text-success' }, { label: 'Revenue', value: '$48,290', change: '+8.2%', icon: 'lucide:dollar-sign', iconColor: 'text-success', changeColor: 'text-success' }, { label: 'Orders', value: '1,890', change: '-3.1%', icon: 'lucide:shopping-cart', iconColor: 'text-warning', changeColor: 'text-error' }] as stat (stat.label)}\n <div class=\"rounded-lg bg-surface-container p-4\">\n <div class=\"flex items-center gap-2\">\n <Icon\n name={stat.icon}\n size=\"18\"\n class={stat.iconColor}\n />\n <span class=\"text-sm text-on-surface-variant\"\n >{stat.label}</span\n >\n </div>\n <p class=\"mt-2 text-2xl font-bold\">{stat.value}</p>\n <p class=\"text-xs {stat.changeColor}\">\n {stat.change} from last month\n </p>\n </div>\n {/each}\n </div>\n {:else if item.value === 'analytics'}\n <div\n class=\"flex flex-col items-center justify-center rounded-lg bg-surface-container p-8\"\n >\n <Icon\n name=\"lucide:bar-chart-3\"\n size=\"48\"\n class=\"text-on-surface-variant/30\"\n />\n <p class=\"mt-3 text-sm text-on-surface-variant\">\n Analytics charts would be rendered here\n </p>\n </div>\n {:else}\n <div class=\"space-y-2\">\n {#each ['Monthly Revenue Report', 'User Growth Report', 'Conversion Funnel Report'] as report (report)}\n <div\n class=\"flex items-center justify-between rounded-lg bg-surface-container p-3\"\n >\n <div class=\"flex items-center gap-3\">\n <Icon\n name=\"lucide:file-text\"\n size=\"18\"\n class=\"text-on-surface-variant\"\n />\n <span class=\"text-sm\">{report}</span>\n </div>\n <Button\n size=\"xs\"\n variant=\"ghost\"\n leadingIcon=\"lucide:download\"\n label=\"Download\"\n />\n </div>\n {/each}\n </div>\n {/if}\n {/snippet}\n </Tabs>\n </div>\n </div>\n\n <!-- Vertical Settings -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">Vertical Settings</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Tabs\n items={[\n {\n label: 'General',\n icon: 'lucide:settings',\n value: 'general',\n content:\n 'Configure general application settings like language, timezone, and display preferences.'\n },\n {\n label: 'Appearance',\n icon: 'lucide:palette',\n value: 'appearance',\n content:\n 'Customize the look and feel including themes, fonts, and layout.'\n },\n {\n label: 'Privacy',\n icon: 'lucide:lock',\n value: 'privacy',\n content:\n 'Control your privacy settings and data sharing preferences.'\n },\n {\n label: 'Notifications',\n icon: 'lucide:bell',\n value: 'notifications',\n content: 'Manage email, push, and in-app notification preferences.'\n }\n ]}\n orientation=\"vertical\"\n color=\"primary\"\n />\n </div>\n </div>\n </div>\n </section>\n</div>\n",
165
168
  "collapsible": "<script lang=\"ts\">\n import { Collapsible, Button, Icon, Badge, Separator } from '$lib/index.js'\n\n let basicOpen = $state(false)\n let controlledOpen = $state(true)\n</script>\n\n<div class=\"mx-auto max-w-3xl space-y-12 p-8\">\n <div>\n <h1 class=\"text-2xl font-bold\">Collapsible</h1>\n <p class=\"mt-1 text-on-surface-variant\">\n An interactive component that expands/collapses content.\n </p>\n </div>\n\n <Separator />\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <Collapsible>\n {#snippet trigger({ open, props })}\n <Button\n {...props}\n variant=\"subtle\"\n trailingIcon={open ? 'lucide:chevron-up' : 'lucide:chevron-down'}\n >\n {open ? 'Hide' : 'Show'} content\n </Button>\n {/snippet}\n {#snippet content()}\n <div class=\"mt-2 rounded-lg border border-outline-variant p-4 text-sm\">\n <p>This is the collapsible content. It can contain any elements you need.</p>\n </div>\n {/snippet}\n </Collapsible>\n </section>\n\n <Separator />\n\n <!-- Initially Open -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Initially Open</h2>\n <Collapsible open>\n {#snippet trigger({ open, props })}\n <Button\n {...props}\n variant=\"outline\"\n trailingIcon={open ? 'lucide:minus' : 'lucide:plus'}\n >\n Toggle section\n </Button>\n {/snippet}\n {#snippet content()}\n <div class=\"mt-2 rounded-lg bg-surface-container p-4 text-sm\">\n <p>This section is open by default when the page loads.</p>\n </div>\n {/snippet}\n </Collapsible>\n </section>\n\n <Separator />\n\n <!-- Controlled -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Controlled (bind:open)</h2>\n <div class=\"flex items-center gap-2\">\n <Badge\n label={controlledOpen ? 'Open' : 'Closed'}\n color={controlledOpen ? 'success' : 'error'}\n />\n <Button variant=\"ghost\" size=\"xs\" onclick={() => (controlledOpen = !controlledOpen)}>\n Toggle externally\n </Button>\n </div>\n <Collapsible bind:open={controlledOpen}>\n {#snippet trigger({ open, props })}\n <Button\n {...props}\n variant=\"soft\"\n color=\"primary\"\n trailingIcon={open ? 'lucide:chevron-up' : 'lucide:chevron-down'}\n >\n Controlled collapsible\n </Button>\n {/snippet}\n {#snippet content()}\n <div\n class=\"mt-2 rounded-lg border border-primary/30 bg-primary-container/20 p-4 text-sm\"\n >\n <p>\n This collapsible is controlled externally via <code\n class=\"rounded bg-surface-container px-1\">bind:open</code\n >.\n </p>\n </div>\n {/snippet}\n </Collapsible>\n </section>\n\n <Separator />\n\n <!-- onOpenChange callback -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">onOpenChange Callback</h2>\n <!-- eslint-disable-next-line no-console -->\n <Collapsible bind:open={basicOpen} onOpenChange={(v) => console.log('open changed:', v)}>\n {#snippet trigger({ open, props })}\n <Button\n {...props}\n variant=\"outline\"\n color=\"secondary\"\n trailingIcon={open ? 'lucide:eye-off' : 'lucide:eye'}\n >\n {open ? 'Collapse' : 'Expand'} (check console)\n </Button>\n {/snippet}\n {#snippet content()}\n <div class=\"mt-2 rounded-lg border border-outline-variant p-4 text-sm\">\n <p>\n Open the console to see the <code class=\"rounded bg-surface-container px-1\"\n >onOpenChange</code\n > callback firing.\n </p>\n </div>\n {/snippet}\n </Collapsible>\n </section>\n\n <Separator />\n\n <!-- Disabled -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Disabled</h2>\n <Collapsible disabled>\n {#snippet trigger({ props })}\n <Button {...props} variant=\"outline\" disabled trailingIcon=\"lucide:chevron-down\">\n Cannot toggle (disabled)\n </Button>\n {/snippet}\n {#snippet content()}\n <div class=\"mt-2 rounded-lg border border-outline-variant p-4 text-sm\">\n <p>You should never see this content.</p>\n </div>\n {/snippet}\n </Collapsible>\n </section>\n\n <Separator />\n\n <!-- Custom trigger (non-Button) -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Trigger</h2>\n <Collapsible>\n {#snippet trigger({ open, props })}\n <div\n {...props}\n class=\"flex cursor-pointer items-center gap-2 rounded-lg border border-outline-variant px-4 py-3 transition-colors hover:bg-surface-container\"\n >\n <Icon name=\"lucide:settings\" class=\"size-5\" />\n <span class=\"flex-1 text-sm font-medium\">Advanced Settings</span>\n <Icon\n name=\"lucide:chevron-down\"\n class=\"size-4 transition-transform duration-200 {open ? 'rotate-180' : ''}\"\n />\n </div>\n {/snippet}\n {#snippet content()}\n <div class=\"mt-1 space-y-3 rounded-lg border border-outline-variant p-4\">\n <div class=\"flex items-center justify-between\">\n <span class=\"text-sm\">Enable notifications</span>\n <Badge label=\"On\" color=\"success\" variant=\"soft\" />\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-sm\">Auto-save drafts</span>\n <Badge label=\"Off\" color=\"error\" variant=\"soft\" />\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-sm\">Dark mode</span>\n <Badge label=\"System\" color=\"info\" variant=\"soft\" />\n </div>\n </div>\n {/snippet}\n </Collapsible>\n </section>\n\n <Separator />\n\n <!-- Custom UI Slots -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom UI Slots</h2>\n <Collapsible\n ui={{\n root: 'rounded-xl border border-outline-variant p-4',\n content: 'mt-3 border-t border-outline-variant pt-3'\n }}\n >\n {#snippet trigger({ open, props })}\n <Button\n {...props}\n variant=\"ghost\"\n size=\"sm\"\n trailingIcon={open ? 'lucide:chevron-up' : 'lucide:chevron-down'}\n >\n Styled with ui prop\n </Button>\n {/snippet}\n {#snippet content()}\n <p class=\"text-sm text-on-surface-variant\">\n The root has a rounded border and padding. The content has a top border\n separator.\n </p>\n {/snippet}\n </Collapsible>\n </section>\n\n <Separator />\n\n <!-- Multiple collapsibles -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Multiple Collapsibles</h2>\n <div class=\"divide-y divide-outline-variant rounded-lg border border-outline-variant\">\n {#each ['Getting Started', 'Installation', 'Configuration'] as title (title)}\n <Collapsible ui={{ root: 'px-4' }}>\n {#snippet trigger({ open, props })}\n <div\n {...props}\n class=\"flex w-full cursor-pointer items-center justify-between py-3\"\n >\n <span class=\"text-sm font-medium\">{title}</span>\n <Icon\n name=\"lucide:chevron-down\"\n class=\"size-4 transition-transform duration-200 {open\n ? 'rotate-180'\n : ''}\"\n />\n </div>\n {/snippet}\n {#snippet content()}\n <div class=\"pb-3 text-sm text-on-surface-variant\">\n Content for the \"{title}\" section. Each collapsible operates\n independently.\n </div>\n {/snippet}\n </Collapsible>\n {/each}\n </div>\n </section>\n</div>\n",
166
169
  "command": "<script lang=\"ts\">\n import { Command, Separator, Badge, Kbd, Button, Popover, Modal, Drawer } from '$lib/index.js'\n import type { CommandGroup } from '$lib/index.js'\n\n // --- Basic groups ---\n const basicGroups: CommandGroup[] = [\n {\n id: 'suggestions',\n label: 'Suggestions',\n items: [\n { value: 'calendar', label: 'Calendar', icon: 'lucide:calendar' },\n { value: 'search-emoji', label: 'Search Emoji', icon: 'lucide:smile' },\n { value: 'calculator', label: 'Calculator', icon: 'lucide:calculator' }\n ]\n },\n {\n id: 'settings',\n label: 'Settings',\n items: [\n {\n value: 'profile',\n label: 'Profile',\n icon: 'lucide:user',\n description: 'Manage your profile settings'\n },\n {\n value: 'billing',\n label: 'Billing',\n icon: 'lucide:credit-card',\n description: 'View billing information'\n },\n {\n value: 'preferences',\n label: 'Preferences',\n icon: 'lucide:settings',\n description: 'Configure app preferences'\n }\n ]\n }\n ]\n\n // --- Groups with disabled items ---\n const disabledGroups: CommandGroup[] = [\n {\n id: 'actions',\n label: 'Actions',\n items: [\n { value: 'new-file', label: 'New File', icon: 'lucide:file-plus' },\n { value: 'new-folder', label: 'New Folder', icon: 'lucide:folder-plus' },\n {\n value: 'delete',\n label: 'Delete (disabled)',\n icon: 'lucide:trash-2',\n disabled: true\n },\n {\n value: 'archive',\n label: 'Archive (disabled)',\n icon: 'lucide:archive',\n disabled: true\n }\n ]\n }\n ]\n\n // --- Keywords for search ---\n const keywordGroups: CommandGroup[] = [\n {\n id: 'navigation',\n label: 'Navigation',\n items: [\n {\n value: 'home',\n label: 'Home',\n icon: 'lucide:home',\n keywords: ['dashboard', 'main', 'start']\n },\n {\n value: 'docs',\n label: 'Documentation',\n icon: 'lucide:book-open',\n keywords: ['help', 'guide', 'manual']\n },\n {\n value: 'components',\n label: 'Components',\n icon: 'lucide:blocks',\n keywords: ['ui', 'elements', 'widgets']\n }\n ]\n }\n ]\n\n // --- External filtering ---\n let externalSearch = $state('')\n const allCountries = [\n { value: 'us', label: 'United States', icon: 'circle-flags:us' },\n { value: 'gb', label: 'United Kingdom', icon: 'circle-flags:gb' },\n { value: 'fr', label: 'France', icon: 'circle-flags:fr' },\n { value: 'de', label: 'Germany', icon: 'circle-flags:de' },\n { value: 'jp', label: 'Japan', icon: 'circle-flags:jp' },\n { value: 'kr', label: 'South Korea', icon: 'circle-flags:kr' },\n { value: 'vn', label: 'Vietnam', icon: 'circle-flags:vn' },\n { value: 'br', label: 'Brazil', icon: 'circle-flags:br' },\n { value: 'au', label: 'Australia', icon: 'circle-flags:au' },\n { value: 'ca', label: 'Canada', icon: 'circle-flags:ca' }\n ]\n const filteredCountries = $derived(\n externalSearch\n ? allCountries.filter((c) =>\n c.label.toLowerCase().includes(externalSearch.toLowerCase())\n )\n : allCountries\n )\n const externalGroups = $derived<CommandGroup[]>([\n {\n id: 'countries',\n label: externalSearch\n ? `Results for \"${externalSearch}\" (${filteredCountries.length})`\n : `All countries (${allCountries.length})`,\n items: filteredCountries\n }\n ])\n\n // --- onSelect callback ---\n let lastSelected = $state('')\n const callbackGroups: CommandGroup[] = [\n {\n id: 'fruits',\n label: 'Fruits',\n items: [\n {\n value: 'apple',\n label: 'Apple',\n icon: 'lucide:apple',\n onSelect: () => (lastSelected = 'Apple')\n },\n {\n value: 'banana',\n label: 'Banana',\n icon: 'lucide:banana',\n onSelect: () => (lastSelected = 'Banana')\n },\n {\n value: 'grape',\n label: 'Grape',\n icon: 'lucide:grape',\n onSelect: () => (lastSelected = 'Grape')\n }\n ]\n }\n ]\n\n // --- Multiple groups ---\n const multiGroups: CommandGroup[] = [\n {\n id: 'general',\n label: 'General',\n items: [\n {\n value: 'appearance',\n label: 'Appearance',\n icon: 'lucide:paintbrush',\n description: 'Change theme and colors'\n },\n {\n value: 'language',\n label: 'Language',\n icon: 'lucide:globe',\n description: 'Select preferred language'\n }\n ]\n },\n {\n id: 'account',\n label: 'Account',\n items: [\n {\n value: 'security',\n label: 'Security',\n icon: 'lucide:shield',\n description: 'Password and 2FA'\n },\n {\n value: 'notifications',\n label: 'Notifications',\n icon: 'lucide:bell',\n description: 'Email and push alerts'\n }\n ]\n },\n {\n id: 'developer',\n label: 'Developer',\n items: [\n {\n value: 'api-keys',\n label: 'API Keys',\n icon: 'lucide:key',\n description: 'Manage API credentials'\n },\n {\n value: 'webhooks',\n label: 'Webhooks',\n icon: 'lucide:webhook',\n description: 'Configure webhook endpoints'\n }\n ]\n }\n ]\n</script>\n\n<div class=\"mx-auto max-w-3xl space-y-12 p-8\">\n <div>\n <h1 class=\"text-2xl font-bold\">Command</h1>\n <p class=\"mt-1 text-on-surface-variant\">\n A command menu with search filtering and keyboard navigation.\n </p>\n </div>\n\n <Separator />\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command groups={basicGroups} placeholder=\"Type a command or search...\" />\n </div>\n </section>\n\n <Separator />\n\n <!-- With descriptions -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Items with Descriptions</h2>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command groups={multiGroups} placeholder=\"Search settings...\" />\n </div>\n </section>\n\n <Separator />\n\n <!-- Disabled items -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Disabled Items</h2>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command groups={disabledGroups} placeholder=\"Search actions...\" />\n </div>\n </section>\n\n <Separator />\n\n <!-- Keywords search -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Keywords (search \"help\", \"ui\", \"dashboard\")</h2>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command groups={keywordGroups} placeholder=\"Try searching help or dashboard...\" />\n </div>\n </section>\n\n <Separator />\n\n <!-- onSelect callback -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">onSelect Callback</h2>\n <div class=\"flex items-center gap-2\">\n <span class=\"text-sm text-on-surface-variant\">Last selected:</span>\n <Badge label={lastSelected || 'None'} color={lastSelected ? 'success' : 'surface'} />\n </div>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command groups={callbackGroups} placeholder=\"Select a fruit...\" />\n </div>\n </section>\n\n <Separator />\n\n <!-- Loading -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Loading State</h2>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command groups={[]} loading placeholder=\"Fetching results...\" />\n </div>\n </section>\n\n <Separator />\n\n <!-- Empty state -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Empty State</h2>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command\n groups={[{ id: 'empty', items: [] }]}\n emptyText=\"Nothing here yet.\"\n placeholder=\"Search...\"\n />\n </div>\n </section>\n\n <Separator />\n\n <!-- Custom empty slot -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Empty Slot</h2>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command groups={basicGroups} placeholder=\"Search something that doesn't exist...\">\n {#snippet empty({ search })}\n <div class=\"flex flex-col items-center gap-2 py-6\">\n <span class=\"text-2xl\">🔍</span>\n <span class=\"text-sm text-on-surface-variant\">\n {search ? `No results for \"${search}\"` : 'Start typing to search'}\n </span>\n </div>\n {/snippet}\n </Command>\n </div>\n </section>\n\n <Separator />\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n {#each ['xs', 'sm', 'md', 'lg', 'xl'] as const as s (s)}\n <div>\n <p class=\"mb-1 text-xs font-medium text-on-surface-variant\">{s}</p>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command\n size={s}\n groups={[\n {\n id: 'size-demo',\n label: 'Actions',\n items: [\n { value: 'copy', label: 'Copy', icon: 'lucide:copy' },\n { value: 'paste', label: 'Paste', icon: 'lucide:clipboard' }\n ]\n }\n ]}\n placeholder=\"Size {s}...\"\n />\n </div>\n </div>\n {/each}\n </section>\n\n <Separator />\n\n <!-- Custom UI slots -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom UI Slots</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Available ui slots: root, input, list, empty, loading, group, groupHeading, groupItems,\n separator, item, itemIcon, itemLabel, itemDescription, itemTrailing\n </p>\n <div class=\"space-y-4\">\n <div>\n <p class=\"mb-1 text-xs font-medium text-on-surface-variant\">\n Custom background + rounded items + uppercase headings\n </p>\n <Command\n groups={basicGroups}\n placeholder=\"Styled command...\"\n ui={{\n root: 'rounded-lg border border-outline-variant shadow-md bg-surface-container-low',\n item: 'rounded-lg',\n groupHeading: 'uppercase tracking-wider text-primary'\n }}\n />\n </div>\n <div>\n <p class=\"mb-1 text-xs font-medium text-on-surface-variant\">\n Custom selected item color + item icon color\n </p>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command\n groups={basicGroups}\n placeholder=\"Custom highlight...\"\n ui={{\n item: 'data-[selected]:bg-primary/10 data-[selected]:text-primary',\n itemIcon: 'text-primary'\n }}\n />\n </div>\n </div>\n <div>\n <p class=\"mb-1 text-xs font-medium text-on-surface-variant\">\n Custom list max height (scrollable)\n </p>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command\n groups={multiGroups}\n placeholder=\"Scroll to see more...\"\n ui={{\n list: 'max-h-48'\n }}\n />\n </div>\n </div>\n </div>\n </section>\n\n <Separator />\n\n <!-- Footer slot -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Footer Slot</h2>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command groups={basicGroups} placeholder=\"Search...\">\n {#snippet footer()}\n <div\n class=\"flex items-center justify-between px-3 py-2 text-xs text-on-surface-variant\"\n >\n <div class=\"flex items-center gap-2\">\n <span class=\"flex items-center gap-1\"\n ><Kbd value=\"↑\" size=\"sm\" /><Kbd value=\"↓\" size=\"sm\" /> Navigate</span\n >\n <span class=\"flex items-center gap-1\"\n ><Kbd value=\"↵\" size=\"sm\" /> Select</span\n >\n </div>\n <span class=\"flex items-center gap-1\"\n ><Kbd value=\"Esc\" size=\"sm\" /> Close</span\n >\n </div>\n {/snippet}\n </Command>\n </div>\n </section>\n\n <Separator />\n\n <!-- shouldFilter=false -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">External Filtering (shouldFilter=false)</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Built-in filter is disabled. The search term is bound via\n <code class=\"rounded bg-surface-container-highest px-1 py-0.5 text-xs\">bind:search</code\n >\n and filtering is handled externally.\n </p>\n <div class=\"rounded-lg border border-outline-variant shadow-md\">\n <Command\n shouldFilter={false}\n bind:search={externalSearch}\n groups={externalGroups}\n placeholder=\"Search countries...\"\n />\n </div>\n </section>\n\n <Separator />\n\n <!-- Inside Popover -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Inside Popover</h2>\n <Popover>\n <Button variant=\"outline\" leadingIcon=\"lucide:search\">Open Command...</Button>\n {#snippet content()}\n <Command\n groups={basicGroups}\n placeholder=\"Search...\"\n ui={{ list: 'max-h-64' }}\n class=\"w-80\"\n />\n {/snippet}\n </Popover>\n </section>\n\n <Separator />\n\n <!-- Inside Modal -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Inside Modal</h2>\n <Modal>\n <Button variant=\"outline\" leadingIcon=\"lucide:search\">\n Search...\n <Kbd value=\"meta\" size=\"sm\" />\n <Kbd value=\"K\" size=\"sm\" />\n </Button>\n {#snippet content()}\n <Command groups={multiGroups} placeholder=\"Search settings...\" />\n {/snippet}\n </Modal>\n </section>\n\n <Separator />\n\n <!-- Inside Drawer -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Inside Drawer</h2>\n <Drawer handle={false}>\n <Button variant=\"outline\" leadingIcon=\"lucide:terminal\">Open Command Drawer</Button>\n {#snippet content()}\n <Command groups={multiGroups} placeholder=\"Search settings...\" />\n {/snippet}\n </Drawer>\n </section>\n</div>\n",
167
170
  "context-menu": "<script lang=\"ts\">\n import {\n ContextMenu,\n Separator,\n type ContextMenuItem,\n type ContextMenuRadioGroup\n } from '$lib/index.js'\n\n let showStatusBar = $state(true)\n let showActivityBar = $state(false)\n let showPanel = $state(true)\n let selectedTheme = $state('system')\n\n const basicItems: ContextMenuItem[] = [\n { label: 'Back', icon: 'lucide:arrow-left', kbds: ['alt', 'left'] },\n { label: 'Forward', icon: 'lucide:arrow-right', kbds: ['alt', 'right'], disabled: true },\n { label: 'Reload', icon: 'lucide:refresh-cw', kbds: ['meta', 'r'] },\n { type: 'separator' },\n { label: 'Save As...', icon: 'lucide:save', kbds: ['meta', 's'] },\n { label: 'Print...', icon: 'lucide:printer', kbds: ['meta', 'p'] }\n ]\n\n const coloredItems: ContextMenuItem[] = [\n { label: 'Edit', icon: 'lucide:pencil' },\n { label: 'Duplicate', icon: 'lucide:copy' },\n { type: 'separator' },\n { label: 'Archive', icon: 'lucide:archive', color: 'warning' },\n { label: 'Delete', icon: 'lucide:trash-2', color: 'error' }\n ]\n\n const checkboxItems: ContextMenuItem[] = $derived([\n { type: 'label', label: 'Appearance' },\n {\n type: 'checkbox',\n label: 'Status Bar',\n checked: showStatusBar,\n closeOnSelect: false,\n onCheckedChange: (v: boolean) => (showStatusBar = v)\n },\n {\n type: 'checkbox',\n label: 'Activity Bar',\n checked: showActivityBar,\n closeOnSelect: false,\n onCheckedChange: (v: boolean) => (showActivityBar = v)\n },\n {\n type: 'checkbox',\n label: 'Panel',\n checked: showPanel,\n closeOnSelect: false,\n onCheckedChange: (v: boolean) => (showPanel = v)\n }\n ])\n\n const radioItems: ContextMenuItem[] = [\n { type: 'label', label: 'Theme' },\n { type: 'radio', label: 'Light', value: 'light' },\n { type: 'radio', label: 'Dark', value: 'dark' },\n { type: 'radio', label: 'System', value: 'system' }\n ]\n\n const radioGroups: ContextMenuRadioGroup[] = $derived([\n {\n name: 'theme',\n value: selectedTheme,\n onValueChange: (v: string) => (selectedTheme = v)\n }\n ])\n\n const submenuItems: ContextMenuItem[] = [\n { label: 'Cut', icon: 'lucide:scissors', kbds: ['meta', 'x'] },\n { label: 'Copy', icon: 'lucide:copy', kbds: ['meta', 'c'] },\n { label: 'Paste', icon: 'lucide:clipboard', kbds: ['meta', 'v'] },\n { type: 'separator' },\n {\n type: 'sub',\n label: 'More Tools',\n icon: 'lucide:wrench',\n items: [\n { label: 'Save Page As...', kbds: ['meta', 's'] },\n { label: 'Create Shortcut...' },\n { label: 'Name Window...' },\n { type: 'separator' },\n { label: 'Developer Tools', kbds: ['meta', 'alt', 'i'] }\n ]\n },\n {\n type: 'sub',\n label: 'Share',\n icon: 'lucide:share-2',\n items: [\n { label: 'Email', icon: 'lucide:mail' },\n { label: 'Message', icon: 'lucide:message-square' },\n { type: 'separator' },\n { label: 'Copy Link', icon: 'lucide:link' }\n ]\n }\n ]\n\n const fullItems: ContextMenuItem[] = $derived([\n { label: 'Cut', icon: 'lucide:scissors', kbds: ['meta', 'x'] },\n { label: 'Copy', icon: 'lucide:copy', kbds: ['meta', 'c'] },\n { label: 'Paste', icon: 'lucide:clipboard', kbds: ['meta', 'v'] },\n { type: 'separator' },\n { type: 'label', label: 'View' },\n {\n type: 'checkbox',\n label: 'Show Bookmarks',\n checked: showStatusBar,\n onCheckedChange: (v: boolean) => (showStatusBar = v)\n },\n {\n type: 'checkbox',\n label: 'Show Full URLs',\n checked: showActivityBar,\n onCheckedChange: (v: boolean) => (showActivityBar = v)\n },\n { type: 'separator' },\n {\n type: 'sub',\n label: 'More Tools',\n icon: 'lucide:wrench',\n items: [\n { label: 'Save Page As...', kbds: ['meta', 's'] },\n { label: 'Create Shortcut...' },\n { type: 'separator' },\n { label: 'Developer Tools', kbds: ['meta', 'alt', 'i'] }\n ]\n },\n { type: 'separator' },\n { label: 'Delete', icon: 'lucide:trash-2', color: 'error', kbds: ['delete'] }\n ])\n\n const triggerClass =\n 'flex items-center justify-center rounded-lg border-2 border-dashed border-outline-variant bg-surface-container-low text-on-surface-variant transition-colors hover:border-primary/50 hover:bg-surface-container cursor-context-menu select-none'\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">ContextMenu</h1>\n <p class=\"text-on-surface-variant\">\n Display a menu of actions or options triggered by right-click. Built on bits-ui\n ContextMenu primitive.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Right-click on the area below to open a context menu with icons and keyboard shortcuts.\n </p>\n <ContextMenu items={basicItems}>\n <div class=\"{triggerClass} h-36 w-full\">\n <span class=\"text-sm\">Right-click here</span>\n </div>\n </ContextMenu>\n </section>\n\n <!-- Colored Items -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Colored Items</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">color</code>\n prop on items for semantic coloring.\n </p>\n <ContextMenu items={coloredItems}>\n <div class=\"{triggerClass} h-36 w-full\">\n <span class=\"text-sm\">Right-click for colored items</span>\n </div>\n </ContextMenu>\n </section>\n\n <!-- Checkbox Items -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Checkbox Items</h2>\n <p class=\"text-sm text-on-surface-variant\">Toggle boolean states with checkbox items.</p>\n <div class=\"flex items-start gap-4 rounded-lg bg-surface-container-high p-4\">\n <ContextMenu items={checkboxItems} class=\"flex-1\">\n <div class=\"{triggerClass} h-36 w-full\">\n <span class=\"text-sm\">Right-click for checkboxes</span>\n </div>\n </ContextMenu>\n <div class=\"text-sm text-on-surface-variant\">\n <p>Status Bar: <code class=\"text-primary\">{showStatusBar}</code></p>\n <p>Activity Bar: <code class=\"text-primary\">{showActivityBar}</code></p>\n <p>Panel: <code class=\"text-primary\">{showPanel}</code></p>\n </div>\n </div>\n </section>\n\n <!-- Radio Items -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Radio Items</h2>\n <p class=\"text-sm text-on-surface-variant\">Single selection with radio items and groups.</p>\n <div class=\"flex items-start gap-4 rounded-lg bg-surface-container-high p-4\">\n <ContextMenu items={radioItems} {radioGroups} class=\"flex-1\">\n <div class=\"{triggerClass} h-36 w-full\">\n <span class=\"text-sm\">Right-click for radio selection</span>\n </div>\n </ContextMenu>\n <div class=\"text-sm text-on-surface-variant\">\n Selected: <code class=\"text-primary\">{selectedTheme}</code>\n </div>\n </div>\n </section>\n\n <!-- Submenus -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Submenus</h2>\n <ContextMenu items={submenuItems}>\n <div class=\"{triggerClass} h-36 w-full\">\n <span class=\"text-sm\">Right-click for submenus</span>\n </div>\n </ContextMenu>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Control the menu size with the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">size</code>\n prop.\n </p>\n <div class=\"grid gap-4 md:grid-cols-3\">\n {#each [{ size: 'xs' as const, label: 'XS' }, { size: 'sm' as const, label: 'SM' }, { size: 'md' as const, label: 'MD (default)' }, { size: 'lg' as const, label: 'LG' }, { size: 'xl' as const, label: 'XL' }] as item (item.size)}\n <ContextMenu items={basicItems.slice(0, 5)} size={item.size}>\n <div class=\"{triggerClass} h-28\">\n <span class=\"text-xs\">{item.label}</span>\n </div>\n </ContextMenu>\n {/each}\n </div>\n </section>\n\n <!-- Custom Header/Footer -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Header/Footer</h2>\n <ContextMenu items={basicItems.slice(0, 4)}>\n <div class=\"{triggerClass} h-36 w-full\">\n <span class=\"text-sm\">Right-click for header/footer</span>\n </div>\n {#snippet header()}\n <div class=\"px-3 py-2\">\n <p class=\"text-sm font-medium\">John Doe</p>\n <p class=\"text-xs text-on-surface-variant\">john@example.com</p>\n </div>\n <Separator />\n {/snippet}\n {#snippet footer({ close })}\n <Separator />\n <div class=\"p-1\">\n <button\n class=\"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-error hover:bg-error-container hover:text-on-error-container\"\n onclick={close}\n >\n Log out\n </button>\n </div>\n {/snippet}\n </ContextMenu>\n </section>\n\n <!-- Custom Content -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Content</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">content</code>\n slot for fully custom context menu content.\n </p>\n <ContextMenu>\n <div class=\"{triggerClass} h-36 w-full\">\n <span class=\"text-sm\">Right-click for custom content</span>\n </div>\n {#snippet content({ close })}\n <div class=\"p-4\">\n <p class=\"mb-3 text-sm font-medium\">Choose a color</p>\n <div class=\"grid grid-cols-5 gap-2\">\n {#each ['bg-red-500', 'bg-orange-500', 'bg-yellow-500', 'bg-green-500', 'bg-teal-500', 'bg-blue-500', 'bg-indigo-500', 'bg-purple-500', 'bg-pink-500', 'bg-gray-500'] as color (color)}\n <button\n class=\"size-8 rounded-full {color} transition-all hover:ring-2 hover:ring-outline hover:ring-offset-2\"\n aria-label=\"Select {color\n .replace('bg-', '')\n .replace('-500', '')} color\"\n onclick={close}\n ></button>\n {/each}\n </div>\n </div>\n {/snippet}\n </ContextMenu>\n </section>\n\n <!-- UI Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Overrides</h2>\n <div class=\"grid gap-4 sm:grid-cols-2\">\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Primary theme</p>\n <ContextMenu\n items={basicItems.slice(0, 4)}\n ui={{\n content: 'bg-primary text-on-primary ring-primary/50',\n item: 'data-[highlighted]:bg-on-primary/20',\n separator: 'bg-on-primary/20'\n }}\n >\n <div class=\"{triggerClass} h-28\">\n <span class=\"text-sm\">Primary Style</span>\n </div>\n </ContextMenu>\n </div>\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Custom rounding</p>\n <ContextMenu\n items={basicItems.slice(0, 4)}\n ui={{ content: 'rounded-xl shadow-2xl' }}\n >\n <div class=\"{triggerClass} h-28\">\n <span class=\"text-sm\">Custom Rounding</span>\n </div>\n </ContextMenu>\n </div>\n </div>\n </section>\n\n <Separator />\n\n <!-- Real World Examples -->\n <section class=\"space-y-6\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n\n <div class=\"space-y-4\">\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">Browser Context Menu</p>\n <ContextMenu items={fullItems}>\n <div class=\"{triggerClass} h-48 w-full\">\n <div class=\"text-center\">\n <p class=\"text-sm font-medium text-on-surface\">Interactive Area</p>\n <p class=\"mt-1 text-xs text-on-surface-variant\">\n Right-click anywhere in this area\n </p>\n </div>\n </div>\n </ContextMenu>\n </div>\n </div>\n </section>\n</div>\n",
168
- "modal": "<script lang=\"ts\">\n import { Modal, Button, Badge, Icon, Separator } from '$lib/index.js'\n\n let basicOpen = $state(false)\n let fullscreenOpen = $state(false)\n let scrollableOpen = $state(false)\n let scrollableFullscreenOpen = $state(false)\n let noCloseOpen = $state(false)\n let noOverlayOpen = $state(false)\n let noTransitionOpen = $state(false)\n let nonDismissibleOpen = $state(false)\n let slotsOpen = $state(false)\n let actionsOpen = $state(false)\n let customContentOpen = $state(false)\n let callbacksOpen = $state(false)\n let callbackLog = $state<string[]>([])\n let uiOverrideOpen = $state(false)\n let programmaticOpen = $state(false)\n\n let confirmOpen = $state(false)\n let formOpen = $state(false)\n let alertOpen = $state(false)\n let imageOpen = $state(false)\n\n let sizeOpens = $state<Record<string, boolean>>({\n sm: false,\n md: false,\n lg: false,\n xl: false,\n full: false\n })\n let transitionOpens = $state<Record<string, boolean>>({\n scale: false,\n fade: false,\n slide: false,\n none: false\n })\n\n function logCallback(name: string) {\n callbackLog = [...callbackLog.slice(-4), `${new Date().toLocaleTimeString()} — ${name}`]\n }\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Modal</h1>\n <p class=\"text-on-surface-variant\">\n A modal dialog component built on bits-ui Dialog. Supports transitions, fullscreen,\n scrollable mode, dismissible control, and full slot customization.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Modal\n bind:open={basicOpen}\n title=\"Basic Modal\"\n description=\"This is a basic modal with title, description, body and footer.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open Modal\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n A centered modal dialog. Click the X, press Escape, or click outside to\n close.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button label=\"Cancel\" variant=\"outline\" onclick={() => (basicOpen = false)} />\n <Button\n label=\"Confirm\"\n variant=\"solid\"\n color=\"primary\"\n onclick={() => (basicOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Fullscreen -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Fullscreen</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Modal\n bind:open={fullscreenOpen}\n fullscreen\n title=\"Fullscreen Modal\"\n description=\"This modal takes up the entire screen.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open Fullscreen\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Covers the entire viewport. Useful for complex forms or media viewers.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (fullscreenOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Scrollable -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Scrollable</h2>\n <div class=\"flex flex-wrap gap-3 rounded-lg bg-surface-container-high p-4\">\n <Modal\n bind:open={scrollableOpen}\n scrollable\n title=\"Scrollable Modal\"\n description=\"The entire modal scrolls within the overlay.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Scrollable\" />\n {/snippet}\n {#snippet body()}\n <div class=\"space-y-3\">\n {#each Array.from({ length: 20 }, (_, i) => i) as i (i)}\n <div class=\"rounded-md bg-surface-container p-3\">\n <p class=\"text-sm text-on-surface-variant\">Content item {i + 1}</p>\n </div>\n {/each}\n </div>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (scrollableOpen = false)}\n />\n {/snippet}\n </Modal>\n\n <Modal\n bind:open={scrollableFullscreenOpen}\n scrollable\n fullscreen\n title=\"Scrollable + Fullscreen\"\n description=\"Full viewport with scrollable content.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Scrollable + Fullscreen\" />\n {/snippet}\n {#snippet body()}\n <div class=\"space-y-3\">\n {#each Array.from({ length: 30 }, (_, i) => i) as i (i)}\n <div class=\"rounded-md bg-surface-container p-3\">\n <p class=\"text-sm text-on-surface-variant\">Content item {i + 1}</p>\n </div>\n {/each}\n </div>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (scrollableFullscreenOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Options -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Options</h2>\n <div class=\"flex flex-wrap gap-3 rounded-lg bg-surface-container-high p-4\">\n <Modal\n bind:open={noTransitionOpen}\n transition={false}\n title=\"No Transition\"\n description=\"Appears instantly without animation.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"No Transition\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">Modal opens and closes without animation.</p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (noTransitionOpen = false)}\n />\n {/snippet}\n </Modal>\n\n <Modal\n bind:open={noCloseOpen}\n close={false}\n title=\"No Close Button\"\n description=\"Close button is hidden.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"No Close Button\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">Use the footer button or Escape to close.</p>\n {/snippet}\n {#snippet footer()}\n <Button label=\"Close\" variant=\"outline\" onclick={() => (noCloseOpen = false)} />\n {/snippet}\n </Modal>\n\n <Modal\n bind:open={noOverlayOpen}\n overlay={false}\n title=\"No Overlay\"\n description=\"Background is visible.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"No Overlay\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">No backdrop overlay behind the modal.</p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (noOverlayOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Non-Dismissible -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Non-Dismissible</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Modal\n bind:open={nonDismissibleOpen}\n dismissible={false}\n title=\"Non-Dismissible\"\n description=\"Must use the close button.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open (Non-Dismissible)\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Clicking outside or pressing Escape won't close this modal.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"solid\"\n color=\"primary\"\n onclick={() => (nonDismissibleOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Slots -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Slots</h2>\n <div class=\"flex flex-wrap gap-3 rounded-lg bg-surface-container-high p-4\">\n <!-- Custom header -->\n <Modal bind:open={slotsOpen}>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Custom Header\" />\n {/snippet}\n {#snippet header()}\n <div class=\"flex items-center gap-3 p-4 sm:px-6\">\n <div\n class=\"flex size-10 items-center justify-center rounded-full bg-primary text-on-primary\"\n >\n <Icon name=\"lucide:settings\" size=\"20\" />\n </div>\n <div>\n <h3 class=\"font-semibold text-on-surface\">Custom Header</h3>\n <p class=\"text-sm text-on-surface-variant\">With icon and layout</p>\n </div>\n </div>\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n The header slot replaces the default title, description, and close button.\n </p>\n {/snippet}\n {#snippet footer()}\n <div class=\"flex gap-2\">\n <Button\n label=\"Cancel\"\n variant=\"outline\"\n onclick={() => (slotsOpen = false)}\n />\n <Button\n label=\"Save\"\n variant=\"solid\"\n color=\"primary\"\n onclick={() => (slotsOpen = false)}\n />\n </div>\n {/snippet}\n </Modal>\n\n <!-- Actions slot -->\n <Modal\n bind:open={actionsOpen}\n title=\"User Profile\"\n description=\"Manage your account settings.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Actions Slot\" />\n {/snippet}\n {#snippet actions()}\n <Badge variant=\"soft\" color=\"success\" size=\"xs\" label=\"Active\" />\n <Badge variant=\"soft\" color=\"info\" size=\"xs\" label=\"Pro\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n The actions slot renders between the title/description and the close button.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button label=\"Close\" variant=\"outline\" onclick={() => (actionsOpen = false)} />\n {/snippet}\n </Modal>\n\n <!-- Full content slot -->\n <Modal bind:open={customContentOpen} title=\"Custom Content\">\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Content Slot\" />\n {/snippet}\n {#snippet content()}\n <div class=\"flex flex-col items-center gap-4 p-6\">\n <div\n class=\"flex size-16 items-center justify-center rounded-full bg-success/10\"\n >\n <Icon name=\"lucide:check-circle\" size=\"32\" class=\"text-success\" />\n </div>\n <h3 class=\"text-xl font-semibold text-on-surface\">Payment Successful</h3>\n <p class=\"text-center text-on-surface-variant\">\n The content slot replaces the entire inner layout.\n </p>\n <Button\n label=\"Done\"\n variant=\"solid\"\n color=\"primary\"\n onclick={() => (customContentOpen = false)}\n />\n </div>\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Lifecycle Callbacks -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Lifecycle Callbacks</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <div class=\"mb-3 space-y-1\">\n {#if callbackLog.length === 0}\n <p class=\"text-sm text-on-surface-variant italic\">\n Open/close the modal to see callback logs...\n </p>\n {/if}\n {#each callbackLog as log, i (i)}\n <p class=\"font-mono text-xs text-on-surface-variant\">{log}</p>\n {/each}\n </div>\n <Modal\n bind:open={callbacksOpen}\n onOpenChange={(v) => logCallback(`onOpenChange(${v})`)}\n onOpenChangeComplete={(v) => logCallback(`onOpenChangeComplete(${v})`)}\n title=\"Callback Demo\"\n description=\"Check the log above.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open (With Callbacks)\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Open, close, and watch the callback log update.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (callbacksOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- Programmatic Control -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Programmatic Control</h2>\n <div class=\"flex gap-3 rounded-lg bg-surface-container-high p-4\">\n <Button\n variant=\"outline\"\n label=\"Open Programmatically\"\n onclick={() => (programmaticOpen = true)}\n />\n <Modal\n bind:open={programmaticOpen}\n title=\"Programmatic Modal\"\n description=\"Opened without a trigger slot.\"\n >\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n This modal has no trigger. It was opened by setting open = true externally.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (programmaticOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <!-- UI Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Slot Overrides</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Modal\n bind:open={uiOverrideOpen}\n title=\"Styled Modal\"\n description=\"Custom styles via the ui prop.\"\n ui={{\n content: 'bg-primary-container',\n title: 'text-on-primary-container',\n description: 'text-on-primary-container/70',\n header: 'border-on-primary-container/10'\n }}\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open Styled Modal\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-primary-container/80\">\n This modal overrides content, title, description, and header slot classes.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (uiOverrideOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n </section>\n\n <Separator />\n\n <!-- Real World Examples -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n <div class=\"grid gap-4 sm:grid-cols-2\">\n <!-- Confirmation Dialog -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Confirmation Dialog</p>\n <Modal bind:open={confirmOpen} dismissible={false} close={false}>\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n leadingIcon=\"lucide:trash-2\"\n label=\"Delete Item\"\n color=\"error\"\n class=\"w-full\"\n />\n {/snippet}\n {#snippet content()}\n <div class=\"flex flex-col items-center gap-4 p-6 text-center\">\n <div\n class=\"flex size-14 items-center justify-center rounded-full bg-error/10\"\n >\n <Icon name=\"lucide:alert-triangle\" size=\"28\" class=\"text-error\" />\n </div>\n <h3 class=\"text-lg font-semibold text-on-surface\">Delete this item?</h3>\n <p class=\"text-sm text-on-surface-variant\">\n This action is permanent and cannot be undone.\n </p>\n <div class=\"flex w-full gap-2\">\n <Button\n label=\"Cancel\"\n variant=\"outline\"\n class=\"flex-1\"\n onclick={() => (confirmOpen = false)}\n />\n <Button\n label=\"Delete\"\n variant=\"solid\"\n color=\"error\"\n class=\"flex-1\"\n onclick={() => (confirmOpen = false)}\n />\n </div>\n </div>\n {/snippet}\n </Modal>\n </div>\n\n <!-- Form Modal -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Form Modal</p>\n <Modal\n bind:open={formOpen}\n title=\"Create Project\"\n description=\"Fill in the details to create a new project.\"\n >\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n leadingIcon=\"lucide:plus\"\n label=\"New Project\"\n class=\"w-full\"\n />\n {/snippet}\n {#snippet body()}\n <div class=\"space-y-4\">\n <div>\n <label\n for=\"project-name\"\n class=\"mb-1 block text-sm font-medium text-on-surface\"\n >Project Name</label\n >\n <input\n id=\"project-name\"\n type=\"text\"\n placeholder=\"My Project\"\n class=\"w-full rounded-md border border-outline-variant bg-surface px-3 py-2 text-sm text-on-surface placeholder:text-on-surface-variant/50 focus:border-primary focus:ring-1 focus:ring-primary focus:outline-none\"\n />\n </div>\n <div>\n <label\n for=\"project-desc\"\n class=\"mb-1 block text-sm font-medium text-on-surface\"\n >Description</label\n >\n <textarea\n id=\"project-desc\"\n rows=\"3\"\n placeholder=\"Describe your project...\"\n class=\"w-full rounded-md border border-outline-variant bg-surface px-3 py-2 text-sm text-on-surface placeholder:text-on-surface-variant/50 focus:border-primary focus:ring-1 focus:ring-primary focus:outline-none\"\n ></textarea>\n </div>\n </div>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Cancel\"\n variant=\"outline\"\n onclick={() => (formOpen = false)}\n />\n <Button\n label=\"Create\"\n variant=\"solid\"\n color=\"primary\"\n onclick={() => (formOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n\n <!-- Alert Modal -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Alert Modal</p>\n <Modal\n bind:open={alertOpen}\n title=\"Session Expired\"\n description=\"Your session has timed out due to inactivity.\"\n dismissible={false}\n >\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n leadingIcon=\"lucide:clock\"\n label=\"Session Alert\"\n class=\"w-full\"\n />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Please sign in again to continue using the application.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Sign In\"\n variant=\"solid\"\n color=\"primary\"\n class=\"w-full\"\n onclick={() => (alertOpen = false)}\n />\n {/snippet}\n </Modal>\n </div>\n\n <!-- Image Preview -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Image Preview</p>\n <Modal bind:open={imageOpen} close={{ color: 'surface', size: 'md' }}>\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n leadingIcon=\"lucide:image\"\n label=\"View Image\"\n class=\"w-full\"\n />\n {/snippet}\n {#snippet content()}\n <div class=\"p-2\">\n <img\n src=\"https://picsum.photos/800/600\"\n alt=\"Preview\"\n class=\"w-full rounded-md\"\n />\n <p class=\"mt-2 text-center text-sm text-on-surface-variant\">\n Photo from Picsum\n </p>\n </div>\n {/snippet}\n </Modal>\n </div>\n </div>\n </section>\n\n <Separator />\n\n <section>\n <h2 class=\"mb-3 text-lg font-semibold\">Size</h2>\n <p class=\"mb-4 text-sm text-on-surface-variant\">\n Use <code>size</code> to control the modal width: <code>sm</code> /\n <code>md</code> (default) / <code>lg</code> / <code>xl</code> /\n <code>full</code>. The legacy <code>fullscreen</code> prop is kept as an alias for\n <code>size=\"full\"</code>.\n </p>\n <div class=\"flex flex-wrap gap-2\">\n {#each ['sm', 'md', 'lg', 'xl', 'full'] as const as s (s)}\n <Modal\n bind:open={sizeOpens[s]}\n size={s}\n title={`Size: ${s}`}\n description=\"Resize your browser to see how the modal width scales.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label={`size=\"${s}\"`} />\n {/snippet}\n {#snippet body()}\n <p class=\"text-sm text-on-surface-variant\">\n Current size is <code>{s}</code>.\n </p>\n {/snippet}\n </Modal>\n {/each}\n </div>\n </section>\n\n <Separator />\n\n <section>\n <h2 class=\"mb-3 text-lg font-semibold\">Transition</h2>\n <p class=\"mb-4 text-sm text-on-surface-variant\">\n Pick how the modal animates in and out. Default is <code>scale</code>; pass\n <code>fade</code>, <code>slide</code>, or <code>none</code> to override. Boolean\n <code>true</code> / <code>false</code> still work as legacy aliases.\n </p>\n <div class=\"flex flex-wrap gap-2\">\n {#each ['scale', 'fade', 'slide', 'none'] as const as t (t)}\n <Modal\n bind:open={transitionOpens[t]}\n transition={t}\n title={`Transition: ${t}`}\n description=\"Open and close to see the animation.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label={`transition=\"${t}\"`} />\n {/snippet}\n </Modal>\n {/each}\n </div>\n </section>\n</div>\n",
169
171
  "drawer": "<script lang=\"ts\">\n import { Drawer, Button, Badge, Icon, Separator } from '$lib/index.js'\n\n let basicOpen = $state(false)\n let directionOpen = $state<Record<string, boolean>>({\n top: false,\n right: false,\n bottom: false,\n left: false\n })\n let insetOpen = $state<Record<string, boolean>>({\n top: false,\n right: false,\n bottom: false,\n left: false\n })\n let noHandleOpen = $state(false)\n let handleOnlyOpen = $state(false)\n let noOverlayOpen = $state(false)\n let scaleBackgroundOpen = $state(false)\n let nonDismissibleOpen = $state(false)\n let snapOpen = $state(false)\n let snapControlledOpen = $state(false)\n let activeSnap = $state<number | string | null>(0.25)\n let nestedOuterOpen = $state(false)\n let nestedInnerOpen = $state(false)\n let slotsOpen = $state(false)\n let customContentOpen = $state(false)\n let callbacksOpen = $state(false)\n let callbackLog = $state<string[]>([])\n let uiOverrideOpen = $state(false)\n let programmaticOpen = $state(false)\n\n let settingsOpen = $state(false)\n let notificationsOpen = $state(false)\n let filterOpen = $state(false)\n let confirmOpen = $state(false)\n\n const directions = ['top', 'right', 'bottom', 'left'] as const\n\n function logCallback(name: string) {\n callbackLog = [...callbackLog.slice(-4), `${new Date().toLocaleTimeString()} — ${name}`]\n }\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Drawer</h1>\n <p class=\"text-on-surface-variant\">\n A draggable drawer component built on vaul-svelte. Supports swipe-to-dismiss, snap\n points, nested drawers, all 4 directions, and full slot customization.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Drawer\n bind:open={basicOpen}\n title=\"Basic Drawer\"\n description=\"This is a basic drawer with title, description, body and footer.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open Drawer\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Slides up from the bottom by default. Swipe down or click the overlay to\n close.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button label=\"Close\" variant=\"outline\" onclick={() => (basicOpen = false)} />\n {/snippet}\n </Drawer>\n </div>\n </section>\n\n <!-- Directions -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Directions</h2>\n <div class=\"flex flex-wrap gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each directions as dir (dir)}\n <Drawer\n bind:open={directionOpen[dir]}\n direction={dir}\n title=\"{dir.charAt(0).toUpperCase() + dir.slice(1)} Drawer\"\n description=\"Opens from the {dir}.\"\n >\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n label={dir.charAt(0).toUpperCase() + dir.slice(1)}\n />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Drawer from the <strong>{dir}</strong>. Swipe towards the edge to\n dismiss.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (directionOpen[dir] = false)}\n />\n {/snippet}\n </Drawer>\n {/each}\n </div>\n </section>\n\n <!-- Inset -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Inset</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Inset drawers have rounded corners and are offset from screen edges.\n </p>\n <div class=\"flex flex-wrap gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each directions as dir (dir)}\n <Drawer\n bind:open={insetOpen[dir]}\n inset\n direction={dir}\n title=\"Inset {dir.charAt(0).toUpperCase() + dir.slice(1)}\"\n description=\"Inset + {dir} direction.\"\n >\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"soft\"\n size=\"sm\"\n label=\"Inset {dir.charAt(0).toUpperCase() + dir.slice(1)}\"\n />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Inset mode combined with <strong>{dir}</strong> direction.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (insetOpen[dir] = false)}\n />\n {/snippet}\n </Drawer>\n {/each}\n </div>\n </section>\n\n <!-- Handle Options -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Handle Options</h2>\n <div class=\"flex flex-wrap gap-3 rounded-lg bg-surface-container-high p-4\">\n <Drawer\n bind:open={noHandleOpen}\n handle={false}\n title=\"No Handle\"\n description=\"Handle is hidden.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"No Handle\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">No drag handle visible. Still swipeable.</p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (noHandleOpen = false)}\n />\n {/snippet}\n </Drawer>\n\n <Drawer\n bind:open={handleOnlyOpen}\n handleOnly\n title=\"Handle Only\"\n description=\"Only the handle can be dragged.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Handle Only\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Content area is not draggable — only the handle responds to drag.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (handleOnlyOpen = false)}\n />\n {/snippet}\n </Drawer>\n </div>\n </section>\n\n <!-- Overlay & Modal -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Overlay & Modal</h2>\n <div class=\"flex flex-wrap gap-3 rounded-lg bg-surface-container-high p-4\">\n <Drawer\n bind:open={noOverlayOpen}\n overlay={false}\n modal={false}\n title=\"Non-Modal\"\n description=\"No overlay, background is interactive.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Non-Modal\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n No overlay. You can still interact with the page behind.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (noOverlayOpen = false)}\n />\n {/snippet}\n </Drawer>\n\n <Drawer\n bind:open={scaleBackgroundOpen}\n shouldScaleBackground\n title=\"Scale Background\"\n description=\"Background scales down when opened.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Scale Background\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n The page content behind scales down, creating a layered depth effect.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (scaleBackgroundOpen = false)}\n />\n {/snippet}\n </Drawer>\n </div>\n </section>\n\n <!-- Non-Dismissible -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Non-Dismissible</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Drawer\n bind:open={nonDismissibleOpen}\n dismissible={false}\n title=\"Non-Dismissible\"\n description=\"You must use the close button.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open (Non-Dismissible)\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Try swiping or clicking outside — the drawer will not close.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close Drawer\"\n variant=\"solid\"\n color=\"primary\"\n onclick={() => (nonDismissibleOpen = false)}\n />\n {/snippet}\n </Drawer>\n </div>\n </section>\n\n <!-- Snap Points -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Snap Points</h2>\n <div class=\"flex flex-wrap gap-3 rounded-lg bg-surface-container-high p-4\">\n <Drawer\n bind:open={snapOpen}\n snapPoints={[0.25, 0.5, 1]}\n fadeFromIndex={1}\n title=\"Snap Points\"\n description=\"Snaps at 25%, 50%, 100%.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"3 Snap Points\" />\n {/snippet}\n {#snippet body()}\n <div class=\"space-y-2\">\n <p class=\"text-on-surface-variant\">\n Drag between 25%, 50%, and 100% heights.\n </p>\n {#each Array.from({ length: 12 }, (_, i) => i) as i (i)}\n <div class=\"rounded-md bg-surface-container p-3\">\n <p class=\"text-sm text-on-surface-variant\">Item {i + 1}</p>\n </div>\n {/each}\n </div>\n {/snippet}\n </Drawer>\n\n <Drawer\n bind:open={snapControlledOpen}\n snapPoints={[0.25, 0.5, 1]}\n fadeFromIndex={1}\n bind:activeSnapPoint={activeSnap}\n title=\"Controlled Snap\"\n description=\"Active: {activeSnap}\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Controlled Snap\" />\n {/snippet}\n {#snippet body()}\n <div class=\"space-y-3\">\n <p class=\"text-on-surface-variant\">\n Active snap point: <strong>{activeSnap}</strong>\n </p>\n <div class=\"flex gap-2\">\n <Button\n size=\"sm\"\n variant=\"soft\"\n label=\"25%\"\n onclick={() => (activeSnap = 0.25)}\n />\n <Button\n size=\"sm\"\n variant=\"soft\"\n label=\"50%\"\n onclick={() => (activeSnap = 0.5)}\n />\n <Button\n size=\"sm\"\n variant=\"soft\"\n label=\"100%\"\n onclick={() => (activeSnap = 1)}\n />\n </div>\n </div>\n {/snippet}\n </Drawer>\n </div>\n </section>\n\n <!-- Nested Drawers -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Nested Drawers</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Drawer\n bind:open={nestedOuterOpen}\n title=\"Outer Drawer\"\n description=\"This is the parent drawer.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open Nested\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Click below to open a child drawer on top of this one.\n </p>\n <div class=\"mt-3\">\n <Drawer\n bind:open={nestedInnerOpen}\n nested\n title=\"Inner Drawer\"\n description=\"Nested child drawer.\"\n >\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"solid\"\n color=\"primary\"\n label=\"Open Inner Drawer\"\n />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n This is the nested drawer. Closing it returns to the outer\n drawer.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close Inner\"\n variant=\"outline\"\n onclick={() => (nestedInnerOpen = false)}\n />\n {/snippet}\n </Drawer>\n </div>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (nestedOuterOpen = false)}\n />\n {/snippet}\n </Drawer>\n </div>\n </section>\n\n <!-- Slots -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Slots</h2>\n <div class=\"flex flex-wrap gap-3 rounded-lg bg-surface-container-high p-4\">\n <!-- Custom header -->\n <Drawer bind:open={slotsOpen}>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Custom Header\" />\n {/snippet}\n {#snippet header()}\n <div class=\"flex items-center gap-3\">\n <div\n class=\"flex size-10 items-center justify-center rounded-full bg-primary text-on-primary\"\n >\n <Icon name=\"lucide:settings\" size=\"20\" />\n </div>\n <div>\n <h3 class=\"font-semibold text-on-surface\">Custom Header</h3>\n <p class=\"text-sm text-on-surface-variant\">With icon and layout</p>\n </div>\n </div>\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n The header slot replaces the default title + description.\n </p>\n {/snippet}\n {#snippet footer()}\n <div class=\"flex gap-2\">\n <Button\n label=\"Cancel\"\n variant=\"outline\"\n class=\"flex-1\"\n onclick={() => (slotsOpen = false)}\n />\n <Button\n label=\"Confirm\"\n variant=\"solid\"\n color=\"primary\"\n class=\"flex-1\"\n onclick={() => (slotsOpen = false)}\n />\n </div>\n {/snippet}\n </Drawer>\n\n <!-- Full content slot -->\n <Drawer bind:open={customContentOpen} title=\"Custom Content\">\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Content Slot\" />\n {/snippet}\n {#snippet content()}\n <div class=\"flex flex-col items-center gap-4 p-6\">\n <div\n class=\"flex size-16 items-center justify-center rounded-full bg-success/10\"\n >\n <Icon name=\"lucide:check-circle\" size=\"32\" class=\"text-success\" />\n </div>\n <h3 class=\"text-xl font-semibold text-on-surface\">Payment Successful</h3>\n <p class=\"text-center text-on-surface-variant\">\n The content slot replaces the entire inner layout.\n </p>\n <Button\n label=\"Done\"\n variant=\"solid\"\n color=\"primary\"\n onclick={() => (customContentOpen = false)}\n />\n </div>\n {/snippet}\n </Drawer>\n </div>\n </section>\n\n <!-- Lifecycle Callbacks -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Lifecycle Callbacks</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <div class=\"mb-3 space-y-1\">\n {#if callbackLog.length === 0}\n <p class=\"text-sm text-on-surface-variant italic\">\n Open/close the drawer to see callback logs...\n </p>\n {/if}\n {#each callbackLog as log, i (i)}\n <p class=\"font-mono text-xs text-on-surface-variant\">{log}</p>\n {/each}\n </div>\n <Drawer\n bind:open={callbacksOpen}\n onOpenChange={(v) => logCallback(`onOpenChange(${v})`)}\n onClose={() => logCallback('onClose()')}\n onAnimationEnd={(v) => logCallback(`onAnimationEnd(open=${v})`)}\n title=\"Callback Demo\"\n description=\"Check the log above.\"\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open (With Callbacks)\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n Open, close, and watch the callback log update.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (callbacksOpen = false)}\n />\n {/snippet}\n </Drawer>\n </div>\n </section>\n\n <!-- Programmatic Control -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Programmatic Control</h2>\n <div class=\"flex gap-3 rounded-lg bg-surface-container-high p-4\">\n <Button\n variant=\"outline\"\n label=\"Open Programmatically\"\n onclick={() => (programmaticOpen = true)}\n />\n <Drawer\n bind:open={programmaticOpen}\n title=\"Programmatic Drawer\"\n description=\"Opened without a trigger slot.\"\n >\n {#snippet body()}\n <p class=\"text-on-surface-variant\">\n This drawer has no trigger. It was opened by setting open = true externally.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (programmaticOpen = false)}\n />\n {/snippet}\n </Drawer>\n </div>\n </section>\n\n <!-- UI Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Slot Overrides</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Drawer\n bind:open={uiOverrideOpen}\n title=\"Styled Drawer\"\n description=\"Custom styles via the ui prop.\"\n ui={{\n content: 'bg-primary-container',\n title: 'text-on-primary-container',\n description: 'text-on-primary-container/70',\n handle: 'bg-on-primary-container/40',\n container: 'gap-3'\n }}\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" label=\"Open Styled Drawer\" />\n {/snippet}\n {#snippet body()}\n <p class=\"text-on-primary-container/80\">\n This drawer overrides content, title, description, handle, and container\n slot classes.\n </p>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Close\"\n variant=\"outline\"\n onclick={() => (uiOverrideOpen = false)}\n />\n {/snippet}\n </Drawer>\n </div>\n </section>\n\n <Separator />\n\n <!-- Real World Examples -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n <div class=\"grid gap-4 sm:grid-cols-2\">\n <!-- Mobile Settings -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Mobile Settings Panel</p>\n <Drawer bind:open={settingsOpen} title=\"Settings\">\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n leadingIcon=\"lucide:settings\"\n label=\"Settings\"\n class=\"w-full\"\n />\n {/snippet}\n {#snippet body()}\n <div class=\"space-y-4\">\n {#each [{ icon: 'lucide:user', label: 'Account', desc: 'Manage your profile' }, { icon: 'lucide:bell', label: 'Notifications', desc: 'Push, email, SMS' }, { icon: 'lucide:shield', label: 'Privacy', desc: 'Data and permissions' }, { icon: 'lucide:palette', label: 'Appearance', desc: 'Theme and display' }, { icon: 'lucide:globe', label: 'Language', desc: 'English (US)' }] as item (item.label)}\n <button\n class=\"flex w-full items-center gap-3 rounded-lg p-2 text-left transition-colors hover:bg-surface-container\"\n >\n <div\n class=\"flex size-10 items-center justify-center rounded-full bg-surface-container-highest\"\n >\n <Icon\n name={item.icon}\n size=\"18\"\n class=\"text-on-surface-variant\"\n />\n </div>\n <div class=\"flex-1\">\n <p class=\"text-sm font-medium text-on-surface\">\n {item.label}\n </p>\n <p class=\"text-xs text-on-surface-variant\">{item.desc}</p>\n </div>\n <Icon\n name=\"lucide:chevron-right\"\n size=\"16\"\n class=\"text-on-surface-variant\"\n />\n </button>\n {/each}\n </div>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Sign Out\"\n variant=\"soft\"\n color=\"error\"\n leadingIcon=\"lucide:log-out\"\n class=\"w-full\"\n onclick={() => (settingsOpen = false)}\n />\n {/snippet}\n </Drawer>\n </div>\n\n <!-- Notifications -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Notifications Drawer</p>\n <Drawer bind:open={notificationsOpen} direction=\"right\">\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n leadingIcon=\"lucide:bell\"\n label=\"Notifications\"\n class=\"w-full\"\n />\n {/snippet}\n {#snippet header()}\n <div class=\"flex items-center justify-between\">\n <h3 class=\"text-lg font-semibold text-on-surface\">Notifications</h3>\n <Badge variant=\"solid\" color=\"error\" size=\"xs\" label=\"3 new\" />\n </div>\n {/snippet}\n {#snippet body()}\n <div class=\"space-y-3\">\n {#each [{ title: 'New message', desc: 'John sent you a message', time: '2m ago', unread: true }, { title: 'Build completed', desc: 'Pipeline #482 passed', time: '15m ago', unread: true }, { title: 'Review requested', desc: 'PR #31 needs review', time: '1h ago', unread: true }, { title: 'Deploy finished', desc: 'v2.4.0 deployed to prod', time: '3h ago', unread: false }] as n (n.title)}\n <div\n class=\"flex gap-3 rounded-lg p-2 {n.unread\n ? 'bg-primary/5'\n : ''}\"\n >\n <div\n class=\"mt-0.5 size-2 shrink-0 rounded-full {n.unread\n ? 'bg-primary'\n : 'bg-transparent'}\"\n ></div>\n <div class=\"flex-1\">\n <p class=\"text-sm font-medium text-on-surface\">{n.title}</p>\n <p class=\"text-xs text-on-surface-variant\">{n.desc}</p>\n <p class=\"mt-1 text-xs text-on-surface-variant/60\">\n {n.time}\n </p>\n </div>\n </div>\n {/each}\n </div>\n {/snippet}\n {#snippet footer()}\n <Button\n label=\"Mark all as read\"\n variant=\"ghost\"\n color=\"primary\"\n class=\"w-full\"\n onclick={() => (notificationsOpen = false)}\n />\n {/snippet}\n </Drawer>\n </div>\n\n <!-- Filter Drawer -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Filter (Snap Points)</p>\n <Drawer\n bind:open={filterOpen}\n snapPoints={[0.4, 0.75, 1]}\n fadeFromIndex={1}\n title=\"Filters\"\n description=\"Refine your search results.\"\n >\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n leadingIcon=\"lucide:filter\"\n label=\"Filters\"\n class=\"w-full\"\n />\n {/snippet}\n {#snippet body()}\n <div class=\"space-y-4\">\n <div>\n <p class=\"mb-2 text-sm font-medium text-on-surface\">Category</p>\n <div class=\"flex flex-wrap gap-2\">\n {#each ['All', 'Electronics', 'Clothing', 'Books', 'Home'] as cat (cat)}\n <Button\n size=\"xs\"\n variant={cat === 'All' ? 'solid' : 'outline'}\n color={cat === 'All' ? 'primary' : 'secondary'}\n label={cat}\n />\n {/each}\n </div>\n </div>\n <Separator />\n <div>\n <p class=\"mb-2 text-sm font-medium text-on-surface\">Price Range</p>\n <div class=\"flex flex-wrap gap-2\">\n {#each ['Under $25', '$25-$50', '$50-$100', '$100+'] as price (price)}\n <Button\n size=\"xs\"\n variant=\"outline\"\n color=\"secondary\"\n label={price}\n />\n {/each}\n </div>\n </div>\n </div>\n {/snippet}\n {#snippet footer()}\n <div class=\"flex gap-2\">\n <Button\n label=\"Reset\"\n variant=\"outline\"\n class=\"flex-1\"\n onclick={() => (filterOpen = false)}\n />\n <Button\n label=\"Apply Filters\"\n variant=\"solid\"\n color=\"primary\"\n class=\"flex-1\"\n onclick={() => (filterOpen = false)}\n />\n </div>\n {/snippet}\n </Drawer>\n </div>\n\n <!-- Confirmation Drawer -->\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <p class=\"mb-3 text-sm font-medium\">Confirmation (Non-Dismissible)</p>\n <Drawer bind:open={confirmOpen} dismissible={false} handle={false}>\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n leadingIcon=\"lucide:trash-2\"\n label=\"Delete Account\"\n color=\"error\"\n class=\"w-full\"\n />\n {/snippet}\n {#snippet content()}\n <div class=\"flex flex-col items-center gap-4 p-6 text-center\">\n <div\n class=\"flex size-14 items-center justify-center rounded-full bg-error/10\"\n >\n <Icon name=\"lucide:alert-triangle\" size=\"28\" class=\"text-error\" />\n </div>\n <h3 class=\"text-lg font-semibold text-on-surface\">Delete Account?</h3>\n <p class=\"text-sm text-on-surface-variant\">\n This action is permanent and cannot be undone.\n </p>\n <div class=\"flex w-full gap-2\">\n <Button\n label=\"Cancel\"\n variant=\"outline\"\n class=\"flex-1\"\n onclick={() => (confirmOpen = false)}\n />\n <Button\n label=\"Delete\"\n variant=\"solid\"\n color=\"error\"\n class=\"flex-1\"\n onclick={() => (confirmOpen = false)}\n />\n </div>\n </div>\n {/snippet}\n </Drawer>\n </div>\n </div>\n </section>\n</div>\n",
170
172
  "dropdown-menu": "<script lang=\"ts\">\n import {\n DropdownMenu,\n Button,\n Separator,\n type DropdownMenuItem,\n type DropdownMenuRadioGroup\n } from '$lib/index.js'\n\n let controlledOpen = $state(false)\n let showStatusBar = $state(true)\n let showActivityBar = $state(false)\n let showPanel = $state(true)\n let selectedTheme = $state('system')\n let clickCount = $state(0)\n let option1 = $state(false)\n let option2 = $state(false)\n let option3 = $state(false)\n\n const basicItems: DropdownMenuItem[] = [\n { label: 'New File', icon: 'lucide:file-plus', kbds: ['meta', 'n'] },\n { label: 'New Window', icon: 'lucide:window', kbds: ['meta', 'shift', 'n'] },\n { type: 'separator' },\n { label: 'Open File...', icon: 'lucide:folder-open', kbds: ['meta', 'o'] },\n { label: 'Save', icon: 'lucide:save', kbds: ['meta', 's'] },\n { type: 'separator' },\n { label: 'Exit', icon: 'lucide:log-out' }\n ]\n\n const coloredItems: DropdownMenuItem[] = [\n { label: 'Edit', icon: 'lucide:pencil' },\n { label: 'Duplicate', icon: 'lucide:copy' },\n { type: 'separator' },\n { label: 'Archive', icon: 'lucide:archive', color: 'warning' },\n { label: 'Delete', icon: 'lucide:trash-2', color: 'error' }\n ]\n\n const checkboxItems: DropdownMenuItem[] = $derived([\n { type: 'label', label: 'Appearance' },\n {\n type: 'checkbox',\n label: 'Status Bar',\n checked: showStatusBar,\n onCheckedChange: (v: boolean) => (showStatusBar = v)\n },\n {\n type: 'checkbox',\n label: 'Activity Bar',\n checked: showActivityBar,\n onCheckedChange: (v: boolean) => (showActivityBar = v)\n },\n {\n type: 'checkbox',\n label: 'Panel',\n checked: showPanel,\n onCheckedChange: (v: boolean) => (showPanel = v)\n }\n ])\n\n const radioItems: DropdownMenuItem[] = [\n { type: 'label', label: 'Theme' },\n { type: 'radio', label: 'Light', value: 'light' },\n { type: 'radio', label: 'Dark', value: 'dark' },\n { type: 'radio', label: 'System', value: 'system' }\n ]\n\n const radioGroups: DropdownMenuRadioGroup[] = $derived([\n {\n name: 'theme',\n value: selectedTheme,\n onValueChange: (v: string) => (selectedTheme = v)\n }\n ])\n\n const closeOnSelectItems: DropdownMenuItem[] = $derived([\n {\n label: 'Click me (stays open)',\n icon: 'lucide:hand-metal',\n closeOnSelect: false,\n onSelect: () => clickCount++\n },\n {\n label: 'Me too (stays open)',\n icon: 'lucide:hand-metal',\n closeOnSelect: false,\n onSelect: () => clickCount++\n },\n { type: 'separator' },\n {\n label: 'Click me (closes menu)',\n icon: 'lucide:log-out',\n onSelect: () => clickCount++\n }\n ])\n\n const checkboxCloseOnSelectItems: DropdownMenuItem[] = $derived([\n { type: 'label', label: 'Select Multiple' },\n {\n type: 'checkbox',\n label: 'Option 1',\n checked: option1,\n closeOnSelect: false,\n onCheckedChange: (v: boolean) => (option1 = v)\n },\n {\n type: 'checkbox',\n label: 'Option 2',\n checked: option2,\n closeOnSelect: false,\n onCheckedChange: (v: boolean) => (option2 = v)\n },\n {\n type: 'checkbox',\n label: 'Option 3',\n checked: option3,\n closeOnSelect: false,\n onCheckedChange: (v: boolean) => (option3 = v)\n }\n ])\n\n const submenuItems: DropdownMenuItem[] = [\n { label: 'Back', icon: 'lucide:arrow-left', kbds: ['meta', '['] },\n { label: 'Forward', icon: 'lucide:arrow-right', kbds: ['meta', ']'], disabled: true },\n { label: 'Reload', icon: 'lucide:refresh-cw', kbds: ['meta', 'r'] },\n { type: 'separator' },\n {\n type: 'sub',\n label: 'More Tools',\n icon: 'lucide:wrench',\n items: [\n { label: 'Save Page As...', kbds: ['meta', 's'] },\n { label: 'Create Shortcut...' },\n { label: 'Name Window...' },\n { type: 'separator' },\n { label: 'Developer Tools', kbds: ['meta', 'alt', 'i'] }\n ]\n }\n ]\n\n const profileItems: DropdownMenuItem[] = [\n { type: 'label', label: 'My Account' },\n { label: 'Profile', icon: 'lucide:user', kbds: ['meta', 'p'] },\n { label: 'Billing', icon: 'lucide:credit-card', kbds: ['meta', 'b'] },\n { label: 'Settings', icon: 'lucide:settings', kbds: ['meta', ','] },\n { type: 'separator' },\n { label: 'Team', icon: 'lucide:users' },\n {\n type: 'sub',\n label: 'Invite users',\n icon: 'lucide:user-plus',\n items: [\n { label: 'Email', icon: 'lucide:mail' },\n { label: 'Message', icon: 'lucide:message-square' },\n { type: 'separator' },\n { label: 'More...', icon: 'lucide:plus-circle' }\n ]\n },\n { label: 'New Team', icon: 'lucide:plus', kbds: ['meta', 't'] },\n { type: 'separator' },\n { label: 'GitHub', icon: 'lucide:github' },\n { label: 'Support', icon: 'lucide:life-buoy' },\n { label: 'API', icon: 'lucide:cloud', disabled: true },\n { type: 'separator' },\n { label: 'Log out', icon: 'lucide:log-out', kbds: ['meta', 'shift', 'q'] }\n ]\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">DropdownMenu</h1>\n <p class=\"text-on-surface-variant\">\n Display a menu of actions or options triggered by a button. Built on bits-ui\n DropdownMenu primitive.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <DropdownMenu items={basicItems}>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\">\n File\n <span class=\"ml-2 text-xs opacity-60\">Alt+F</span>\n </Button>\n {/snippet}\n </DropdownMenu>\n </div>\n </section>\n\n <!-- Positions -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Positions</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Control dropdown placement with the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">side</code>\n prop.\n </p>\n <div\n class=\"flex flex-wrap items-center justify-center gap-8 rounded-lg bg-surface-container-high p-8\"\n >\n {#each [{ side: 'top' as const, label: 'Top' }, { side: 'right' as const, label: 'Right' }, { side: 'bottom' as const, label: 'Bottom' }, { side: 'left' as const, label: 'Left' }] as item (item.side)}\n <DropdownMenu items={basicItems.slice(0, 4)} side={item.side}>\n {#snippet children({ props })}\n <Button {...props} variant=\"soft\">{item.label}</Button>\n {/snippet}\n </DropdownMenu>\n {/each}\n </div>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n {#each [{ size: 'xs' as const, label: 'XS' }, { size: 'sm' as const, label: 'SM' }, { size: 'md' as const, label: 'MD' }, { size: 'lg' as const, label: 'LG' }, { size: 'xl' as const, label: 'XL' }] as item (item.size)}\n <DropdownMenu items={basicItems.slice(0, 4)} size={item.size}>\n {#snippet children({ props })}\n <Button {...props} size={item.size} variant=\"outline\">{item.label}</Button>\n {/snippet}\n </DropdownMenu>\n {/each}\n </div>\n </section>\n\n <!-- Colored Items -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Colored Items</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">color</code>\n prop on items for semantic coloring.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <DropdownMenu items={coloredItems}>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" icon=\"lucide:more-horizontal\"\n >Actions</Button\n >\n {/snippet}\n </DropdownMenu>\n </div>\n </section>\n\n <!-- Checkbox Items -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Checkbox Items</h2>\n <p class=\"text-sm text-on-surface-variant\">Toggle boolean states with checkbox items.</p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <DropdownMenu items={checkboxItems}>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" icon=\"lucide:layout\">View</Button>\n {/snippet}\n </DropdownMenu>\n <div class=\"text-sm text-on-surface-variant\">\n <p>Status Bar: <code class=\"text-primary\">{showStatusBar}</code></p>\n <p>Activity Bar: <code class=\"text-primary\">{showActivityBar}</code></p>\n <p>Panel: <code class=\"text-primary\">{showPanel}</code></p>\n </div>\n </div>\n </section>\n\n <!-- Radio Items -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Radio Items</h2>\n <p class=\"text-sm text-on-surface-variant\">Single selection with radio items and groups.</p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <DropdownMenu items={radioItems} {radioGroups}>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" icon=\"lucide:sun-moon\">Theme</Button>\n {/snippet}\n </DropdownMenu>\n <div class=\"text-sm text-on-surface-variant\">\n Selected: <code class=\"text-primary\">{selectedTheme}</code>\n </div>\n </div>\n </section>\n\n <!-- Submenus -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Submenus</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <DropdownMenu items={submenuItems}>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" icon=\"lucide:menu\">Navigate</Button>\n {/snippet}\n </DropdownMenu>\n </div>\n </section>\n\n <!-- Close On Select -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Close On Select</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\"\n >closeOnSelect: false</code\n >\n to keep the menu open after clicking an item.\n </p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <DropdownMenu items={closeOnSelectItems}>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" icon=\"lucide:mouse-pointer-click\"\n >Actions</Button\n >\n {/snippet}\n </DropdownMenu>\n <DropdownMenu items={checkboxCloseOnSelectItems}>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" icon=\"lucide:check-square\"\n >Multi-Select</Button\n >\n {/snippet}\n </DropdownMenu>\n <div class=\"text-sm text-on-surface-variant\">\n <p>Click count: <code class=\"text-primary\">{clickCount}</code></p>\n <p>Options: <code class=\"text-primary\">[{option1}, {option2}, {option3}]</code></p>\n </div>\n </div>\n </section>\n\n <!-- Controlled -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Controlled</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Control dropdown visibility programmatically with\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">open</code>\n binding.\n </p>\n <div class=\"grid gap-4 sm:grid-cols-2\">\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Observe click state</p>\n <div class=\"flex items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <DropdownMenu items={basicItems.slice(0, 4)} bind:open={controlledOpen}>\n {#snippet children({ props })}\n <Button {...props} variant={controlledOpen ? 'solid' : 'outline'}>\n Click me\n </Button>\n {/snippet}\n </DropdownMenu>\n <span class=\"text-sm text-on-surface-variant\">\n open: <code class=\"text-primary\">{controlledOpen}</code>\n </span>\n </div>\n </div>\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Toggle programmatically</p>\n <div class=\"flex items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <DropdownMenu items={basicItems.slice(0, 4)} open={controlledOpen}>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\">Target</Button>\n {/snippet}\n </DropdownMenu>\n <Button variant=\"soft\" onclick={() => (controlledOpen = !controlledOpen)}>\n {controlledOpen ? 'Close' : 'Open'}\n </Button>\n </div>\n </div>\n </div>\n </section>\n\n <!-- Custom Header/Footer -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Header/Footer</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <DropdownMenu items={basicItems.slice(0, 4)}>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" icon=\"lucide:user-circle\">Account</Button>\n {/snippet}\n {#snippet header()}\n <div class=\"px-3 py-2\">\n <p class=\"text-sm font-medium\">John Doe</p>\n <p class=\"text-xs text-on-surface-variant\">john@example.com</p>\n </div>\n <Separator />\n {/snippet}\n {#snippet footer({ close })}\n <Separator />\n <div class=\"p-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n class=\"w-full justify-start\"\n icon=\"lucide:log-out\"\n color=\"error\"\n onclick={close}\n >\n Log out\n </Button>\n </div>\n {/snippet}\n </DropdownMenu>\n </div>\n </section>\n\n <!-- Custom Content -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Content</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">content</code>\n slot for fully custom dropdown content.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <DropdownMenu>\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\" icon=\"lucide:palette\">Colors</Button>\n {/snippet}\n {#snippet content({ close })}\n <div class=\"p-4\">\n <p class=\"mb-3 text-sm font-medium\">Choose a color</p>\n <div class=\"grid grid-cols-5 gap-2\">\n {#each ['bg-red-500', 'bg-orange-500', 'bg-yellow-500', 'bg-green-500', 'bg-teal-500', 'bg-blue-500', 'bg-indigo-500', 'bg-purple-500', 'bg-pink-500', 'bg-gray-500'] as color (color)}\n <button\n class=\"size-8 rounded-full {color} transition-all hover:ring-2 hover:ring-outline hover:ring-offset-2\"\n aria-label=\"Select {color\n .replace('bg-', '')\n .replace('-500', '')} color\"\n onclick={close}\n ></button>\n {/each}\n </div>\n </div>\n {/snippet}\n </DropdownMenu>\n </div>\n </section>\n\n <!-- UI Slot Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Slot Overrides</h2>\n <div class=\"grid gap-4 sm:grid-cols-2\">\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Primary theme</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <DropdownMenu\n items={basicItems.slice(0, 4)}\n ui={{\n content: 'bg-primary text-on-primary ring-primary/50',\n item: 'data-[highlighted]:bg-on-primary/20',\n separator: 'bg-on-primary/20'\n }}\n >\n {#snippet children({ props })}\n <Button {...props}>Primary Style</Button>\n {/snippet}\n </DropdownMenu>\n </div>\n </div>\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Custom rounding</p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <DropdownMenu\n items={basicItems.slice(0, 4)}\n ui={{ content: 'rounded-xl shadow-2xl' }}\n >\n {#snippet children({ props })}\n <Button {...props} variant=\"outline\">Rounded</Button>\n {/snippet}\n </DropdownMenu>\n </div>\n </div>\n </div>\n </section>\n\n <Separator />\n\n <!-- Real World Examples -->\n <section class=\"space-y-6\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <!-- Profile Menu -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">Profile Menu</p>\n <div\n class=\"flex items-center justify-center rounded-lg bg-surface-container-high p-6\"\n >\n <DropdownMenu items={profileItems}>\n {#snippet children({ props })}\n <Button {...props} icon=\"lucide:chevron-down\" trailing>\n <span class=\"flex items-center gap-2\">\n <span\n class=\"flex size-6 items-center justify-center rounded-full bg-primary text-xs text-on-primary\"\n >\n JD\n </span>\n shadcn\n </span>\n </Button>\n {/snippet}\n </DropdownMenu>\n </div>\n </div>\n\n <!-- Context Menu Style -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">Right-Click Style</p>\n <div\n class=\"flex items-center justify-center rounded-lg bg-surface-container-high p-6\"\n >\n <DropdownMenu items={coloredItems} arrow align=\"center\">\n {#snippet children({ props })}\n <Button\n {...props}\n variant=\"outline\"\n icon=\"lucide:more-vertical\"\n square\n aria-label=\"More options\"\n />\n {/snippet}\n </DropdownMenu>\n </div>\n </div>\n </div>\n </section>\n</div>\n",
171
173
  "popover": "<script lang=\"ts\">\n import { Popover, Button, Badge, Icon, Separator } from '$lib/index.js'\n\n let controlledOpen = $state(false)\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Popover</h1>\n <p class=\"text-on-surface-variant\">\n Display rich content in a floating panel triggered by click. Built on bits-ui Popover\n primitive.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Popover>\n <Button variant=\"outline\">Click me</Button>\n {#snippet content()}\n <div class=\"w-72 p-4\">\n <p class=\"text-sm font-medium\">Popover Content</p>\n <p class=\"mt-1 text-sm text-on-surface-variant\">\n This is a simple popover with some informational text.\n </p>\n </div>\n {/snippet}\n </Popover>\n </div>\n </section>\n\n <!-- Positions -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Positions</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Control popover placement with the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">side</code>\n prop.\n </p>\n <div\n class=\"flex flex-wrap items-center justify-center gap-8 rounded-lg bg-surface-container-high p-8\"\n >\n {#each [{ side: 'top' as const, label: 'Top' }, { side: 'right' as const, label: 'Right' }, { side: 'bottom' as const, label: 'Bottom' }, { side: 'left' as const, label: 'Left' }] as item (item.side)}\n <Popover side={item.side}>\n <Button variant=\"soft\">{item.label}</Button>\n {#snippet content()}\n <div class=\"p-3\">\n <p class=\"text-sm\">Popover on {item.side}</p>\n </div>\n {/snippet}\n </Popover>\n {/each}\n </div>\n </section>\n\n <!-- Alignment -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Alignment</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Control alignment with the\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">align</code>\n prop.\n </p>\n <div\n class=\"flex flex-wrap items-center justify-center gap-8 rounded-lg bg-surface-container-high p-8\"\n >\n {#each [{ align: 'start' as const, label: 'Start' }, { align: 'center' as const, label: 'Center' }, { align: 'end' as const, label: 'End' }] as item (item.align)}\n <Popover side=\"bottom\" align={item.align}>\n <Button variant=\"outline\">{item.label}</Button>\n {#snippet content()}\n <div class=\"w-48 p-3\">\n <p class=\"text-sm\">Aligned to {item.align}</p>\n </div>\n {/snippet}\n </Popover>\n {/each}\n </div>\n </section>\n\n <!-- Arrow -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Arrow</h2>\n <div class=\"grid gap-4 sm:grid-cols-2\">\n {#each [{ side: 'top' as const, label: 'Top' }, { side: 'right' as const, label: 'Right' }, { side: 'bottom' as const, label: 'Bottom' }, { side: 'left' as const, label: 'Left' }] as item (item.side)}\n <div\n class=\"flex items-center justify-center rounded-lg bg-surface-container-high p-6\"\n >\n <Popover arrow side={item.side}>\n <Button>{item.label}</Button>\n {#snippet content()}\n <div class=\"p-3\">\n <p class=\"text-sm\">Content with arrow</p>\n </div>\n {/snippet}\n </Popover>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Close Action -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Close Action</h2>\n <p class=\"text-sm text-on-surface-variant\">\n The\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">content</code>\n snippet exposes a\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">close</code>\n function to programmatically dismiss the popover.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Popover>\n <Button variant=\"outline\">Confirm Action</Button>\n {#snippet content({ close })}\n <div class=\"w-72 p-4\">\n <div class=\"flex items-center justify-between\">\n <p class=\"font-medium\">Confirm Action</p>\n <Button\n icon=\"lucide:x\"\n square\n variant=\"ghost\"\n size=\"xs\"\n onclick={close}\n />\n </div>\n <p class=\"mt-2 text-sm text-on-surface-variant\">\n Are you sure you want to proceed with this action?\n </p>\n <div class=\"mt-4 flex justify-end gap-2\">\n <Button variant=\"outline\" size=\"sm\" onclick={close}>Cancel</Button>\n <Button size=\"sm\" onclick={close}>Confirm</Button>\n </div>\n </div>\n {/snippet}\n </Popover>\n </div>\n </section>\n\n <!-- Controlled -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Controlled</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Control popover visibility programmatically with\n <code class=\"rounded bg-surface-container-highest px-1.5 py-0.5 text-xs\">open</code>\n binding.\n </p>\n <div class=\"grid gap-4 sm:grid-cols-2\">\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Observe click state</p>\n <div class=\"flex items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <Popover bind:open={controlledOpen}>\n <Button variant={controlledOpen ? 'solid' : 'outline'}>Click me</Button>\n {#snippet content()}\n <div class=\"w-64 p-4\">\n <p class=\"text-sm\">Controlled popover content</p>\n </div>\n {/snippet}\n </Popover>\n <span class=\"text-sm text-on-surface-variant\">\n open: <code class=\"text-primary\">{controlledOpen}</code>\n </span>\n </div>\n </div>\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Toggle programmatically</p>\n <div class=\"flex items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <Popover open={controlledOpen}>\n <Button variant=\"outline\">Target</Button>\n {#snippet content()}\n <div class=\"w-64 p-4\">\n <p class=\"text-sm\">Programmatic popover</p>\n </div>\n {/snippet}\n </Popover>\n <Button variant=\"soft\" onclick={() => (controlledOpen = !controlledOpen)}>\n {controlledOpen ? 'Close' : 'Open'}\n </Button>\n </div>\n </div>\n </div>\n </section>\n\n <!-- Non-dismissible -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Non-dismissible</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Prevent dismissing by clicking outside or pressing Escape.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Popover dismissible={false}>\n <Button variant=\"outline\">Non-dismissible</Button>\n {#snippet content({ close })}\n <div class=\"w-72 p-4\">\n <p class=\"text-sm font-medium\">Cannot dismiss by clicking outside</p>\n <p class=\"mt-1 text-sm text-on-surface-variant\">\n You must use the close button to dismiss this popover.\n </p>\n <div class=\"mt-3 flex justify-end\">\n <Button size=\"sm\" onclick={close}>Got it</Button>\n </div>\n </div>\n {/snippet}\n </Popover>\n </div>\n </section>\n\n <!-- UI Slot Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Slot Overrides</h2>\n <div class=\"grid gap-4 sm:grid-cols-2\">\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Custom rounding</p>\n <div\n class=\"flex items-center justify-center rounded-lg bg-surface-container-high p-6\"\n >\n <Popover ui={{ content: 'rounded-xl shadow-2xl' }}>\n <Button variant=\"outline\">Rounded</Button>\n {#snippet content()}\n <div class=\"w-64 p-4\">\n <p class=\"text-sm\">Extra rounded with larger shadow.</p>\n </div>\n {/snippet}\n </Popover>\n </div>\n </div>\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">No ring border</p>\n <div\n class=\"flex items-center justify-center rounded-lg bg-surface-container-high p-6\"\n >\n <Popover ui={{ content: 'ring-0 shadow-xl' }}>\n <Button variant=\"outline\">No Ring</Button>\n {#snippet content()}\n <div class=\"w-64 p-4\">\n <p class=\"text-sm\">Ring removed, shadow only.</p>\n </div>\n {/snippet}\n </Popover>\n </div>\n </div>\n </div>\n </section>\n\n <Separator />\n\n <!-- Real World Examples -->\n <section class=\"space-y-6\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <!-- User Profile Card -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">User Profile Card</p>\n <div\n class=\"flex items-center justify-center rounded-lg bg-surface-container-high p-6\"\n >\n <Popover>\n <Button variant=\"soft\" icon=\"lucide:user\">Profile</Button>\n {#snippet content()}\n <div class=\"w-72\">\n <div class=\"p-4\">\n <div class=\"flex items-center gap-3\">\n <div\n class=\"flex size-10 items-center justify-center rounded-full bg-primary text-on-primary\"\n >\n <Icon name=\"lucide:user\" size=\"20\" />\n </div>\n <div>\n <p class=\"font-medium\">John Doe</p>\n <p class=\"text-sm text-on-surface-variant\">\n john@example.com\n </p>\n </div>\n </div>\n <Separator class=\"my-3\" />\n <div class=\"flex gap-4 text-sm text-on-surface-variant\">\n <span\n ><strong class=\"text-on-surface\">128</strong> posts</span\n >\n <span\n ><strong class=\"text-on-surface\">1.2k</strong> followers</span\n >\n </div>\n </div>\n <Separator />\n <div class=\"p-2\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n class=\"w-full justify-start\"\n icon=\"lucide:settings\">Settings</Button\n >\n <Button\n variant=\"ghost\"\n size=\"sm\"\n class=\"w-full justify-start\"\n icon=\"lucide:log-out\"\n color=\"error\">Sign out</Button\n >\n </div>\n </div>\n {/snippet}\n </Popover>\n </div>\n </div>\n\n <!-- Share Menu -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">Share Menu</p>\n <div\n class=\"flex items-center justify-center rounded-lg bg-surface-container-high p-6\"\n >\n <Popover>\n <Button variant=\"outline\" icon=\"lucide:share-2\">Share</Button>\n {#snippet content({ close })}\n <div class=\"w-56 p-2\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n class=\"w-full justify-start\"\n icon=\"lucide:link\"\n onclick={close}>Copy link</Button\n >\n <Button\n variant=\"ghost\"\n size=\"sm\"\n class=\"w-full justify-start\"\n icon=\"lucide:twitter\"\n onclick={close}>Twitter</Button\n >\n <Button\n variant=\"ghost\"\n size=\"sm\"\n class=\"w-full justify-start\"\n icon=\"lucide:facebook\"\n onclick={close}>Facebook</Button\n >\n <Button\n variant=\"ghost\"\n size=\"sm\"\n class=\"w-full justify-start\"\n icon=\"lucide:mail\"\n onclick={close}>Email</Button\n >\n </div>\n {/snippet}\n </Popover>\n </div>\n </div>\n\n <!-- Notification Panel -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">Notification Panel</p>\n <div\n class=\"flex items-center justify-center rounded-lg bg-surface-container-high p-6\"\n >\n <Popover>\n <Button variant=\"outline\" icon=\"lucide:bell\">Notifications</Button>\n {#snippet content()}\n <div class=\"w-80\">\n <div class=\"flex items-center justify-between p-4 pb-2\">\n <p class=\"font-medium\">Notifications</p>\n <Badge label=\"3 new\" size=\"xs\" color=\"primary\" />\n </div>\n <div class=\"divide-y divide-outline-variant\">\n <div class=\"flex gap-3 p-4\">\n <div\n class=\"flex size-8 shrink-0 items-center justify-center rounded-full bg-primary/10 text-primary\"\n >\n <Icon name=\"lucide:message-circle\" size=\"16\" />\n </div>\n <div>\n <p class=\"text-sm\">New comment on your post</p>\n <p class=\"text-xs text-on-surface-variant\">\n 2 minutes ago\n </p>\n </div>\n </div>\n <div class=\"flex gap-3 p-4\">\n <div\n class=\"flex size-8 shrink-0 items-center justify-center rounded-full bg-success/10 text-success\"\n >\n <Icon name=\"lucide:user-plus\" size=\"16\" />\n </div>\n <div>\n <p class=\"text-sm\">New follower: Jane Smith</p>\n <p class=\"text-xs text-on-surface-variant\">\n 1 hour ago\n </p>\n </div>\n </div>\n </div>\n </div>\n {/snippet}\n </Popover>\n </div>\n </div>\n\n <!-- Filter Panel -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium\">Filter Panel</p>\n <div\n class=\"flex items-center justify-center rounded-lg bg-surface-container-high p-6\"\n >\n <Popover>\n <Button variant=\"outline\" icon=\"lucide:filter\">Filters</Button>\n {#snippet content({ close })}\n <div class=\"w-72\">\n <div class=\"p-4\">\n <p class=\"font-medium\">Filter Results</p>\n </div>\n <Separator />\n <div class=\"space-y-3 p-4\">\n <div>\n <p class=\"text-sm font-medium\">Status</p>\n <div class=\"mt-1 flex gap-2\">\n <Badge label=\"Active\" color=\"success\" />\n <Badge label=\"Pending\" color=\"warning\" />\n <Badge label=\"Closed\" color=\"error\" />\n </div>\n </div>\n <div>\n <p class=\"text-sm font-medium\">Priority</p>\n <div class=\"mt-1 flex gap-2\">\n <Badge label=\"High\" />\n <Badge label=\"Medium\" />\n <Badge label=\"Low\" />\n </div>\n </div>\n </div>\n <Separator />\n <div class=\"flex justify-end gap-2 p-3\">\n <Button variant=\"ghost\" size=\"sm\" onclick={close}>Reset</Button>\n <Button size=\"sm\" onclick={close}>Apply</Button>\n </div>\n </div>\n {/snippet}\n </Popover>\n </div>\n </div>\n </div>\n </section>\n</div>\n",