From 5a27a42119b794ed0e4a5cb1185f1e206e972ef4 Mon Sep 17 00:00:00 2001 From: Alex Martin Date: Mon, 1 Jun 2026 18:02:07 -0700 Subject: [PATCH 1/7] feat(badge): add BadgeSize type --- src/components/Badge/index.test.tsx | 6 ++++++ src/types.ts | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/components/Badge/index.test.tsx b/src/components/Badge/index.test.tsx index 408098ac..8d65b018 100644 --- a/src/components/Badge/index.test.tsx +++ b/src/components/Badge/index.test.tsx @@ -8,4 +8,10 @@ describe('Badge', () => { render(Default) expect(screen.getByText('Default')).toBeInTheDocument() }) + + it('accepts size prop without type error', () => { + // This test is a compile-time check; runtime just verifies it renders + const { container } = render(Test) + expect(container.firstChild).toBeInTheDocument() + }) }) 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' From 6726d43ffd22b3478e2099f64225334933650359 Mon Sep 17 00:00:00 2001 From: Alex Martin Date: Mon, 1 Jun 2026 18:03:39 -0700 Subject: [PATCH 2/7] test(badge): remove misleading comment from size prop test --- src/components/Badge/index.test.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Badge/index.test.tsx b/src/components/Badge/index.test.tsx index 8d65b018..97019e35 100644 --- a/src/components/Badge/index.test.tsx +++ b/src/components/Badge/index.test.tsx @@ -10,7 +10,6 @@ describe('Badge', () => { }) it('accepts size prop without type error', () => { - // This test is a compile-time check; runtime just verifies it renders const { container } = render(Test) expect(container.firstChild).toBeInTheDocument() }) From 17511ddbda60f5e61bcaf63b940f4fef4365a281 Mon Sep 17 00:00:00 2001 From: Alex Martin Date: Mon, 1 Jun 2026 18:05:07 -0700 Subject: [PATCH 3/7] feat(badge): add size variant (sm/md/lg) --- src/components/Badge/index.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/Badge/index.tsx b/src/components/Badge/index.tsx index 4d481e3b..26fc806d 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, @@ -46,7 +46,7 @@ const BadgeText = React.forwardRef< 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 +56,11 @@ const badgeVariants = cva( success: 'text-default-success border-success-softest', warning: 'text-default-warning border-warning-softest', }, + size: { + sm: 'h-[15px] px-[3px] py-[3px] text-[9px] leading-[9px] gap-[3px] [&_svg]:size-[9px]', + md: 'h-5 px-1 py-1 text-[12px] leading-[12px] gap-1 [&_svg]:size-3', + lg: 'h-[25px] px-[5px] py-[5px] text-[15px] leading-[15px] gap-[5px] [&_svg]:size-[15px]', + }, background: { true: '', false: 'bg-transparent', @@ -91,6 +96,7 @@ const badgeVariants = cva( defaultVariants: { variant: 'neutral', background: true, + size: 'md', }, } ) @@ -100,6 +106,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 +116,7 @@ const Badge = React.forwardRef( ( { variant = 'neutral', + size = 'md', background = true, asChild = false, className, @@ -200,7 +208,7 @@ const Badge = React.forwardRef( return ( From dd8393e8c2b6bea4aa0953b7cd7983f518f29642 Mon Sep 17 00:00:00 2001 From: Alex Martin Date: Mon, 1 Jun 2026 18:08:13 -0700 Subject: [PATCH 4/7] test(badge): add size prop coverage --- src/components/Badge/index.test.tsx | 36 ++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/components/Badge/index.test.tsx b/src/components/Badge/index.test.tsx index 97019e35..0cccc7ee 100644 --- a/src/components/Badge/index.test.tsx +++ b/src/components/Badge/index.test.tsx @@ -9,8 +9,38 @@ describe('Badge', () => { expect(screen.getByText('Default')).toBeInTheDocument() }) - it('accepts size prop without type error', () => { - const { container } = render(Test) - expect(container.firstChild).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-[12px]') + }) + + it('applies sm size classes', () => { + const { container } = render(Small) + const badge = container.firstChild as HTMLElement + expect(badge).toHaveClass('h-[15px]') + expect(badge).toHaveClass('text-[9px]') + }) + + it('applies lg size classes', () => { + const { container } = render(Large) + const badge = container.firstChild as HTMLElement + expect(badge).toHaveClass('h-[25px]') + expect(badge).toHaveClass('text-[15px]') + }) + + 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') + }) }) }) From d90aaa79a62e4fc68f8ed025bbc407c3a5076ff4 Mon Sep 17 00:00:00 2001 From: Alex Martin Date: Mon, 1 Jun 2026 18:09:25 -0700 Subject: [PATCH 5/7] docs(badge): add AllSizes and AllSizesWithIcon stories --- src/components/Badge/index.stories.tsx | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) 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 + +
+ ), +} From ab401ddda279af454efdfbe9cd1a85d2a09afdb4 Mon Sep 17 00:00:00 2001 From: Alex Martin Date: Mon, 1 Jun 2026 19:01:12 -0700 Subject: [PATCH 6/7] switch to using tailwind classes not arbitray values --- src/components/Badge/index.test.tsx | 10 +++++----- src/components/Badge/index.tsx | 6 +++--- src/global.css | 6 ++++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/components/Badge/index.test.tsx b/src/components/Badge/index.test.tsx index 0cccc7ee..f0e5a153 100644 --- a/src/components/Badge/index.test.tsx +++ b/src/components/Badge/index.test.tsx @@ -14,21 +14,21 @@ describe('Badge', () => { const { container } = render(Default) const badge = container.firstChild as HTMLElement expect(badge).toHaveClass('h-5') - expect(badge).toHaveClass('text-[12px]') + expect(badge).toHaveClass('text-xs') }) it('applies sm size classes', () => { const { container } = render(Small) const badge = container.firstChild as HTMLElement - expect(badge).toHaveClass('h-[15px]') - expect(badge).toHaveClass('text-[9px]') + 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-[25px]') - expect(badge).toHaveClass('text-[15px]') + expect(badge).toHaveClass('h-6') + expect(badge).toHaveClass('text-base') }) it('sm does not have md size classes', () => { diff --git a/src/components/Badge/index.tsx b/src/components/Badge/index.tsx index 26fc806d..c093c252 100644 --- a/src/components/Badge/index.tsx +++ b/src/components/Badge/index.tsx @@ -57,9 +57,9 @@ const badgeVariants = cva( warning: 'text-default-warning border-warning-softest', }, size: { - sm: 'h-[15px] px-[3px] py-[3px] text-[9px] leading-[9px] gap-[3px] [&_svg]:size-[9px]', - md: 'h-5 px-1 py-1 text-[12px] leading-[12px] gap-1 [&_svg]:size-3', - lg: 'h-[25px] px-[5px] py-[5px] text-[15px] leading-[15px] gap-[5px] [&_svg]:size-[15px]', + 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: '', 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 */ +} From f0e6ed8f1dc6f20cc2f9eb6a7a44dd6872124f5b Mon Sep 17 00:00:00 2001 From: Alex Martin Date: Mon, 1 Jun 2026 19:09:26 -0700 Subject: [PATCH 7/7] fix: add text-trim-cap to badge text fixes text alignment for better centering --- src/components/Badge/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/Badge/index.tsx b/src/components/Badge/index.tsx index c093c252..8abf029b 100644 --- a/src/components/Badge/index.tsx +++ b/src/components/Badge/index.tsx @@ -41,7 +41,11 @@ const BadgeText = React.forwardRef< HTMLSpanElement, React.HTMLAttributes >(({ className, ...props }, ref) => ( - + )) BadgeText.displayName = 'BadgeText'