← All proposals

Section Message

A copy of the PDS v2 Section Message (pds-section-message, same class names, props and behavior) with an agentic type (AI gradient border on a surface fill, the Agent Avatar as its leading icon (decided 2026-10-21; iconName picks its icon), the standard secondary Button as the CTA, a silver-muted Badge) and an avatarProps option for the avatar (halo, shape, size).

Extends a PDS componentOpen in Storybook

proposals/SectionMessage/SectionMessage.stories.tsx255 lines · View on GitHub
import { Meta, StoryObj } from '@storybook/react-vite';

import { SectionMessage } from './SectionMessage';

const meta: Meta<typeof SectionMessage> = {
	tags: ['ready-for-dev'],
	title: 'Component Proposals/Section Message',
	component: SectionMessage,
	parameters: {
		docs: {
			description: {
				component:
					'A copy of the PDS v2 Section Message: a message used to alert users to a particular section of the screen.',
			},
		},
	},

	argTypes: {
		iconName: {
			control: 'select',
			options: ['zappy', 'sparklesSolid'],
			table: {
				category: 'Content',
			},
		},
		avatarProps: {
			control: 'object',
			table: {
				category: 'Content',
			},
		},
		badgeIcon: {
			control: 'select',
			table: {
				category: 'Content',
			},
		},
		badgeLabel: {
			table: {
				category: 'Content',
			},
		},
		className: {
			table: {
				category: 'Base attributes',
			},
		},
		ctaButton: {
			table: {
				category: 'Content',
			},
		},
		ctaIcon: {
			control: 'select',
			table: {
				category: 'Content',
			},
		},
		dismissLabel: {
			table: {
				category: 'Translation strings',
			},
		},
		secondaryCta: {
			table: {
				category: 'Content',
			},
		},
		id: {
			table: {
				category: 'Base attributes',
			},
		},
		isDismissible: {
			table: {
				category: 'Component configuration',
			},
		},
		message: {
			table: {
				category: 'Content',
			},
		},
		onDismiss: {
			table: {
				category: 'Functions',
			},
		},
		title: {
			table: {
				category: 'Content',
			},
		},
		type: {
			control: {
				type: 'select',
			},
			table: {
				category: 'Status',
			},
		},
		typeLabels: {
			table: {
				category: 'Translation strings',
			},
		},
	},
	args: {
		type: 'agentic',
		dismissLabel: 'Dismiss',
		title: 'Zappy recommends a quieter time',
	},
};

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
	args: {
		message: (
			<p>
				Run this operation at 1:00–2:00 AM, your quietest hour and about 94%
				below peak traffic. <a href='#'>See traffic by hour</a>
			</p>
		),
		isDismissible: true,
		id: '001',
		onDismiss: () => {
			console.log('Message dismissed.');
		},
	},
};

export const WithoutTitle: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'Omit `title` for a shorter message that doesn’t need its own heading — just a single line of text.',
			},
		},
	},
	args: {
		message:
			'Zappy recommends running this operation at 1:00–2:00 AM, your quietest hour.',
		id: '002',
		title: undefined,
	},
};

export const WithCTA: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'Pass a `ctaButton` object to surface a primary action directly in the message — use this when users need to take a specific step before they can proceed.',
			},
		},
	},
	args: {
		message:
			'Zappy recommends running this operation at 1:00–2:00 AM, your quietest hour and about 94% below peak traffic.',
		id: '003',
		ctaButton: {
			label: 'Schedule for 1:00 AM',
			type: 'button' as const,
			onClick: () => {
				console.log('CTA button clicked.');
			},
		},
	},
};

export const WithCTAIcon: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'Pass `ctaIcon` to show a leading icon on the CTA button. It always matches the button’s (and the section message’s) own foreground color.',
			},
		},
	},
	args: {
		message:
			'Zappy recommends running this operation at 1:00–2:00 AM, your quietest hour and about 94% below peak traffic.',
		id: '004',
		ctaButton: {
			label: 'Schedule for 1:00 AM',
			type: 'button' as const,
			onClick: () => {
				console.log('CTA button clicked.');
			},
		},
		ctaIcon: 'clock',
	},
};

export const WithSecondaryAction: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'Pass a `secondaryCta` alongside `ctaButton` for a lesser action, such as undoing or dismissing the state the message describes. It renders before the CTA so the more prominent action sits on the outside, and defaults to the `link` variant.',
			},
		},
	},
	args: {
		message:
			'Backups for 3 sites are scheduled during peak hours (9:00 AM–5:00 PM). Moving them to 1:00 AM avoids slowing those sites down.',
		id: '005',
		title: 'Move backups to a quieter time?',
		ctaButton: {
			label: 'Reschedule to 1:00 AM',
			type: 'button' as const,
			onClick: () => {
				console.log('CTA button clicked.');
			},
		},
		secondaryCta: {
			label: 'Keep current time',
			type: 'button' as const,
			onClick: () => {
				console.log('Secondary button clicked.');
			},
		},
	},
};

export const WithBadge: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'Pass `badgeLabel` (and optionally `badgeIcon`) to show a badge beside the title. The badge color matches `type`, except for `agentic`, where it is the neutral `silver-muted`. Requires `title`.',
			},
		},
	},
	args: {
		message:
			'Zappy recommends running this operation at 1:00–2:00 AM, your quietest hour and about 94% below peak traffic.',
		id: '006',
		title: 'Best time to run this operation',
		badgeLabel: 'Suggested',
		badgeIcon: 'clock',
		ctaButton: {
			label: 'Schedule for 1:00 AM',
			type: 'button' as const,
			onClick: () => {
				console.log('CTA button clicked.');
			},
		},
	},
};