chore: rewrite existing shared/ui stories using snippet template pattern

This commit is contained in:
Ilia Mashkov
2026-02-22 11:25:02 +03:00
parent 30bbfa7e11
commit 0c8b8e989f
15 changed files with 403 additions and 304 deletions

View File

@@ -65,9 +65,13 @@ const selectedFilter = createFilter({
</script> </script>
<Story name="Default"> <Story name="Default">
<CheckboxFilter filter={defaultFilter} displayedLabel="Zoo" /> {#snippet template(args)}
<CheckboxFilter filter={defaultFilter} displayedLabel="Zoo" {...args} />
{/snippet}
</Story> </Story>
<Story name="Selected"> <Story name="Selected">
<CheckboxFilter filter={selectedFilter} displayedLabel="Shopping list" /> {#snippet template(args)}
<CheckboxFilter filter={selectedFilter} displayedLabel="Shopping list" {...args} />
{/snippet}
</Story> </Story>

View File

@@ -51,7 +51,9 @@ const customLabelsControl = createTypographyControl({ value: 50, min: 0, max: 10
control: defaultControl, control: defaultControl,
}} }}
> >
<ComboControl control={defaultControl} /> {#snippet template(args)}
<ComboControl control={defaultControl} {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -60,7 +62,9 @@ const customLabelsControl = createTypographyControl({ value: 50, min: 0, max: 10
control: atMinimumControl, control: atMinimumControl,
}} }}
> >
<ComboControl control={atMinimumControl} /> {#snippet template(args)}
<ComboControl control={atMinimumControl} {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -69,7 +73,9 @@ const customLabelsControl = createTypographyControl({ value: 50, min: 0, max: 10
control: atMaximumControl, control: atMaximumControl,
}} }}
> >
<ComboControl control={atMaximumControl} /> {#snippet template(args)}
<ComboControl control={atMaximumControl} {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -78,7 +84,9 @@ const customLabelsControl = createTypographyControl({ value: 50, min: 0, max: 10
control: withFloatControl, control: withFloatControl,
}} }}
> >
<ComboControl control={withFloatControl} /> {#snippet template(args)}
<ComboControl control={withFloatControl} {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -90,10 +98,13 @@ const customLabelsControl = createTypographyControl({ value: 50, min: 0, max: 10
controlLabel: 'Open font size controls', controlLabel: 'Open font size controls',
}} }}
> >
{#snippet template(args)}
<ComboControl <ComboControl
control={customLabelsControl} control={customLabelsControl}
decreaseLabel="Decrease font size" decreaseLabel="Decrease font size"
increaseLabel="Increase font size" increaseLabel="Increase font size"
controlLabel="Open font size controls" controlLabel="Open font size controls"
{...args}
/> />
{/snippet}
</Story> </Story>

View File

@@ -52,7 +52,9 @@ const largeRangeControl = createTypographyControl({ min: 0, max: 1000, step: 10,
label: 'Size', label: 'Size',
}} }}
> >
<ComboControlV2 control={horizontalControl} orientation="horizontal" label="Size" /> {#snippet template(args)}
<ComboControlV2 control={horizontalControl} orientation="horizontal" label="Size" {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -63,7 +65,9 @@ const largeRangeControl = createTypographyControl({ min: 0, max: 1000, step: 10,
label: 'Size', label: 'Size',
}} }}
> >
<ComboControlV2 control={verticalControl} orientation="vertical" class="h-48" label="Size" /> {#snippet template(args)}
<ComboControlV2 control={verticalControl} orientation="vertical" class="h-48" label="Size" {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -74,7 +78,9 @@ const largeRangeControl = createTypographyControl({ min: 0, max: 1000, step: 10,
label: 'Opacity', label: 'Opacity',
}} }}
> >
<ComboControlV2 control={floatControl} orientation="vertical" class="h-48" label="Opacity" /> {#snippet template(args)}
<ComboControlV2 control={floatControl} orientation="vertical" class="h-48" label="Opacity" {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -85,7 +91,9 @@ const largeRangeControl = createTypographyControl({ min: 0, max: 1000, step: 10,
label: 'Size', label: 'Size',
}} }}
> >
<ComboControlV2 control={atMinControl} orientation="horizontal" label="Size" /> {#snippet template(args)}
<ComboControlV2 control={atMinControl} orientation="horizontal" label="Size" {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -96,7 +104,9 @@ const largeRangeControl = createTypographyControl({ min: 0, max: 1000, step: 10,
label: 'Size', label: 'Size',
}} }}
> >
<ComboControlV2 control={atMaxControl} orientation="horizontal" label="Size" /> {#snippet template(args)}
<ComboControlV2 control={atMaxControl} orientation="horizontal" label="Size" {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -107,5 +117,7 @@ const largeRangeControl = createTypographyControl({ min: 0, max: 1000, step: 10,
label: 'Scale', label: 'Scale',
}} }}
> >
<ComboControlV2 control={largeRangeControl} orientation="horizontal" label="Scale" /> {#snippet template(args)}
<ComboControlV2 control={largeRangeControl} orientation="horizontal" label="Scale" {...args} />
{/snippet}
</Story> </Story>

View File

@@ -55,7 +55,9 @@ let longValue = $state(
letterSpacing: 0, letterSpacing: 0,
}} }}
> >
<ContentEditable bind:text={value} /> {#snippet template(args)}
<ContentEditable bind:text={value} {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -67,7 +69,9 @@ let longValue = $state(
letterSpacing: 0, letterSpacing: 0,
}} }}
> >
<ContentEditable bind:text={smallValue} /> {#snippet template(args)}
<ContentEditable bind:text={smallValue} {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -79,7 +83,9 @@ let longValue = $state(
letterSpacing: 0, letterSpacing: 0,
}} }}
> >
<ContentEditable bind:text={largeValue} /> {#snippet template(args)}
<ContentEditable bind:text={largeValue} {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -91,7 +97,9 @@ let longValue = $state(
letterSpacing: 0.3, letterSpacing: 0.3,
}} }}
> >
<ContentEditable bind:text={spacedValue} /> {#snippet template(args)}
<ContentEditable bind:text={spacedValue} {...args} />
{/snippet}
</Story> </Story>
<Story <Story
@@ -103,5 +111,7 @@ let longValue = $state(
letterSpacing: 0, letterSpacing: 0,
}} }}
> >
<ContentEditable bind:text={longValue} /> {#snippet template(args)}
<ContentEditable bind:text={longValue} {...args} />
{/snippet}
</Story> </Story>

View File

@@ -59,7 +59,7 @@ const { Story } = defineMeta({
</script> </script>
{/* @ts-ignore */ null} {/* @ts-ignore */ null}
<Story name="With hidden content"> <Story name="With hidden content">
{#snippet children(args)} {#snippet template(args)}
<div class="p-12 bg-slate-100 min-h-[300px] flex justify-center items-start"> <div class="p-12 bg-slate-100 min-h-[300px] flex justify-center items-start">
<ExpandableWrapper <ExpandableWrapper
{...args} {...args}
@@ -71,7 +71,7 @@ const { Story } = defineMeta({
{/* @ts-ignore */ null} {/* @ts-ignore */ null}
<Story name="Disabled" args={{ disabled: true }}> <Story name="Disabled" args={{ disabled: true }}>
{#snippet children(args)} {#snippet template(args)}
<div class="p-12 bg-slate-100 min-h-[300px] flex justify-center items-start"> <div class="p-12 bg-slate-100 min-h-[300px] flex justify-center items-start">
<ExpandableWrapper <ExpandableWrapper
{...args} {...args}
@@ -84,7 +84,7 @@ const { Story } = defineMeta({
{/* @ts-ignore */ null} {/* @ts-ignore */ null}
<Story name="With badge" args={{ badge: badgeSnippet }}> <Story name="With badge" args={{ badge: badgeSnippet }}>
{#snippet children(args)} {#snippet template(args)}
<div class="p-12 bg-slate-100 min-h-[300px] flex justify-center items-start"> <div class="p-12 bg-slate-100 min-h-[300px] flex justify-center items-start">
<ExpandableWrapper <ExpandableWrapper
{...args} {...args}

View File

@@ -17,15 +17,19 @@ const { Story } = defineMeta({
</script> </script>
<Story name="Default"> <Story name="Default">
<Footnote> {#snippet template(args)}
<Footnote {...args}>
Footnote Footnote
</Footnote> </Footnote>
{/snippet}
</Story> </Story>
<Story name="With custom render"> <Story name="With custom render">
<Footnote> {#snippet template(args)}
<Footnote {...args}>
{#snippet render({ class: className })} {#snippet render({ class: className })}
<span class={className}>Footnote</span> <span class={className}>Footnote</span>
{/snippet} {/snippet}
</Footnote> </Footnote>
{/snippet}
</Story> </Story>

View File

@@ -77,11 +77,13 @@ import XIcon from '@lucide/svelte/icons/x';
icon: chevronRightIcon, icon: chevronRightIcon,
}} }}
> >
<IconButton onclick={() => console.log('Default clicked')}> {#snippet template(args)}
<IconButton onclick={() => console.log('Default clicked')} {...args}>
{#snippet icon({ className })} {#snippet icon({ className })}
<ChevronRight class={className} /> <ChevronRight class={className} />
{/snippet} {/snippet}
</IconButton> </IconButton>
{/snippet}
</Story> </Story>
<Story <Story
@@ -91,11 +93,13 @@ import XIcon from '@lucide/svelte/icons/x';
disabled: true, disabled: true,
}} }}
> >
{#snippet template(args)}
<div class="flex flex-col gap-4 items-center"> <div class="flex flex-col gap-4 items-center">
<IconButton disabled> <IconButton disabled {...args}>
{#snippet icon({ className })} {#snippet icon({ className })}
<ChevronRight class={className} /> <ChevronRight class={className} />
{/snippet} {/snippet}
</IconButton> </IconButton>
</div> </div>
{/snippet}
</Story> </Story>

View File

@@ -50,33 +50,47 @@ const placeholder = 'Enter text';
<!-- Default Story --> <!-- Default Story -->
<Story name="Default" args={{ placeholder }}> <Story name="Default" args={{ placeholder }}>
<Input bind:value={valueDefault} {placeholder} /> {#snippet template(args)}
<Input bind:value={valueDefault} {placeholder} {...args} />
{/snippet}
</Story> </Story>
<!-- Size Variants --> <!-- Size Variants -->
<Story name="Small" args={{ placeholder }}> <Story name="Small" args={{ placeholder }}>
<Input bind:value={valueSm} {placeholder} size="sm" /> {#snippet template(args)}
<Input bind:value={valueSm} {placeholder} size="sm" {...args} />
{/snippet}
</Story> </Story>
<Story name="Medium" args={{ placeholder }}> <Story name="Medium" args={{ placeholder }}>
<Input bind:value={valueMd} {placeholder} size="md" /> {#snippet template(args)}
<Input bind:value={valueMd} {placeholder} size="md" {...args} />
{/snippet}
</Story> </Story>
<Story name="Large" args={{ placeholder }}> <Story name="Large" args={{ placeholder }}>
<Input bind:value={valueLg} {placeholder} size="lg" /> {#snippet template(args)}
<Input bind:value={valueLg} {placeholder} size="lg" {...args} />
{/snippet}
</Story> </Story>
<!-- Ghost Variant with Sizes --> <!-- Ghost Variant with Sizes -->
<Story name="Ghost Small" args={{ placeholder }}> <Story name="Ghost Small" args={{ placeholder }}>
<Input bind:value={valueGhostSm} {placeholder} variant="ghost" size="sm" /> {#snippet template(args)}
<Input bind:value={valueGhostSm} {placeholder} variant="ghost" size="sm" {...args} />
{/snippet}
</Story> </Story>
<Story name="Ghost Medium" args={{ placeholder }}> <Story name="Ghost Medium" args={{ placeholder }}>
<Input bind:value={valueGhostMd} {placeholder} variant="ghost" size="md" /> {#snippet template(args)}
<Input bind:value={valueGhostMd} {placeholder} variant="ghost" size="md" {...args} />
{/snippet}
</Story> </Story>
<Story name="Ghost Large" args={{ placeholder }}> <Story name="Ghost Large" args={{ placeholder }}>
<Input bind:value={valueGhostLg} {placeholder} variant="ghost" size="lg" /> {#snippet template(args)}
<Input bind:value={valueGhostLg} {placeholder} variant="ghost" size="lg" {...args} />
{/snippet}
</Story> </Story>
<!-- Size Comparison --> <!-- Size Comparison -->

View File

@@ -29,5 +29,7 @@ const { Story } = defineMeta({
</script> </script>
<Story name="Default"> <Story name="Default">
<Loader /> {#snippet template(args)}
<Loader {...args} />
{/snippet}
</Story> </Story>

View File

@@ -17,5 +17,7 @@ const { Story } = defineMeta({
</script> </script>
<Story name="Default"> <Story name="Default">
<Logo /> {#snippet template(args)}
<Logo {...args} />
{/snippet}
</Story> </Story>

View File

@@ -39,5 +39,7 @@ let defaultSearchValue = $state('');
placeholder: 'Type here...', placeholder: 'Type here...',
}} }}
> >
<SearchBar bind:value={defaultSearchValue} placeholder="Type here..." /> {#snippet template(args)}
<SearchBar bind:value={defaultSearchValue} placeholder="Type here..." {...args} />
{/snippet}
</Story> </Story>

View File

@@ -192,21 +192,23 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
content: welcomeContent, content: welcomeContent,
}} }}
> >
{#snippet template(args)}
<div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto"> <div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto">
<Section index={1}> <Section index={1} {...args}>
{#snippet title({ className })} {#snippet title({ className })}
<h2 class={className}>Welcome</h2> <h2 class={className}>Welcome</h2>
{/snippet} {/snippet}
{#snippet content({ className })} {#snippet content({ className })}
<div class={cn(className, 'min-w-128')}> <div class={cn(className, 'min-w-128')}>
<p class="text-lg text-text-muted"> <p class="text-lg text-text-muted">
This is the default section layout with a title and content area. The section uses a 2-column This is the default section layout with a title and content area. The section uses a
grid layout with the title on the left and content on the right. 2-column grid layout with the title on the left and content on the right.
</p> </p>
</div> </div>
{/snippet} {/snippet}
</Section> </Section>
</div> </div>
{/snippet}
</Story> </Story>
<Story <Story
@@ -216,6 +218,7 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
content: stickyContent, content: stickyContent,
}} }}
> >
{#snippet template(args)}
<div class="h-[200vh]"> <div class="h-[200vh]">
<div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto"> <div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto">
<Section <Section
@@ -223,6 +226,7 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
index={1} index={1}
stickyTitle={true} stickyTitle={true}
stickyOffset="20px" stickyOffset="20px"
{...args}
> >
{#snippet title({ className })} {#snippet title({ className })}
<h2 class={className}>Sticky Title</h2> <h2 class={className}>Sticky Title</h2>
@@ -230,8 +234,8 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
{#snippet content({ className })} {#snippet content({ className })}
<div class={cn(className, 'min-w-128')}> <div class={cn(className, 'min-w-128')}>
<p class="text-lg text-text-muted mb-4"> <p class="text-lg text-text-muted mb-4">
This section has a sticky title that stays fixed while you scroll through the content. Try This section has a sticky title that stays fixed while you scroll through the content.
scrolling down to see the effect. Try scrolling down to see the effect.
</p> </p>
<div class="space-y-4"> <div class="space-y-4">
<p class="text-text-muted"> <p class="text-text-muted">
@@ -239,20 +243,20 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
incididunt ut labore et dolore magna aliqua. incididunt ut labore et dolore magna aliqua.
</p> </p>
<p class="text-text-muted"> <p class="text-text-muted">
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
commodo consequat. ex ea commodo consequat.
</p> </p>
<p class="text-text-muted"> <p class="text-text-muted">
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
nulla pariatur. fugiat nulla pariatur.
</p> </p>
<p class="text-text-muted"> <p class="text-text-muted">
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollim anim id est laborum. mollim anim id est laborum.
</p> </p>
<p class="text-text-muted"> <p class="text-text-muted">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
laudantium. doloremque laudantium.
</p> </p>
</div> </div>
</div> </div>
@@ -260,6 +264,7 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
</Section> </Section>
</div> </div>
</div> </div>
{/snippet}
</Story> </Story>
<Story <Story
@@ -271,8 +276,9 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
content: searchFontsContent, content: searchFontsContent,
}} }}
> >
{#snippet template(args)}
<div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto"> <div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto">
<Section index={1}> <Section index={1} {...args}>
{#snippet title({ className })} {#snippet title({ className })}
<h2 class={className}>Search Fonts</h2> <h2 class={className}>Search Fonts</h2>
{/snippet} {/snippet}
@@ -285,21 +291,24 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
{#snippet content({ className })} {#snippet content({ className })}
<div class={cn(className, 'min-w-128')}> <div class={cn(className, 'min-w-128')}>
<p class="text-lg text-text-muted"> <p class="text-lg text-text-muted">
Use the search bar to find fonts by name, or use the filters to browse by category, subset, or Use the search bar to find fonts by name, or use the filters to browse by category, subset,
provider. or provider.
</p> </p>
</div> </div>
{/snippet} {/snippet}
</Section> </Section>
</div> </div>
{/snippet}
</Story> </Story>
<Story name="Multiple Sections" tags={['!autodocs']}> <Story name="Multiple Sections" tags={['!autodocs']}>
{#snippet template(args)}
<div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto"> <div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto">
<Section <Section
id="section-1" id="section-1"
index={1} index={1}
stickyTitle={true} stickyTitle={true}
{...args}
> >
{#snippet title({ className })} {#snippet title({ className })}
<h2 class={className}>Typography</h2> <h2 class={className}>Typography</h2>
@@ -324,6 +333,7 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
id="section-2" id="section-2"
index={2} index={2}
stickyTitle={true} stickyTitle={true}
{...args}
> >
{#snippet title({ className })} {#snippet title({ className })}
<h2 class={className}>Font Search</h2> <h2 class={className}>Font Search</h2>
@@ -337,8 +347,8 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
{#snippet content({ className })} {#snippet content({ className })}
<div class={cn(className, 'min-w-128')}> <div class={cn(className, 'min-w-128')}>
<p class="text-lg text-text-muted"> <p class="text-lg text-text-muted">
Search through our collection of fonts from Google Fonts and Fontshare. Use filters to narrow Search through our collection of fonts from Google Fonts and Fontshare. Use filters to
down your selection. narrow down your selection.
</p> </p>
</div> </div>
{/snippet} {/snippet}
@@ -348,6 +358,7 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
id="section-3" id="section-3"
index={3} index={3}
stickyTitle={true} stickyTitle={true}
{...args}
> >
{#snippet title({ className })} {#snippet title({ className })}
<h2 class={className}>Sample List</h2> <h2 class={className}>Sample List</h2>
@@ -368,6 +379,7 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
{/snippet} {/snippet}
</Section> </Section>
</div> </div>
{/snippet}
</Story> </Story>
<Story <Story
@@ -377,11 +389,13 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
content: longContent, content: longContent,
}} }}
> >
{#snippet template(args)}
<div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto"> <div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto">
<Section <Section
index={1} index={1}
stickyTitle={true} stickyTitle={true}
stickyOffset="0px" stickyOffset="0px"
{...args}
> >
{#snippet title({ className })} {#snippet title({ className })}
<h2 class={className}>Long Content</h2> <h2 class={className}>Long Content</h2>
@@ -390,22 +404,23 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
<div class={cn(className, 'min-w-128')}> <div class={cn(className, 'min-w-128')}>
<div class="space-y-6"> <div class="space-y-6">
<p class="text-lg text-text-muted"> <p class="text-lg text-text-muted">
This section demonstrates how the sticky title behaves with longer content. As you scroll This section demonstrates how the sticky title behaves with longer content. As you
through this content, the title remains visible at the top of the viewport. scroll through this content, the title remains visible at the top of the viewport.
</p> </p>
<div class="h-64 bg-background-40 rounded-lg flex items-center justify-center"> <div class="h-64 bg-background-40 rounded-lg flex items-center justify-center">
<span class="text-text-muted">Content block 1</span> <span class="text-text-muted">Content block 1</span>
</div> </div>
<p class="text-text-muted"> <p class="text-text-muted">
The sticky position is achieved using CSS position: sticky with a configurable top offset. The sticky position is achieved using CSS position: sticky with a configurable top
This is useful for long sections where you want to maintain context while scrolling. offset. This is useful for long sections where you want to maintain context while
scrolling.
</p> </p>
<div class="h-64 bg-background-40 rounded-lg flex items-center justify-center"> <div class="h-64 bg-background-40 rounded-lg flex items-center justify-center">
<span class="text-text-muted">Content block 2</span> <span class="text-text-muted">Content block 2</span>
</div> </div>
<p class="text-text-muted"> <p class="text-text-muted">
The Intersection Observer API is used to detect when the section title scrolls out of view, The Intersection Observer API is used to detect when the section title scrolls out of
triggering the optional onTitleStatusChange callback. view, triggering the optional onTitleStatusChange callback.
</p> </p>
<div class="h-64 bg-background-40 rounded-lg flex items-center justify-center"> <div class="h-64 bg-background-40 rounded-lg flex items-center justify-center">
<span class="text-text-muted">Content block 3</span> <span class="text-text-muted">Content block 3</span>
@@ -415,6 +430,7 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
{/snippet} {/snippet}
</Section> </Section>
</div> </div>
{/snippet}
</Story> </Story>
<Story <Story
@@ -424,8 +440,9 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
content: minimalContent, content: minimalContent,
}} }}
> >
{#snippet template(args)}
<div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto"> <div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto">
<Section> <Section {...args}>
{#snippet title({ className })} {#snippet title({ className })}
<h2 class={className}>Minimal Section</h2> <h2 class={className}>Minimal Section</h2>
{/snippet} {/snippet}
@@ -438,6 +455,7 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
{/snippet} {/snippet}
</Section> </Section>
</div> </div>
{/snippet}
</Story> </Story>
<Story <Story
@@ -448,8 +466,9 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
content: customContent, content: customContent,
}} }}
> >
{#snippet template(args)}
<div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto"> <div class="grid grid-cols-1 lg:grid-cols-[auto_1fr] gap-x-6 sm:gap-x-8 md:gap-x-10 lg:gap-x-12 p-8 max-w-6xl mx-auto">
<Section index={42}> <Section index={42} {...args}>
{#snippet title({ className })} {#snippet title({ className })}
<h2 class={className}>Custom Content</h2> <h2 class={className}>Custom Content</h2>
{/snippet} {/snippet}
@@ -472,4 +491,5 @@ import SettingsIcon from '@lucide/svelte/icons/settings';
{/snippet} {/snippet}
</Section> </Section>
</div> </div>
{/snippet}
</Story> </Story>

View File

@@ -29,13 +29,15 @@ const { Story } = defineMeta({
animate: true, animate: true,
}} }}
> >
{#snippet template(args)}
<div class="flex flex-col gap-4 p-4 w-full"> <div class="flex flex-col gap-4 p-4 w-full">
<div class="flex flex-col gap-2 p-4 border rounded-xl border-border-subtle bg-background-40"> <div class="flex flex-col gap-2 p-4 border rounded-xl border-border-subtle bg-background-40">
<div class="flex items-center justify-between mb-4"> <div class="flex items-center justify-between mb-4">
<Skeleton class="h-8 w-1/3" /> <Skeleton class="h-8 w-1/3" {...args} />
<Skeleton class="h-8 w-8 rounded-full" /> <Skeleton class="h-8 w-8 rounded-full" {...args} />
</div> </div>
<Skeleton class="h-32 w-full" /> <Skeleton class="h-32 w-full" {...args} />
</div> </div>
</div> </div>
{/snippet}
</Story> </Story>

View File

@@ -44,13 +44,19 @@ let value = $state(50);
</script> </script>
<Story name="Horizontal" args={{ orientation: 'horizontal', min: 0, max: 100, step: 1, value }}> <Story name="Horizontal" args={{ orientation: 'horizontal', min: 0, max: 100, step: 1, value }}>
<Slider bind:value /> {#snippet template(args)}
<Slider bind:value {...args} />
{/snippet}
</Story> </Story>
<Story name="Vertical" args={{ orientation: 'vertical', min: 0, max: 100, step: 1, value }}> <Story name="Vertical" args={{ orientation: 'vertical', min: 0, max: 100, step: 1, value }}>
<Slider bind:value /> {#snippet template(args)}
<Slider bind:value {...args} />
{/snippet}
</Story> </Story>
<Story name="With Label" args={{ orientation: 'horizontal', min: 0, max: 100, step: 1, value, label: 'SIZE' }}> <Story name="With Label" args={{ orientation: 'horizontal', min: 0, max: 100, step: 1, value, label: 'SIZE' }}>
<Slider bind:value /> {#snippet template(args)}
<Slider bind:value {...args} />
{/snippet}
</Story> </Story>

View File

@@ -46,29 +46,35 @@ const emptyDataSet: string[] = [];
</script> </script>
<Story name="Small Dataset"> <Story name="Small Dataset">
{#snippet template(args)}
<div class="h-[400px]"> <div class="h-[400px]">
<VirtualList items={smallDataSet} itemHeight={40}> <VirtualList items={smallDataSet} itemHeight={40} {...args}>
{#snippet children({ item })} {#snippet children({ item })}
<div class="p-2 m-0.5 rounded-sm hover:bg-accent">{item}</div> <div class="p-2 m-0.5 rounded-sm hover:bg-accent">{item}</div>
{/snippet} {/snippet}
</VirtualList> </VirtualList>
</div> </div>
{/snippet}
</Story> </Story>
<Story name="Medium Dataset (200 items)"> <Story name="Medium Dataset (200 items)">
{#snippet template(args)}
<div class="h-[400px]"> <div class="h-[400px]">
<VirtualList items={mediumDataSet} itemHeight={40}> <VirtualList items={mediumDataSet} itemHeight={40} {...args}>
{#snippet children({ item })} {#snippet children({ item })}
<div class="p-2 m-0.5 rounded-sm hover:bg-accent">{item}</div> <div class="p-2 m-0.5 rounded-sm hover:bg-accent">{item}</div>
{/snippet} {/snippet}
</VirtualList> </VirtualList>
</div> </div>
{/snippet}
</Story> </Story>
<Story name="Empty Dataset"> <Story name="Empty Dataset">
<VirtualList items={emptyDataSet} itemHeight={40}> {#snippet template(args)}
<VirtualList items={emptyDataSet} itemHeight={40} {...args}>
{#snippet children({ item })} {#snippet children({ item })}
<div class="p-2 m-0.5 rounded-sm hover:bg-accent">{item}</div> <div class="p-2 m-0.5 rounded-sm hover:bg-accent">{item}</div>
{/snippet} {/snippet}
</VirtualList> </VirtualList>
{/snippet}
</Story> </Story>