svelora 3.0.8 → 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.
@@ -1,14 +1,20 @@
1
- <script lang="ts">import { untrack } from "svelte";
1
+ <script lang="ts">import { untrack, getContext } from "svelte";
2
2
  import { twMerge } from "tailwind-merge";
3
- import Icon from "../Icon/Icon.svelte";
3
+ import { Icon } from "../Icon/index.js";
4
4
  import Badge from "../Badge/Badge.svelte";
5
5
  import Kbd from "../Kbd/Kbd.svelte";
6
- import DropdownMenu from "../DropdownMenu/DropdownMenu.svelte";
6
+ import { DropdownMenu } from "../DropdownMenu/index.js";
7
+ import { Tooltip } from "../Tooltip/index.js";
7
8
  import { navigationMenuVariants } from "./navigation-menu.variants.js";
8
9
  let { items = [], variant = "default", orientation = "horizontal", accordion = false, class: className, ui, children } = $props();
10
+ const sidebarCollapsedFn = getContext("sidebar-collapsed");
11
+ let isCollapsed = $derived(sidebarCollapsedFn ? sidebarCollapsedFn() : false);
12
+ const sidebarPositionFn = getContext("sidebar-position");
13
+ let sidebarPosition = $derived(sidebarPositionFn ? sidebarPositionFn() : "left");
9
14
  let styles = $derived(navigationMenuVariants({
10
15
  variant,
11
- orientation
16
+ orientation,
17
+ collapsed: isCollapsed
12
18
  }));
13
19
  let normalizedItems = $derived.by(() => {
14
20
  if (!items || items.length === 0) return [];
@@ -89,67 +95,94 @@ function getKbds(item) {
89
95
  >
90
96
  {#snippet children({ props, open })}
91
97
  <!-- svelte-ignore a11y_no_static_element_interactions -->
92
- <button
93
- type="button"
94
- {...props}
95
- class={twMerge(styles.item({ active: isActive(item) }), item.class)}
96
- disabled={item.disabled}
97
- >
98
- {#if item.icon}
99
- <Icon name={item.icon} class={styles.icon({ active: isActive(item) })} />
100
- {/if}
101
- <span>{item.label}</span>
102
- {#if item.badge !== undefined}
103
- <Badge label={String(item.badge)} color={item.badgeColor || 'primary'} size="sm" class="ml-1" />
104
- {/if}
105
- <span class="ml-auto flex items-center">
106
- <Icon
107
- name="lucide:chevron-down"
108
- class={twMerge(styles.chevron(), open ? 'rotate-180' : '')}
109
- />
110
- </span>
111
- </button>
98
+ {#snippet buttonContent()}
99
+ <button
100
+ type="button"
101
+ {...props}
102
+ class={twMerge(styles.item({ active: isActive(item), collapsed: isCollapsed }), item.class)}
103
+ disabled={item.disabled}
104
+ >
105
+ {#if item.icon}
106
+ <Icon name={item.icon} class={styles.icon({ active: isActive(item), collapsed: isCollapsed })} />
107
+ {/if}
108
+ {#if !isCollapsed}
109
+ <span>{item.label}</span>
110
+ {#if item.badge !== undefined}
111
+ <Badge label={String(item.badge)} color={item.badgeColor || 'primary'} size="sm" class="ml-1" />
112
+ {/if}
113
+ <span class="ml-auto flex items-center">
114
+ <Icon
115
+ name="lucide:chevron-down"
116
+ class={twMerge(styles.chevron(), open ? 'rotate-180' : '')}
117
+ />
118
+ </span>
119
+ {/if}
120
+ </button>
121
+ {/snippet}
122
+
123
+ {#if isCollapsed}
124
+ <Tooltip text={item.label} side={sidebarPosition === 'right' ? 'left' : 'right'}>
125
+ {@render buttonContent()}
126
+ </Tooltip>
127
+ {:else}
128
+ {@render buttonContent()}
129
+ {/if}
112
130
  {/snippet}
113
131
  </DropdownMenu>
114
132
  {:else}
115
133
  <!-- VERTICAL: Accordion -->
116
- <button
117
- type="button"
118
- class={twMerge(
119
- styles.accordionTrigger(),
120
- isGroupOpen(item) ? styles.item({ active: true }) : '',
121
- item.class
122
- )}
123
- disabled={item.disabled}
124
- onclick={() => handleGroupToggle(item)}
125
- >
126
- <div class="flex flex-1 items-center truncate">
127
- {#if item.icon}
128
- <Icon name={item.icon} class={styles.icon({ active: isActive(item) })} />
129
- {/if}
130
- <span class="truncate">{item.label}</span>
131
- </div>
132
- <div class="flex items-center gap-2">
133
- {#if item.badge !== undefined || getKbds(item).length > 0}
134
- <span class="flex items-center gap-2">
135
- {#if item.badge !== undefined}
136
- <Badge label={String(item.badge)} color={item.badgeColor || 'primary'} size="sm" />
137
- {/if}
138
- {#if getKbds(item).length > 0}
139
- <span class="flex items-center gap-0.5">
140
- {#each getKbds(item) as key}
141
- <Kbd value={typeof key === 'string' ? key : key.value} size="sm" />
142
- {/each}
134
+ {#snippet accordionButton()}
135
+ <button
136
+ type="button"
137
+ class={twMerge(
138
+ styles.accordionTrigger(),
139
+ isGroupOpen(item) ? styles.item({ active: true, collapsed: isCollapsed }) : '',
140
+ isCollapsed ? styles.item({ collapsed: true }) : '',
141
+ item.class
142
+ )}
143
+ disabled={item.disabled}
144
+ onclick={() => handleGroupToggle(item)}
145
+ >
146
+ <div class="flex flex-1 items-center truncate">
147
+ {#if item.icon}
148
+ <Icon name={item.icon} class={styles.icon({ active: isActive(item), collapsed: isCollapsed })} />
149
+ {/if}
150
+ {#if !isCollapsed}
151
+ <span class="truncate ml-1.5">{item.label}</span>
152
+ {/if}
153
+ </div>
154
+ {#if !isCollapsed}
155
+ <div class="flex items-center gap-2">
156
+ {#if item.badge !== undefined || getKbds(item).length > 0}
157
+ <span class="flex items-center gap-2">
158
+ {#if item.badge !== undefined}
159
+ <Badge label={String(item.badge)} color={item.badgeColor || 'primary'} size="sm" />
160
+ {/if}
161
+ {#if getKbds(item).length > 0}
162
+ <span class="flex items-center gap-0.5">
163
+ {#each getKbds(item) as key}
164
+ <Kbd value={typeof key === 'string' ? key : key.value} size="sm" />
165
+ {/each}
166
+ </span>
167
+ {/if}
143
168
  </span>
144
169
  {/if}
145
- </span>
170
+ <Icon
171
+ name="lucide:chevron-down"
172
+ class={twMerge(styles.chevron(), isGroupOpen(item) ? 'rotate-180' : '')}
173
+ />
174
+ </div>
146
175
  {/if}
147
- <Icon
148
- name="lucide:chevron-down"
149
- class={twMerge(styles.chevron(), isGroupOpen(item) ? 'rotate-180' : '')}
150
- />
151
- </div>
152
- </button>
176
+ </button>
177
+ {/snippet}
178
+
179
+ {#if isCollapsed}
180
+ <Tooltip text={item.label} side={sidebarPosition === 'right' ? 'left' : 'right'}>
181
+ {@render accordionButton()}
182
+ </Tooltip>
183
+ {:else}
184
+ {@render accordionButton()}
185
+ {/if}
153
186
  {#if isGroupOpen(item)}
154
187
  <ul class={styles.accordionGroupContent()}>
155
188
  {#each subItems as subItem}
@@ -161,38 +194,48 @@ function getKbds(item) {
161
194
  {:else}
162
195
  <!-- STANDARD LINK -->
163
196
  <!-- svelte-ignore a11y_no_static_element_interactions -->
164
- <svelte:element
165
- this={item.href ? 'a' : 'button'}
166
- href={item.href}
167
- target={item.target}
168
- type={!item.href ? 'button' : undefined}
169
- class={twMerge(styles.item({ active: isActive(item) }), item.class)}
170
- disabled={item.disabled}
171
- onclick={item.onClick}
172
- >
173
- <div class="flex flex-1 items-center truncate gap-1.5">
174
- {#if item.icon}
175
- <Icon name={item.icon} class={styles.icon({ active: isActive(item) })} />
176
- {/if}
177
- {#if item.label}
178
- <span class="truncate">{item.label}</span>
179
- {/if}
180
- </div>
181
- {#if item.badge !== undefined || getKbds(item).length > 0}
182
- <span class="ml-auto flex items-center gap-2">
183
- {#if item.badge !== undefined}
184
- <Badge label={String(item.badge)} color={item.badgeColor || 'primary'} size="sm" />
197
+ {#snippet linkContent()}
198
+ <svelte:element
199
+ this={item.href ? 'a' : 'button'}
200
+ href={item.href}
201
+ target={item.target}
202
+ type={!item.href ? 'button' : undefined}
203
+ class={twMerge(styles.item({ active: isActive(item), collapsed: isCollapsed }), item.class)}
204
+ disabled={item.disabled}
205
+ onclick={item.onClick}
206
+ >
207
+ <div class="flex flex-1 items-center truncate gap-1.5">
208
+ {#if item.icon}
209
+ <Icon name={item.icon} class={styles.icon({ active: isActive(item), collapsed: isCollapsed })} />
185
210
  {/if}
186
- {#if getKbds(item).length > 0}
187
- <span class="flex items-center gap-0.5">
188
- {#each getKbds(item) as key}
189
- <Kbd value={typeof key === 'string' ? key : key.value} size="sm" />
190
- {/each}
191
- </span>
211
+ {#if !isCollapsed && item.label}
212
+ <span class="truncate">{item.label}</span>
192
213
  {/if}
193
- </span>
194
- {/if}
195
- </svelte:element>
214
+ </div>
215
+ {#if !isCollapsed && (item.badge !== undefined || getKbds(item).length > 0)}
216
+ <span class="ml-auto flex items-center gap-2">
217
+ {#if item.badge !== undefined}
218
+ <Badge label={String(item.badge)} color={item.badgeColor || 'primary'} size="sm" />
219
+ {/if}
220
+ {#if getKbds(item).length > 0}
221
+ <span class="flex items-center gap-0.5">
222
+ {#each getKbds(item) as key}
223
+ <Kbd value={typeof key === 'string' ? key : key.value} size="sm" />
224
+ {/each}
225
+ </span>
226
+ {/if}
227
+ </span>
228
+ {/if}
229
+ </svelte:element>
230
+ {/snippet}
231
+
232
+ {#if isCollapsed}
233
+ <Tooltip text={item.label} side={sidebarPosition === 'right' ? 'left' : 'right'}>
234
+ {@render linkContent()}
235
+ </Tooltip>
236
+ {:else}
237
+ {@render linkContent()}
238
+ {/if}
196
239
  {/if}
197
240
  </li>
198
241
  {/snippet}
@@ -30,6 +30,13 @@ export declare const navigationMenuVariants: import("tailwind-variants").TVRetur
30
30
  };
31
31
  false: {};
32
32
  };
33
+ collapsed: {
34
+ true: {
35
+ item: string;
36
+ icon: string;
37
+ };
38
+ false: {};
39
+ };
33
40
  }, {
34
41
  base: string;
35
42
  group: string;
@@ -69,6 +76,13 @@ export declare const navigationMenuVariants: import("tailwind-variants").TVRetur
69
76
  };
70
77
  false: {};
71
78
  };
79
+ collapsed: {
80
+ true: {
81
+ item: string;
82
+ icon: string;
83
+ };
84
+ false: {};
85
+ };
72
86
  }, {
73
87
  base: string;
74
88
  group: string;
@@ -108,6 +122,13 @@ export declare const navigationMenuVariants: import("tailwind-variants").TVRetur
108
122
  };
109
123
  false: {};
110
124
  };
125
+ collapsed: {
126
+ true: {
127
+ item: string;
128
+ icon: string;
129
+ };
130
+ false: {};
131
+ };
111
132
  }, {
112
133
  base: string;
113
134
  group: string;
@@ -54,6 +54,13 @@ export const navigationMenuVariants = tv({
54
54
  accordionTrigger: 'bg-primary-container text-on-primary-container'
55
55
  },
56
56
  false: {}
57
+ },
58
+ collapsed: {
59
+ true: {
60
+ item: 'w-10 h-10 justify-center p-0 aspect-square shrink-0',
61
+ icon: 'text-[1.25rem] m-0'
62
+ },
63
+ false: {}
57
64
  }
58
65
  },
59
66
  defaultVariants: {
@@ -6,25 +6,25 @@ let styles = $derived(sidebarVariants({
6
6
  collapsed,
7
7
  position
8
8
  }));
9
- // Provide context to children (like Menu) so they know if sidebar is collapsed
10
- // Useful if we want the Menu to hide labels when collapsed
9
+ // Provide context to children (like Menu) so they know if sidebar is collapsed or right-aligned
11
10
  setContext("sidebar-collapsed", () => collapsed);
11
+ setContext("sidebar-position", () => position);
12
12
  </script>
13
13
 
14
14
  <aside class={twMerge(styles.base(), className)} {...restProps}>
15
15
  {#if header}
16
16
  <div class={styles.header()}>
17
- {@render header()}
17
+ {@render header({ collapsed })}
18
18
  </div>
19
19
  {/if}
20
20
 
21
21
  <div class={styles.content()}>
22
- {@render children?.()}
22
+ {@render children?.({ collapsed })}
23
23
  </div>
24
24
 
25
25
  {#if footer}
26
26
  <div class={styles.footer()}>
27
- {@render footer()}
27
+ {@render footer({ collapsed })}
28
28
  </div>
29
29
  {/if}
30
30
  </aside>
@@ -1,7 +1,7 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  import type { HTMLAttributes } from 'svelte/elements';
3
3
  import type { SidebarVariantProps } from './sidebar.variants.js';
4
- export interface SidebarProps extends HTMLAttributes<HTMLElement> {
4
+ export interface SidebarProps extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
5
5
  /**
6
6
  * Whether the sidebar is collapsed (icons only).
7
7
  * @default false
@@ -19,13 +19,19 @@ export interface SidebarProps extends HTMLAttributes<HTMLElement> {
19
19
  /**
20
20
  * Snippet for the top header section (e.g. Logo).
21
21
  */
22
- header?: Snippet;
22
+ header?: Snippet<[{
23
+ collapsed: boolean;
24
+ }]>;
23
25
  /**
24
26
  * Snippet for the main content (e.g. Navigation Menu).
25
27
  */
26
- children?: Snippet;
28
+ children?: Snippet<[{
29
+ collapsed: boolean;
30
+ }]>;
27
31
  /**
28
32
  * Snippet for the bottom footer section (e.g. User Profile).
29
33
  */
30
- footer?: Snippet;
34
+ footer?: Snippet<[{
35
+ collapsed: boolean;
36
+ }]>;
31
37
  }
@@ -11,9 +11,15 @@ export declare const sidebarVariants: import("tailwind-variants").TVReturnType<{
11
11
  collapsed: {
12
12
  true: {
13
13
  base: string;
14
+ header: string;
15
+ content: string;
16
+ footer: string;
14
17
  };
15
18
  false: {
16
19
  base: string;
20
+ header: string;
21
+ content: string;
22
+ footer: string;
17
23
  };
18
24
  };
19
25
  }, {
@@ -33,9 +39,15 @@ export declare const sidebarVariants: import("tailwind-variants").TVReturnType<{
33
39
  collapsed: {
34
40
  true: {
35
41
  base: string;
42
+ header: string;
43
+ content: string;
44
+ footer: string;
36
45
  };
37
46
  false: {
38
47
  base: string;
48
+ header: string;
49
+ content: string;
50
+ footer: string;
39
51
  };
40
52
  };
41
53
  }, {
@@ -55,9 +67,15 @@ export declare const sidebarVariants: import("tailwind-variants").TVReturnType<{
55
67
  collapsed: {
56
68
  true: {
57
69
  base: string;
70
+ header: string;
71
+ content: string;
72
+ footer: string;
58
73
  };
59
74
  false: {
60
75
  base: string;
76
+ header: string;
77
+ content: string;
78
+ footer: string;
61
79
  };
62
80
  };
63
81
  }, {
@@ -1,10 +1,10 @@
1
1
  import { tv } from 'tailwind-variants';
2
2
  export const sidebarVariants = tv({
3
3
  slots: {
4
- base: 'flex flex-col h-full bg-surface-50 dark:bg-surface-900 border-outline-variant text-surface-900 dark:text-surface-50 transition-all duration-300',
5
- header: 'flex items-center px-4 h-16 shrink-0 border-b border-outline-variant',
6
- content: 'flex-1 overflow-y-auto px-3 py-4',
7
- footer: 'p-4 mt-auto border-t border-outline-variant shrink-0'
4
+ base: 'flex flex-col h-full bg-surface-container-low border-outline-variant/60 text-on-surface transition-[width] duration-300 ease-in-out',
5
+ header: 'flex items-center shrink-0 border-b border-outline-variant/60 transition-[padding] duration-300 h-16',
6
+ content: 'flex-1 overflow-y-auto py-4 transition-[padding] duration-300',
7
+ footer: 'mt-auto border-t border-outline-variant/60 shrink-0 transition-[padding] duration-300'
8
8
  },
9
9
  variants: {
10
10
  position: {
@@ -12,8 +12,18 @@ export const sidebarVariants = tv({
12
12
  right: { base: 'border-l' }
13
13
  },
14
14
  collapsed: {
15
- true: { base: 'w-16' },
16
- false: { base: 'w-64' }
15
+ true: {
16
+ base: 'w-[64px]',
17
+ header: 'px-3 justify-center',
18
+ content: 'px-3 flex flex-col items-center',
19
+ footer: 'p-3 flex flex-col items-center justify-center gap-4'
20
+ },
21
+ false: {
22
+ base: 'w-64',
23
+ header: 'px-4',
24
+ content: 'px-3',
25
+ footer: 'p-4'
26
+ }
17
27
  }
18
28
  },
19
29
  defaultVariants: {
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "version": 1,
3
3
  "packageName": "svelora",
4
- "packageVersion": "3.0.8",
5
- "generatedAt": "2026-06-26T04:45:42.017Z",
4
+ "packageVersion": "3.0.10",
5
+ "generatedAt": "2026-06-26T11:53:53.695Z",
6
6
  "slugs": {
7
7
  "components": [
8
8
  "button",
@@ -162,7 +162,7 @@
162
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",
163
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",
164
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",
165
- "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",
166
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",
167
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",
168
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",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelora",
3
- "version": "3.0.8",
3
+ "version": "3.0.10",
4
4
  "description": "Modern primitive-based UI component library for Svelte 5",
5
5
  "packageManager": "bun@1.3.14",
6
6
  "author": "asphum",