import type { Meta, StoryObj } from '@storybook/nextjs-vite' import { useMemo } from 'react' import { InfoCircleIcon } from '../components/icons-v2-generated/signs-and-symbols' import { type ColumnDef, DataTable, type Row, useDataTable } from '../components/ui/data-table' import { EntityImage } from '../components/ui/entity-image' import { StackedRowsPanel } from '../components/ui/stacked-rows-panel' import { Tag } from '../components/ui/tag' const meta = { title: 'UI/StackedRowsPanel', component: StackedRowsPanel, parameters: { layout: 'padded', docs: { description: { component: 'A single bordered card that stacks rows inside it. Each row can be one full-width element ' + '(title + subtitle), several columns (value + label, optionally a tag/avatar), or an arbitrary ' + 'node such as a nested table. The container handles all rounding: one row rounds every corner, ' + 'while many rows round only the first row’s top corners and the last row’s bottom corners.', }, }, }, tags: ['autodocs'], } satisfies Meta export default meta type Story = StoryObj /** Header card: a full-width title/description row followed by a columns row. */ export const HeaderCard: Story = { args: { rows: [ { id: 'title', columns: [ { key: 'title', value: 'Monitors sustained high processor utilization indicating performance bottlenecks', label: 'Description', }, ], }, { id: 'meta', columns: [ { key: 'severity', value: 'Critical', label: 'Severity' }, { key: 'status', value: , label: 'Status' }, { key: 'author', value: 'Jane Doe', label: 'Author' }, ], }, ], }, } /** Standard table: uniform multi-column rows (avatar + name/email, role, status tag). */ export const StandardTable: Story = { args: { rows: [ { id: 'jane', columns: [ { key: 'user', content: (
Jane Doe jane.doe@example.com
), }, { key: 'role', value: 'Admin', hideAt: 'md' }, { key: 'status', content: , align: 'right' }, ], }, { id: 'john', columns: [ { key: 'user', content: (
John Roe john.roe@example.com
), }, { key: 'role', value: 'Admin', hideAt: 'md' }, { key: 'status', content: , align: 'right' }, ], }, ], }, } /** A single row rounds all four corners. */ export const SingleRow: Story = { args: { rows: [{ id: 'only', columns: [{ key: 'only', value: 'High CPU Usage >85%', label: 'Policy' }] }], }, } /** Info-banner row: `leadingIcon` centers a 24px glyph against both text lines. */ export const InfoBanner: Story = { args: { rows: [ { id: 'banner', className: 'p-[var(--spacing-system-s)]', columns: [ { key: 'banner', leadingIcon: , value: 'Using OpenFrame default actions', label: 'These quick actions are curated and approved by OpenFrame.', }, ], }, ], }, } interface DemoDevice { id: string name: string status: 'NON-COMPLIANT' | 'COMPLIANT' } const DEMO_DEVICES: DemoDevice[] = [ { id: '1', name: "John's Device", status: 'NON-COMPLIANT' }, { id: '2', name: 'Workstation-04', status: 'COMPLIANT' }, ] function NestedDevicesTable() { const columns = useMemo[]>( () => [ { accessorKey: 'name', header: 'DEVICE', cell: ({ row }: { row: Row }) => (
{row.original.name} Last Online: 2 hours ago
), }, { accessorKey: 'status', header: 'STATUS', cell: ({ row }: { row: Row }) => ( ), meta: { width: 'w-[180px]' }, }, ], [], ) const table = useDataTable({ data: DEMO_DEVICES, columns, getRowId: (row: DemoDevice) => row.id, enableSorting: false, }) return ( ) } /** A panel row can host an arbitrary node — here a nested DataTable. */ export const WithNestedTable: Story = { args: { title: 'Devices', rows: [{ id: 'devices', className: 'p-[var(--spacing-system-m)]', content: }], }, }