import { StoryObj, Meta } from "@storybook/react-vite"; import { within, expect } from "storybook/test"; import Badge from "./badge"; import "./badge.scss"; const meta: Meta = { title: "FP.React Components/Badge", component: Badge, tags: ["beta", "accessible"], parameters: { docs: { description: { component: `A notification badge component for displaying counts or status indicators with accessibility support. ## CSS Variables Customize the Badge appearance using CSS custom properties: ### Layout & Structure - \`--badge-bg\`: Background color (default: \`lightgray\`) - \`--badge-color\`: Text color (default: \`currentColor\`) - \`--badge-radius\`: Border radius (default: \`0.5rem\`) - \`--badge-padding\`: Internal padding (default: \`0.3rem\`) - \`--badge-vertical-align\`: Vertical alignment (default: \`0.5rem\`) ### Typography - \`--badge-fs\`: Font size (default: \`var(--fs-1)\`) ### Rounded Variant When using \`variant="rounded"\`: - \`--badge-size\`: Fixed circular size (default: \`1.5625rem\`) - Border radius automatically becomes \`50%\` - Padding becomes \`0\` - Content truncated with ellipsis if too long **Example:** \`\`\`css sup:has(> span) { --badge-bg: #ef4444; --badge-color: white; --badge-radius: 0.25rem; --badge-padding: 0.5rem; --badge-vertical-align: 0.75rem; --badge-fs: 0.875rem; } \`\`\``, }, }, }, args: { children: "5", }, } as Meta; export default meta; type Story = StoryObj; /** * Default badge story - demonstrates basic usage with notification count */ export const Default: Story = { args: { children: "5", "aria-label": "5 unread notifications", }, play: async ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText("5")).toBeInTheDocument(); expect(canvas.getByRole("status")).toHaveAttribute( "aria-label", "5 unread notifications" ); }, }; /** * Badge within text content - shows typical usage alongside other content */ export const WithinText: Story = { render: () => { return (

Messages 3

); }, play: async ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText(/messages/i)).toBeInTheDocument(); expect(canvas.getByText("3")).toBeInTheDocument(); }, } as Story; /** * Rounded variant badge - circular style for compact display */ export const RoundedVariant: Story = { args: { variant: "rounded", children: "99+", "aria-label": "More than 99 notifications", }, render: (args) => { return (

Notifications

); }, play: async ({ canvasElement }) => { const canvas = within(canvasElement); const badge = canvas.getByRole("status"); expect(badge).toHaveAttribute("data-badge", "rounded"); expect(canvas.getByText("99+")).toBeInTheDocument(); }, } as Story; /** * Multiple badges - demonstrates using multiple badges in the same context */ export const MultipleBadges: Story = { render: () => { return (

Inbox 122

Inbox 12

Tasks 5

Alerts 1

); }, } as Story; /** * Rounded badges with fixed circular shape - demonstrates perfect circles with ellipsis truncation * All rounded badges maintain a fixed size (1.5625rem), with content truncated using ellipsis if too long */ export const RoundedCircles: Story = { render: () => { return (

Single digit (perfect circle) 1

Single digit (perfect circle) 9

Double digits (perfect circle) 12

Double digits (perfect circle) 99

✅ Good: Formatted by developer 99+

⚠️ Will truncate: Too many characters 999+

⚠️ Will truncate: Text content NEW

⚠️ Will truncate: Very long text Multiple

); }, } as Story; /** * Custom styled badge - demonstrates custom styling with inline styles */ export const CustomStyling: Story = { args: { children: "NEW", "aria-label": "New feature", styles: { backgroundColor: "#10b981", color: "white", }, }, render: (args) => { return (

Feature Release

); }, } as Story;