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(``),
};