import type { Meta, StoryObj } from '@storybook/react-vite' import { IconMenu2, IconSquareRounded } from '@tabler/icons-react' import { AppShell } from './AppShell' import { Banner } from './Banner' import { EmptyState } from './EmptyState' import { IconButton } from './IconButton' import { NavItem } from './NavItem' import { PersonTrigger } from './PersonTrigger' import { Rail } from './Rail' import { RailItem } from './RailItem' import { Sidebar } from './Sidebar' const meta = { title: 'Frame/AppShell', component: AppShell, parameters: { layout: 'fullscreen', // axe color-contrast is off here until PLAN.md stage 0.10 is ruled: // the count chip is muted text, 3.06:1 on the active row in signal, and the info // banner reads 3.99:1 on its wash in ship (AA 4.5:1). a11y: { config: { rules: [{ id: 'color-contrast', enabled: false }] } }, }, args: { nav: null, children: null }, argTypes: { variant: { control: 'inline-radio', options: ['solid', 'floating'] }, menu: { control: false }, logo: { control: false }, search: { control: false }, onSearch: { control: false }, identity: { control: false }, banner: { control: false }, nav: { control: false }, children: { control: false }, }, decorators: [(Story) =>
{Story()}
], } satisfies Meta export default meta type Story = StoryObj const identity = const menuButton = ( ) const placeholder = const sidebar = ( ) const rail = ( ) /** The structured frame: solid bar, sidebar, content beside it. */ export const Solid: Story = { render: (args) => ( {}} identity={identity} nav={sidebar}> ), } /** The banner belongs to the content area — at its top, never across the navigation. */ /** A page taller than the frame: it scrolls in the frame's own bar — the region every page passes through — never a native one. */ export const SolidScrolls: Story = { render: (args) => ( {}} identity={identity} nav={sidebar}>
{Array.from({ length: 60 }, (_, i) => (

Row {i + 1}

))}
), } export const SolidWithBanner: Story = { render: (args) => ( Public key copied.}> ), } /** The structured frame the other way round: the bar and the sidebar on the ground, the content a lighter card beside them. */ export const Inset: Story = { args: { variant: 'inset' }, render: (args) => ( {}} identity={identity} nav={sidebar}> ), } export const InsetWithBanner: Story = { args: { variant: 'inset' }, render: (args) => ( Public key copied.}> ), } /** The floating frame: the bar floats over the top edge, the rail stands on the background, and the content lives in the rounded card. */ export const Floating: Story = { render: (args) => ( {}} identity={identity} nav={rail} > ), } /** In the floating frame the banner draws inside the card, at its top. */ export const FloatingWithBanner: Story = { render: (args) => ( A new version is available. Reload when convenient.} > ), }