fix: stories errors
All checks were successful
Workflow / build (pull_request) Successful in 3m22s
Workflow / publish (pull_request) Has been skipped

This commit is contained in:
Ilia Mashkov
2026-03-02 22:45:29 +03:00
parent 87bba388dc
commit 6f65aa207e
2 changed files with 121 additions and 433 deletions

View File

@@ -56,7 +56,7 @@ let longValue = $state(
}} }}
> >
{#snippet template(args)} {#snippet template(args)}
<ContentEditable bind:text={value} {...args} /> <ContentEditable {...args} />
{/snippet} {/snippet}
</Story> </Story>
@@ -70,7 +70,7 @@ let longValue = $state(
}} }}
> >
{#snippet template(args)} {#snippet template(args)}
<ContentEditable bind:text={smallValue} {...args} /> <ContentEditable {...args} />
{/snippet} {/snippet}
</Story> </Story>
@@ -84,7 +84,7 @@ let longValue = $state(
}} }}
> >
{#snippet template(args)} {#snippet template(args)}
<ContentEditable bind:text={largeValue} {...args} /> <ContentEditable {...args} />
{/snippet} {/snippet}
</Story> </Story>
@@ -98,7 +98,7 @@ let longValue = $state(
}} }}
> >
{#snippet template(args)} {#snippet template(args)}
<ContentEditable bind:text={spacedValue} {...args} /> <ContentEditable {...args} />
{/snippet} {/snippet}
</Story> </Story>
@@ -112,6 +112,6 @@ let longValue = $state(
}} }}
> >
{#snippet template(args)} {#snippet template(args)}
<ContentEditable bind:text={longValue} {...args} /> <ContentEditable {...args} />
{/snippet} {/snippet}
</Story> </Story>

View File

@@ -1,5 +1,4 @@
<script module> <script module>
import { cn } from '$shared/shadcn/utils/shadcn-utils';
import { defineMeta } from '@storybook/addon-svelte-csf'; import { defineMeta } from '@storybook/addon-svelte-csf';
import Section from './Section.svelte'; import Section from './Section.svelte';
@@ -11,7 +10,7 @@ const { Story } = defineMeta({
docs: { docs: {
description: { description: {
component: component:
'Page layout component with optional sticky title feature. Provides a container for page widgets with title, icon, description snippets. The title can remain fixed while scrolling through content.', 'Page layout component that provides a container for page widgets with title, optional header, description, and content snippets.',
}, },
story: { inline: false }, story: { inline: false },
}, },
@@ -22,474 +21,163 @@ const { Story } = defineMeta({
control: 'text', control: 'text',
description: 'ID of the section', description: 'ID of the section',
}, },
title: {
control: 'text',
description: 'Section title text',
},
index: { index: {
control: 'number', control: 'number',
description: 'Index of the section (used for default description)', description: 'Index of the section',
}, },
stickyTitle: { headerTitle: {
control: 'boolean',
description: 'When true, title stays fixed while scrolling through content',
},
stickyOffset: {
control: 'text', control: 'text',
description: 'Top offset for sticky title (e.g. "60px")', description: 'Header title text',
},
headerSubtitle: {
control: 'text',
description: 'Header subtitle text',
}, },
class: { class: {
control: 'text', control: 'text',
description: 'Additional CSS classes', description: 'Additional CSS classes',
}, },
onTitleStatusChange: {
action: 'titleStatusChanged',
description: 'Callback when title visibility status changes',
},
}, },
}); });
</script> </script>
<script lang="ts"> <Story name="Default">
import ListIcon from '@lucide/svelte/icons/list'; {#snippet template()}
import SearchIcon from '@lucide/svelte/icons/search'; <Section title="Welcome" index={1}>
import SettingsIcon from '@lucide/svelte/icons/settings'; {#snippet content()}
</script> <p class="text-lg text-text-muted">
This is the default section layout with a title and content area. The section provides a container
{#snippet searchIcon({ className }: { className?: string })} for page widgets.
<SearchIcon class={className} /> </p>
{/snippet} {/snippet}
</Section>
{#snippet welcomeTitle({ className }: { className?: string })}
<h2 class={className}>Welcome</h2>
{/snippet}
{#snippet welcomeContent({ className }: { className?: string })}
<div class={cn(className, 'min-w-128')}>
<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 grid layout
with the title on the left and content on the right.
</p>
</div>
{/snippet}
{#snippet stickyTitle({ className }: { className?: string })}
<h2 class={className}>Sticky Title</h2>
{/snippet}
{#snippet stickyContent({ className }: { className?: string })}
<div class={cn(className, 'min-w-128')}>
<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 scrolling down to
see the effect.
</p>
<div class="space-y-4">
<p class="text-text-muted">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua.
</p>
<p class="text-text-muted">
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.
</p>
<p class="text-text-muted">
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
</p>
<p class="text-text-muted">
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollim anim id est
laborum.
</p>
<p class="text-text-muted">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.
</p>
</div>
</div>
{/snippet}
{#snippet searchFontsTitle({ className }: { className?: string })}
<h2 class={className}>Search Fonts</h2>
{/snippet}
{#snippet searchFontsDescription({ className }: { className?: string })}
<span class={className}>Find your perfect typeface</span>
{/snippet}
{#snippet searchFontsContent({ className }: { className?: string })}
<div class={cn(className, 'min-w-128')}>
<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 provider.
</p>
</div>
{/snippet}
{#snippet longContentTitle({ className }: { className?: string })}
<h2 class={className}>Long Content</h2>
{/snippet}
{#snippet longContent({ className }: { className?: string })}
<div class={cn(className, 'min-w-128')}>
<div class="space-y-6">
<p class="text-lg text-text-muted">
This section demonstrates how the sticky title behaves with longer content. As you scroll through this
content, the title remains visible at the top of the viewport.
</p>
<div class="h-64 bg-background-40 rounded-lg flex items-center justify-center">
<span class="text-text-muted">Content block 1</span>
</div>
<p class="text-text-muted">
The sticky position is achieved using CSS position: sticky with a configurable top offset. This is
useful for long sections where you want to maintain context while scrolling.
</p>
<div class="h-64 bg-background-40 rounded-lg flex items-center justify-center">
<span class="text-text-muted">Content block 2</span>
</div>
<p class="text-text-muted">
The Intersection Observer API is used to detect when the section title scrolls out of view, triggering
the optional onTitleStatusChange callback.
</p>
<div class="h-64 bg-background-40 rounded-lg flex items-center justify-center">
<span class="text-text-muted">Content block 3</span>
</div>
</div>
</div>
{/snippet}
{#snippet minimalTitle({ className }: { className?: string })}
<h2 class={className}>Minimal Section</h2>
{/snippet}
{#snippet minimalContent({ className }: { className?: string })}
<div class={cn(className, 'min-w-128')}>
<p class="text-text-muted">
A minimal section without index, icon, or description. Just the essentials.
</p>
</div>
{/snippet}
{#snippet customTitle({ className }: { className?: string })}
<h2 class={className}>Custom Content</h2>
{/snippet}
{#snippet customDescription({ className }: { className?: string })}
<span class={className}>With interactive elements</span>
{/snippet}
{#snippet customContent({ className }: { className?: string })}
<div class={cn(className, 'min-w-128')}>
<div class="grid grid-cols-2 gap-4">
<div class="p-4 bg-background-40 rounded-lg">
<h3 class="font-semibold mb-2">Card 1</h3>
<p class="text-sm text-text-muted">Some content here</p>
</div>
<div class="p-4 bg-background-40 rounded-lg">
<h3 class="font-semibold mb-2">Card 2</h3>
<p class="text-sm text-text-muted">More content here</p>
</div>
</div>
</div>
{/snippet}
<Story
name="Default"
args={{
title: welcomeTitle,
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">
<Section index={1} {...args}>
{#snippet title({ className })}
<h2 class={className}>Welcome</h2>
{/snippet}
{#snippet content({ className })}
<div class={cn(className, 'min-w-128')}>
<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 grid layout with the title on the left and content on the right.
</p>
</div>
{/snippet}
</Section>
</div>
{/snippet} {/snippet}
</Story> </Story>
<Story <Story name="With Header">
name="With Sticky Title" {#snippet template()}
args={{ <Section title="Typography Settings" headerTitle="Section Header" headerSubtitle="Subtitle text" index={1}>
title: stickyTitle, {#snippet content()}
content: stickyContent, <p class="text-lg text-text-muted">
}} This section includes a header with title and subtitle above the section title.
> </p>
{#snippet template(args)} {/snippet}
<div class="h-[200vh]"> </Section>
<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
id="sticky-section"
index={1}
stickyTitle={true}
stickyOffset="20px"
{...args}
>
{#snippet title({ className })}
<h2 class={className}>Sticky Title</h2>
{/snippet}
{#snippet content({ className })}
<div class={cn(className, 'min-w-128')}>
<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 scrolling down to see the effect.
</p>
<div class="space-y-4">
<p class="text-text-muted">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
</p>
<p class="text-text-muted">
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat.
</p>
<p class="text-text-muted">
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur.
</p>
<p class="text-text-muted">
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollim anim id est laborum.
</p>
<p class="text-text-muted">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
doloremque laudantium.
</p>
</div>
</div>
{/snippet}
</Section>
</div>
</div>
{/snippet} {/snippet}
</Story> </Story>
<Story <Story name="With Header Content">
name="With Icon and Description" {#snippet template()}
args={{ <Section title="Search Fonts" index={1}>
icon: searchIcon, {#snippet headerContent()}
title: searchFontsTitle, <button class="px-3 py-1.5 text-sm bg-background-40 rounded-lg text-text-muted">
description: searchFontsDescription, Action
content: searchFontsContent, </button>
}} {/snippet}
> {#snippet content()}
{#snippet template(args)} <p class="text-lg text-text-muted">
<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"> Use the search bar to find fonts by name, or use the filters to browse by category, subset, or
<Section index={1} {...args}> provider.
{#snippet title({ className })} </p>
<h2 class={className}>Search Fonts</h2> {/snippet}
{/snippet} </Section>
{#snippet icon({ className })}
<SearchIcon class={className} />
{/snippet}
{#snippet description({ className })}
<span class={className}>Find your perfect typeface</span>
{/snippet}
{#snippet content({ className })}
<div class={cn(className, 'min-w-128')}>
<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 provider.
</p>
</div>
{/snippet}
</Section>
</div>
{/snippet} {/snippet}
</Story> </Story>
<Story name="Multiple Sections" tags={['!autodocs']}> <Story name="Multiple Sections" tags={['!autodocs']}>
{#snippet template(args)} {#snippet template()}
<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="space-y-0">
<Section <Section id="section-1" title="Typography" index={1}>
id="section-1" {#snippet content()}
index={1} <p class="text-lg text-text-muted">
stickyTitle={true} Control the size, weight, and line height of your text. These settings apply across the
{...args} comparison view.
> </p>
{#snippet title({ className })}
<h2 class={className}>Typography</h2>
{/snippet}
{#snippet icon({ className })}
<SettingsIcon class={className} />
{/snippet}
{#snippet description({ className })}
<span class={className}>Adjust text appearance</span>
{/snippet}
{#snippet content({ className })}
<div class={cn(className, 'min-w-128')}>
<p class="text-lg text-text-muted">
Control the size, weight, and line height of your text. These settings apply across the
comparison view.
</p>
</div>
{/snippet} {/snippet}
</Section> </Section>
<Section <Section id="section-2" title="Font Search" index={2}>
id="section-2" {#snippet content()}
index={2} <p class="text-lg text-text-muted">
stickyTitle={true} Search through our collection of fonts from Google Fonts and Fontshare. Use filters to narrow
{...args} down your selection.
> </p>
{#snippet title({ className })}
<h2 class={className}>Font Search</h2>
{/snippet}
{#snippet icon({ className })}
<SearchIcon class={className} />
{/snippet}
{#snippet description({ className })}
<span class={className}>Browse available typefaces</span>
{/snippet}
{#snippet content({ className })}
<div class={cn(className, 'min-w-128')}>
<p class="text-lg text-text-muted">
Search through our collection of fonts from Google Fonts and Fontshare. Use filters to
narrow down your selection.
</p>
</div>
{/snippet} {/snippet}
</Section> </Section>
<Section <Section id="section-3" title="Sample List" index={3}>
id="section-3" {#snippet content()}
index={3} <p class="text-lg text-text-muted">
stickyTitle={true} Browse through font samples with your custom text. The list is virtualized for optimal
{...args} performance.
> </p>
{#snippet title({ className })}
<h2 class={className}>Sample List</h2>
{/snippet}
{#snippet icon({ className })}
<ListIcon class={className} />
{/snippet}
{#snippet description({ className })}
<span class={className}>Preview font samples</span>
{/snippet}
{#snippet content({ className })}
<div class={cn(className, 'min-w-128')}>
<p class="text-lg text-text-muted">
Browse through font samples with your custom text. The list is virtualized for optimal
performance.
</p>
</div>
{/snippet} {/snippet}
</Section> </Section>
</div> </div>
{/snippet} {/snippet}
</Story> </Story>
<Story <Story name="With Long Content">
name="With Long Content" {#snippet template()}
args={{ <Section title="Long Content" index={1}>
title: longContentTitle, {#snippet content()}
content: longContent, <div class="space-y-6">
}} <p class="text-lg text-text-muted">
> This section demonstrates how the component behaves with longer content.
{#snippet template(args)} </p>
<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="h-64 bg-background-40 rounded-lg flex items-center justify-center">
<Section <span class="text-text-muted">Content block 1</span>
index={1}
stickyTitle={true}
stickyOffset="0px"
{...args}
>
{#snippet title({ className })}
<h2 class={className}>Long Content</h2>
{/snippet}
{#snippet content({ className })}
<div class={cn(className, 'min-w-128')}>
<div class="space-y-6">
<p class="text-lg text-text-muted">
This section demonstrates how the sticky title behaves with longer content. As you
scroll through this content, the title remains visible at the top of the viewport.
</p>
<div class="h-64 bg-background-40 rounded-lg flex items-center justify-center">
<span class="text-text-muted">Content block 1</span>
</div>
<p class="text-text-muted">
The sticky position is achieved using CSS position: sticky with a configurable top
offset. This is useful for long sections where you want to maintain context while
scrolling.
</p>
<div class="h-64 bg-background-40 rounded-lg flex items-center justify-center">
<span class="text-text-muted">Content block 2</span>
</div>
<p class="text-text-muted">
The Intersection Observer API is used to detect when the section title scrolls out of
view, triggering the optional onTitleStatusChange callback.
</p>
<div class="h-64 bg-background-40 rounded-lg flex items-center justify-center">
<span class="text-text-muted">Content block 3</span>
</div>
</div>
</div> </div>
{/snippet} <p class="text-text-muted">
</Section> The Section component provides a consistent layout container for page-level widgets with
</div> configurable titles and content areas.
</p>
<div class="h-64 bg-background-40 rounded-lg flex items-center justify-center">
<span class="text-text-muted">Content block 2</span>
</div>
<p class="text-text-muted">
Content is passed via snippets, allowing full flexibility in what gets rendered inside.
</p>
<div class="h-64 bg-background-40 rounded-lg flex items-center justify-center">
<span class="text-text-muted">Content block 3</span>
</div>
</div>
{/snippet}
</Section>
{/snippet} {/snippet}
</Story> </Story>
<Story <Story name="Minimal">
name="Minimal" {#snippet template()}
args={{ <Section title="Minimal Section">
title: minimalTitle, {#snippet content()}
content: minimalContent, <p class="text-text-muted">
}} A minimal section without index or header. Just the essentials.
> </p>
{#snippet template(args)} {/snippet}
<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 })}
<h2 class={className}>Minimal Section</h2>
{/snippet}
{#snippet content({ className })}
<div class={cn(className, 'min-w-128')}>
<p class="text-text-muted">
A minimal section without index, icon, or description. Just the essentials.
</p>
</div>
{/snippet}
</Section>
</div>
{/snippet} {/snippet}
</Story> </Story>
<Story <Story name="Custom Content">
name="Custom Content" {#snippet template()}
args={{ <Section title="Custom Content" index={42}>
title: customTitle, {#snippet content()}
description: customDescription, <div class="grid grid-cols-2 gap-4">
content: customContent, <div class="p-4 bg-background-40 rounded-lg">
}} <h3 class="font-semibold mb-2">Card 1</h3>
> <p class="text-sm text-text-muted">Some content here</p>
{#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">
<Section index={42} {...args}>
{#snippet title({ className })}
<h2 class={className}>Custom Content</h2>
{/snippet}
{#snippet description({ className })}
<span class={className}>With interactive elements</span>
{/snippet}
{#snippet content({ className })}
<div class={cn(className, 'min-w-128')}>
<div class="grid grid-cols-2 gap-4">
<div class="p-4 bg-background-40 rounded-lg">
<h3 class="font-semibold mb-2">Card 1</h3>
<p class="text-sm text-text-muted">Some content here</p>
</div>
<div class="p-4 bg-background-40 rounded-lg">
<h3 class="font-semibold mb-2">Card 2</h3>
<p class="text-sm text-text-muted">More content here</p>
</div>
</div>
</div> </div>
{/snippet} <div class="p-4 bg-background-40 rounded-lg">
</Section> <h3 class="font-semibold mb-2">Card 2</h3>
</div> <p class="text-sm text-text-muted">More content here</p>
</div>
</div>
{/snippet}
</Section>
{/snippet} {/snippet}
</Story> </Story>