← All proposals

Panel

The PDS v2 Panel (src/components/panels/Panel, branch v2.x) with one addition: the agentic-default, agentic-raised and agentic-sunken variants: each existing surface with the AI gradient as the border.

Extends a PDS componentOpen in Storybook

proposals/Panel/Panel.stories.tsx125 lines · View on GitHub
import { ComponentType, ReactNode } from 'react';

import { FlexContainer } from '@pantheon-systems/pds-toolkit-react';
import { Meta, StoryObj } from '@storybook/react-vite';

import { SlotPlaceholder } from '../_story-helpers/SlotPlaceholder';
import { ApprovalReport } from './ApprovalReport';
import { Panel, PanelPadding, PanelVariant } from './Panel';

// Storybook needs one flat args type. The component's own props only accept
// `isAnimated` with an `agentic-*` variant, which the controls can't express.
type PanelArgs = {
	children: ReactNode;
	className?: string;
	isAnimated?: boolean;
	padding?: PanelPadding;
	variant?: PanelVariant;
};

const meta: Meta<PanelArgs> = {
	tags: ['ready-for-dev'],
	title: 'Proposals/Panel',
	component: Panel as ComponentType<PanelArgs>,
	parameters: {
		docs: {
			description: {
				component:
					'Proposal, based on the PDS Panel, with `agentic-default`, `agentic-raised` and `agentic-sunken` variants: the AI gradient as the border, for content an agent produced or is acting on.',
			},
		},
	},
	argTypes: {
		children: { control: false, table: { category: 'Content' } },
		className: { table: { category: 'Base attributes' } },
		isAnimated: {
			control: 'boolean',
			table: { category: 'Appearance' },
		},
		padding: {
			control: 'select',
			options: ['none', 'condensed', 'standard', 'spacious'],
			table: { category: 'Layout' },
		},
		variant: {
			control: 'select',
			options: [
				'default',
				'agentic-default',
				'agentic-raised',
				'agentic-sunken',
				'sunken',
				'raised',
				'overlay',
				'critical',
				'info',
				'warning',
				'success',
				'discovery',
			],
			table: { category: 'Appearance' },
		},
	},
	args: {
		children: (
			<SlotPlaceholder label='children' style={{ minHeight: '8rem' }} />
		),
		isAnimated: true,
		padding: 'standard',
		variant: 'agentic-default',
	},
	decorators: [
		(Story) => (
			<div style={{ margin: '1rem' }}>
				<Story />
			</div>
		),
	],
};

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {};

export const WithContent: Story = {
	args: {
		children: <ApprovalReport />,
	},
	parameters: {
		docs: {
			description: {
				story:
					'An investigation report that needs approval, as the content of an agentic panel. The content belongs to the screen; the Panel only supplies the border and surface.',
			},
		},
	},
};

const AGENTIC_VARIANTS = [
	'agentic-default',
	'agentic-raised',
	'agentic-sunken',
] as const;

export const AllAgenticVariants: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'The three agentic variants. Each has the fill and shadow of the matching variant (default, raised, sunken) with the AI gradient as the border.',
			},
		},
	},
	render: (args) => (
		<FlexContainer flexDirection='column' gap='l'>
			{AGENTIC_VARIANTS.map((variant) => (
				<Panel {...args} key={variant} variant={variant}>
					<SlotPlaceholder label={variant} style={{ minHeight: '6rem' }} />
				</Panel>
			))}
		</FlexContainer>
	),
};