diff --git a/src/components/Badge/index.stories.tsx b/src/components/Badge/index.stories.tsx index 33cc6812..de23c939 100644 --- a/src/components/Badge/index.stories.tsx +++ b/src/components/Badge/index.stories.tsx @@ -220,3 +220,44 @@ export const AllVariants: Story = { ), } + +export const AllSizes: Story = { + render: () => ( +
+ + Small + + + Medium + + + Large + +
+ ), +} + +export const AllSizesWithIcon: Story = { + render: () => ( +
+ + + + + Small + + + + + + Medium + + + + + + Large + +
+ ), +} diff --git a/src/components/Badge/index.test.tsx b/src/components/Badge/index.test.tsx index 408098ac..f0e5a153 100644 --- a/src/components/Badge/index.test.tsx +++ b/src/components/Badge/index.test.tsx @@ -8,4 +8,39 @@ describe('Badge', () => { render(Default) expect(screen.getByText('Default')).toBeInTheDocument() }) + + describe('size prop', () => { + it('defaults to md size classes', () => { + const { container } = render(Default) + const badge = container.firstChild as HTMLElement + expect(badge).toHaveClass('h-5') + expect(badge).toHaveClass('text-xs') + }) + + it('applies sm size classes', () => { + const { container } = render(Small) + const badge = container.firstChild as HTMLElement + expect(badge).toHaveClass('h-4') + expect(badge).toHaveClass('text-2xs') + }) + + it('applies lg size classes', () => { + const { container } = render(Large) + const badge = container.firstChild as HTMLElement + expect(badge).toHaveClass('h-6') + expect(badge).toHaveClass('text-base') + }) + + it('sm does not have md size classes', () => { + const { container } = render(Small) + const badge = container.firstChild as HTMLElement + expect(badge).not.toHaveClass('h-5') + }) + + it('lg does not have md size classes', () => { + const { container } = render(Large) + const badge = container.firstChild as HTMLElement + expect(badge).not.toHaveClass('h-5') + }) + }) }) diff --git a/src/components/Badge/index.tsx b/src/components/Badge/index.tsx index 4d481e3b..8abf029b 100644 --- a/src/components/Badge/index.tsx +++ b/src/components/Badge/index.tsx @@ -3,7 +3,7 @@ import { Slot } from '@radix-ui/react-slot' import { cva } from 'class-variance-authority' import { cn } from '@/lib/utils' -import { BadgeVariant } from '@/types' +import { BadgeVariant, BadgeSize } from '@/types' const BadgeLeftIcon = React.forwardRef< HTMLSpanElement, @@ -41,12 +41,16 @@ const BadgeText = React.forwardRef< HTMLSpanElement, React.HTMLAttributes >(({ className, ...props }, ref) => ( - + )) BadgeText.displayName = 'BadgeText' const badgeVariants = cva( - 'inline-flex items-center justify-center whitespace-nowrap select-none font-mono uppercase tracking-[0.03em] rounded-xs border transition-colors h-5 px-1 py-1 text-[12px] leading-[12px] gap-1 [&_svg]:size-3', + 'inline-flex items-center justify-center whitespace-nowrap select-none font-mono uppercase tracking-[0.03em] rounded-xs border transition-colors', { variants: { variant: { @@ -56,6 +60,11 @@ const badgeVariants = cva( success: 'text-default-success border-success-softest', warning: 'text-default-warning border-warning-softest', }, + size: { + sm: 'h-4 px-0.75 py-0.75 text-2xs leading-none gap-0.75 [&_svg]:size-2.25', + md: 'h-5 px-1 py-1 text-xs leading-none gap-1 [&_svg]:size-3', + lg: 'h-6 px-1 py-1 text-base leading-none gap-1 [&_svg]:size-4', + }, background: { true: '', false: 'bg-transparent', @@ -91,6 +100,7 @@ const badgeVariants = cva( defaultVariants: { variant: 'neutral', background: true, + size: 'md', }, } ) @@ -100,6 +110,7 @@ type Attributes = Omit, 'style'> export interface BadgeProps extends Attributes { asChild?: boolean variant?: BadgeVariant + size?: BadgeSize background?: boolean className?: string 'aria-label'?: string @@ -109,6 +120,7 @@ const Badge = React.forwardRef( ( { variant = 'neutral', + size = 'md', background = true, asChild = false, className, @@ -200,7 +212,7 @@ const Badge = React.forwardRef( return ( diff --git a/src/global.css b/src/global.css index fcc49c30..35973d60 100644 --- a/src/global.css +++ b/src/global.css @@ -1,6 +1,6 @@ /* * Global CSS - Main Entry Point - * + * * This file orchestrates the design system by: * 1. Importing Tailwind and plugins * 2. Defining custom variants @@ -63,5 +63,7 @@ --font-mono: var(--font-diatype-mono); --font-display: var(--font-tobias); --font-ascii: var(--font-speakeasy), var(--font-diatype-mono), monospace; -} + /* Extended text scale */ + --text-2xs: 0.5625rem; /* 9px */ +} diff --git a/src/types.ts b/src/types.ts index 6a122d8e..ac84e6a3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -29,6 +29,10 @@ export const badgeVariants = [ ] as const export type BadgeVariant = (typeof badgeVariants)[number] +// Badge sizes +export const badgeSizes = ['sm', 'md', 'lg'] as const +export type BadgeSize = (typeof badgeSizes)[number] + // Generic export type Orientation = 'horizontal' | 'vertical'