import type { Meta, StoryObj } from 'storybook-solidjs-vite'; import { For } from 'solid-js'; import { ScrollButton } from './scroll-button'; import { ChatContainerRoot, ChatContainerContent } from './chat-container'; import { componentDescription } from '../stories/docs/element-controls'; /** * `ScrollButton` reads scroll state from the surrounding `ChatContainerRoot` * context, so every story wraps it in a scrollable container. It is hidden * (faded out) while pinned to the bottom and appears once you scroll up. */ function ScrollDemo(props: { variant?: 'outline' | 'ghost' | 'default'; size?: 'sm' | 'md' | 'lg' | 'icon' | 'icon-sm'; class?: string }) { return (
{(_, i) => (
Message {i() + 1}
)}
{/* ScrollButton must live INSIDE ChatContainerRoot (it reads that context); it's absolutely positioned relative to the outer .relative box, so it stays pinned and doesn't scroll with the content. */}
); } const meta = { title: 'Solid (Advanced)/Elements/ScrollButton', component: ScrollButton, tags: ['autodocs'], parameters: { layout: 'padded', docs: { description: componentDescription([ 'A floating "scroll to bottom" button wired to the enclosing `ChatContainerRoot`. It calls `scrollToBottom()` on click and animates in/out based on `isAtBottom`.', '**When to use:** in a scrollable message log, to let the user jump back to the latest message after scrolling up. It hides itself automatically while pinned to the bottom.', '**How to use:** render it inside a `ChatContainerRoot` (it consumes that context). Position it with absolute layout and optionally restyle via `variant`, `size`, and `class`.', '**Placement:** overlaid near the bottom-center of the chat message area.', ]), controls: { exclude: ['use:eventListener'] }, }, }, argTypes: { variant: { control: 'select', options: ['default', 'ghost', 'outline'], description: 'Underlying button visual emphasis.', table: { defaultValue: { summary: 'outline' } }, }, size: { control: 'select', options: ['sm', 'md', 'lg', 'icon', 'icon-sm'], description: 'Underlying button size preset.', table: { defaultValue: { summary: 'sm' } }, }, class: { control: 'text', description: 'Additional classes merged onto the button.', }, }, args: { variant: 'outline', size: 'sm', }, render: (args) => , } satisfies Meta; export default meta; type Story = StoryObj; const IMPORT = `import { ScrollButton, ChatContainerRoot, ChatContainerContent } from '@kitn.ai/chat';`; const src = (code: string) => ({ parameters: { docs: { source: { code: `${IMPORT}\n\n${code}`, language: 'tsx' } } }, }); /** Interactive playground — scroll up to reveal the button; tweak `variant`/`size`. */ export const Playground: Story = { ...src(`
{/* messages */} {/* inside the Root (reads its context); absolutely positioned to stay pinned */}
`), }; /** Ghost variant overlaid in a chat area (showcase). */ export const Ghost: Story = { args: { variant: 'ghost' }, ...src(``), };