import { Meta, StoryObj } from '@storybook/react-webpack5'; import { Bank, Defrost } from '@transferwise/icons'; import Body from '../body'; import Button from '../button'; import Header from '../header'; import Link from '../link'; import IconButton from '../iconButton'; import StatusIcon from '../statusIcon'; import AvatarView from '../avatarView'; import SentimentSurface from './SentimentSurface'; import type { Sentiment, Emphasis } from './SentimentSurface.types'; const withComponentGrid = (Story: () => JSX.Element) => (
); /** * SentimentSurface is a polymorphic container component that exposes and, optionally, applies * contextual colour tokens as CSS custom properties, based on sentiment types (`negative`, * `warning`, `neutral`, `success`, `proposition`). */ const meta: Meta = { component: SentimentSurface, title: 'Foundations/SentimentSurface', tags: ['early-access'], argTypes: { sentiment: { control: 'select', options: ['negative', 'warning', 'neutral', 'success', 'proposition'], description: 'The sentiment type that determines the colour scheme', table: { type: { summary: 'Sentiment' }, }, }, emphasis: { control: 'inline-radio', options: ['base', 'elevated'], description: 'The emphasis level affecting background and text contrast', table: { defaultValue: { summary: '"base"' }, }, }, hasBaseStyles: { control: 'boolean', description: 'If true, sets the `background-color` and `color` on the container. Otherwise, only exposes the tokens as CSS custom properties without rendering.', table: { defaultValue: { summary: 'true' }, }, }, as: { control: 'text', description: 'The underlying HTML element to render.', table: { defaultValue: { summary: '"div"', }, type: { summary: 'string' }, }, }, className: { table: { type: { summary: 'string' }, }, control: 'text', }, id: { table: { type: { summary: 'string' }, }, control: 'text', }, 'data-testid': { control: 'text', table: { type: { summary: 'string' }, }, }, children: { table: { type: { summary: 'ReactNode' }, }, control: false, }, }, args: { sentiment: 'neutral', emphasis: 'base', hasBaseStyles: undefined, as: undefined, className: undefined, id: undefined, 'data-testid': undefined, children: 'This is a sentiment surface', }, }; export default meta; type Story = StoryObj; /** * The Playground story allows you to experiment with all the props of the SentimentSurface component. * Use the controls below to customise the sentiment type, emphasis level, and content. */ export const Playground: Story = { args: { sentiment: 'negative', emphasis: 'base', children: (
This is a custom div demonstrating a sentiment surface. It exposes CSS custom properties for the selected sentiment type and emphasis level and, optionally, applies background and text colours.
), }, }; const sentiments: Sentiment[] = ['negative', 'warning', 'neutral', 'success', 'proposition']; const emphasisLevels: Emphasis[] = ['base', 'elevated']; const tokenCategories = [ { name: 'Content', tokens: [ '--color-sentiment-content-primary', '--color-sentiment-content-primary-hover', '--color-sentiment-content-primary-active', ], }, { name: 'Interactive Primary', tokens: [ '--color-sentiment-interactive-primary', '--color-sentiment-interactive-primary-hover', '--color-sentiment-interactive-primary-active', ], }, { name: 'Interactive Secondary', tokens: [ '--color-sentiment-interactive-secondary', '--color-sentiment-interactive-secondary-hover', '--color-sentiment-interactive-secondary-active', ], }, { name: 'Interactive Control', tokens: [ '--color-sentiment-interactive-control', '--color-sentiment-interactive-control-hover', '--color-sentiment-interactive-control-active', ], }, { name: 'Background Surface', tokens: [ '--color-sentiment-background-surface', '--color-sentiment-background-surface-hover', '--color-sentiment-background-surface-active', ], }, ]; const TokenSwatch = ({ token }: { token: string }) => (
{token}
); /** * Each sentiment type has two emphasis levels – `base` and `elevated` – to provide different levels of visual prominence. * * **When to use:** * * - `Base`: For inline notifications, subtle callouts, or when sentiment needs to be communicated without drawing too much attention * - `Elevated`: For prominent banners, critical alerts, or when the sentiment should be immediately noticeable * */ export const EmphasisLevels: Story = { render: (args) => ( <>
Negative - Base emphasis
Negative - Elevated emphasis
Success - Base emphasis
Success - Elevated emphasis
), parameters: { controls: { disable: true }, }, decorators: [withComponentGrid], }; /** * By default, `SentimentSurface` exposes the tokens as CSS custom properties and also applies * the base styles for `background-color` and `color`. However, you can choose to expose said * properties without rendering them, by setting the `hasBaseStyles` prop to `false`. * This is useful when you want to create custom components that adapt to the sentiment context * without applying default styles. */ export const RenderingBaseStyles: Story = { render: (args) => ( <>
This example exposes and applies the tokens.
This example only exposes the tokens without applying them.
Which means you have to apply them yourself.
), parameters: { controls: { disable: true }, docs: { source: { // Storybook strips out props that are set to false, so we need to hack it back in :/ transform: async (source: string) => { if (source.includes('hasBaseStyles')) { return source; } return source.replace( /(<\/SentimentSurface>\s+