docs(popover): add storybook stories
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
<script module>
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import Popover from './Popover.svelte';
|
||||
|
||||
const { Story } = defineMeta({
|
||||
title: 'Shared/Popover',
|
||||
component: Popover,
|
||||
tags: ['autodocs'],
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
'Anchored popover on the native Popover API (top-layer, light-dismiss, ESC, focus return). Hand-rolled side/align/offset positioning with flip + shift.',
|
||||
},
|
||||
story: { inline: false }, // Render stories in iframe for state isolation
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
side: {
|
||||
control: 'select',
|
||||
options: ['top', 'bottom', 'left', 'right'],
|
||||
description: 'Preferred side',
|
||||
},
|
||||
align: {
|
||||
control: 'select',
|
||||
options: ['start', 'center', 'end'],
|
||||
description: 'Cross-axis alignment',
|
||||
},
|
||||
sideOffset: {
|
||||
control: 'number',
|
||||
description: 'Gap between trigger and content (px)',
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { Slider } from '$shared/ui';
|
||||
|
||||
let open = $state(false);
|
||||
let value = $state(50);
|
||||
</script>
|
||||
|
||||
<Story name="Bottom">
|
||||
{#snippet template()}
|
||||
<div class="p-32 flex-center min-h-screen">
|
||||
<Popover bind:open side="bottom" align="center" sideOffset={8}>
|
||||
{#snippet trigger(props)}
|
||||
<button {...props} class="surface-card-elevated px-4 py-2">Open popover</button>
|
||||
{/snippet}
|
||||
{#snippet children()}
|
||||
<div class="surface-popover p-4 w-56">Popover content</div>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
</div>
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
||||
<Story name="Top">
|
||||
{#snippet template()}
|
||||
<div class="p-32 flex-center min-h-screen">
|
||||
<Popover bind:open side="top" align="center" sideOffset={8}>
|
||||
{#snippet trigger(props)}
|
||||
<button {...props} class="surface-card-elevated px-4 py-2">Open popover</button>
|
||||
{/snippet}
|
||||
{#snippet children()}
|
||||
<div class="surface-popover p-4 w-56">Popover content</div>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
</div>
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
||||
<!--
|
||||
Mirrors TypographyMenu: top/end placement with a programmatic Close button
|
||||
wired to the `close()` param of the children snippet.
|
||||
-->
|
||||
<Story name="AlignedEnd">
|
||||
{#snippet template()}
|
||||
<div class="p-32 flex-center min-h-screen">
|
||||
<Popover bind:open side="top" align="end" sideOffset={8}>
|
||||
{#snippet trigger(props)}
|
||||
<button {...props} class="surface-card-elevated px-4 py-2">Open menu</button>
|
||||
{/snippet}
|
||||
{#snippet children({ close })}
|
||||
<div class="surface-popover p-4 w-72">
|
||||
<h3 class="text-sm font-medium mb-3">Menu header</h3>
|
||||
<p class="text-sm text-muted-foreground mb-4">
|
||||
Aligned to the trigger's end edge.
|
||||
</p>
|
||||
<button class="surface-card-elevated px-3 py-1.5 text-sm" onclick={close}>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
</div>
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
||||
<!-- Mirrors ComboControl: a vertical Slider lives inside the popover content. -->
|
||||
<Story name="WithSlider">
|
||||
{#snippet template()}
|
||||
<div class="p-32 flex-center min-h-screen">
|
||||
<Popover bind:open side="top" align="center" sideOffset={8}>
|
||||
{#snippet trigger(props)}
|
||||
<button {...props} class="surface-card-elevated px-4 py-2">Adjust value</button>
|
||||
{/snippet}
|
||||
{#snippet children()}
|
||||
<div class="surface-card-elevated p-3 h-64 flex-center">
|
||||
<Slider orientation="vertical" min={0} max={100} bind:value />
|
||||
</div>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
</div>
|
||||
{/snippet}
|
||||
</Story>
|
||||
Reference in New Issue
Block a user