import type { Meta, StoryObj } from 'storybook-solidjs-vite';
import { fn } from 'storybook/test';
import { ResizablePanelGroup, ResizablePanel, ResizableHandle, Resizable } from './resizable';
import { componentDescription } from '../stories/docs/element-controls';
const meta = {
title: 'Solid (Advanced)/Primitives/Resizable',
component: ResizablePanelGroup,
tags: ['autodocs'],
parameters: {
layout: 'padded',
docs: {
controls: { exclude: ['use:eventListener'] },
description: componentDescription([
'A **resizable split layout**: `ResizablePanelGroup` lays out `ResizablePanel` children along an axis, divided by a draggable `ResizableHandle`.',
'**When to use:** to let users adjust the relative size of two or more regions — e.g. a collapsible sidebar next to the main chat, or a chat pane next to an inspector.',
'**How to use:** wrap panels in `ResizablePanelGroup` and set `orientation` (`horizontal` row / `vertical` column). Give panels a `defaultSize` (percent) and optional `minSize`/`maxSize`; min/max are read from `data-min-size`/`data-max-size` attributes at drag time. Place a `ResizableHandle` (add `withHandle` for a visible grip) between panels. The group needs a sized container (height/width).',
'**Placement:** app shells — sidebar + conversation, conversation + context/inspector panels, or stacked editor/preview regions.',
]),
},
},
argTypes: {
orientation: {
control: 'select',
options: ['horizontal', 'vertical'],
description: 'Axis the panels are laid out along.',
table: { defaultValue: { summary: 'horizontal' } },
},
},
args: {
orientation: 'horizontal',
},
render: (args) => (
),
} satisfies Meta;
export default meta;
type Story = StoryObj;
const IMPORT = `import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@kitn.ai/chat';`;
const src = (code: string) => ({
parameters: { docs: { source: { code: `${IMPORT}\n\n${code}`, language: 'tsx' } } },
});
/** Interactive playground — flip the orientation, then drag the handle. */
export const Playground: Story = {
...src(`
Sidebar
Content
`),
};
export const Horizontal: Story = {
args: { orientation: 'horizontal' },
...src(`
Sidebar
Content
`),
};
/** Stacked top/bottom split (showcase). */
export const Vertical: Story = {
render: () => (
),
...src(`
Top
Bottom
`),
};
/** Three panels with two handles (showcase). */
export const ThreePanels: Story = {
name: 'Three Panels',
render: () => (
),
...src(`
Left
Center
Right
`),
};
/** Handle without a visible grip; reports drag deltas via `onPanelResize` (showcase). */
export const NoHandle: Story = {
name: 'Without Handle',
render: () => (
),
...src(`
Panel A
console.log(delta)} />
Panel B
`),
};
/**
* The `Resizable` convenience: pass `ResizablePanel` children and it
* auto-inserts a handle between each visible pair. A `locked` panel makes its
* neighbouring handle a static (non-draggable) divider; a `hidden` panel drops
* its divider entirely.
*/
export const ConvenienceGroup: Story = {
name: 'Resizable (convenience)',
render: () => (
console.log('sizes', sizes)}>
Locked sidebar (240px)
Chat
Preview
),
...src(` console.log(sizes)}>
Locked sidebar
Chat
Preview
`),
};
/**
* Min/max + keyboard: focus the handle (Tab) and use ←/→ to nudge, Home/End to
* jump to the panel's min/max. Sizes accept px or %.
*/
export const MinMaxKeyboard: Story = {
name: 'Min/Max + Keyboard',
render: () => (
min 120px · max 50%
Content (min 160px)
),
...src(`
Sidebar
Content
`),
};