import type { Meta, StoryObj } from '@storybook/react-vite' import { IconDotsVertical } from '@tabler/icons-react' import { IconButton } from './IconButton' import { Panel } from './Panel' /** * A panel of a page: a header, a body that scrolls whenever it is taller than * the panel, and a row fixed under it when there is one. The body's words are * stand-ins. */ const meta = { title: 'Layout/Panel', component: Panel, parameters: { layout: 'fullscreen' }, args: { title: 'Details', children: null, bodyClassName: 'flex flex-col gap-3 px-4 pt-3 pb-4' }, argTypes: { children: { control: false }, actions: { control: false }, footer: { control: false } }, // A side column of the frame: 380px wide and a fixed height, where a panel sits beside a page. decorators: [ (Story) => (
{Story()}
), ], } satisfies Meta export default meta type Story = StoryObj const paragraph = (n: number) => (

Paragraph {n}. What this item is for, who it is for, and what it leaves for later, written out in full the way a real description is.

) const paragraphs = (count: number) => Array.from({ length: count }, (_, i) => paragraph(i + 1)) const menu = /** A short body: it fits, so there is no bar. */ export const Default: Story = { args: { actions: menu }, render: (args) => {paragraphs(2)}, } /** A title that opens something: the chevron after it, as ContainerHeader draws it. */ export const WithChevron: Story = { args: { chevron: true }, render: (args) => {paragraphs(2)}, } /** A body taller than the panel: it scrolls, and the bar shows at rest because there is more below. */ export const ALongBody: Story = { args: { actions: menu }, render: (args) => {paragraphs(14)}, } /** A row fixed under the body, such as a reply box: the body scrolls above it, and it stays put. */ export const WithAFooter: Story = { render: (args) => (
Footer
} > {paragraphs(12)}
), } /** Two panels in one column: the first capped at three fifths, each scrolls in its own room. */ export const TwoInAColumn: Story = { render: (args) => ( <> {paragraphs(10)} {paragraphs(6)} ), } /** In a plain box with a height, not a flex column: it still fills it, and the body still scrolls. */ export const InAPlainBox: Story = { decorators: [ (Story) => (
{Story()}
), ], parameters: { layout: 'fullscreen' }, render: (args) => {paragraphs(14)}, } function Broken(): never { throw new Error('The body could not draw itself') } /** A crash inside it stays inside it: the title stays, and the message takes the body's room. */ export const WhenTheBodyBreaks: Story = { render: (args) => ( ), }