feat: add StatusText primitive with semantic color variants
Inline <span> component supporting success, warning, error, running, and muted variants with optional bold styling. Includes 7 unit tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
.statusText {}
|
||||
.success { color: var(--success); }
|
||||
.warning { color: var(--warning); }
|
||||
.error { color: var(--error); }
|
||||
.running { color: var(--running); }
|
||||
.muted { color: var(--text-muted); }
|
||||
.bold { font-weight: 600; }
|
||||
47
src/design-system/primitives/StatusText/StatusText.test.tsx
Normal file
47
src/design-system/primitives/StatusText/StatusText.test.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { StatusText } from './StatusText'
|
||||
|
||||
describe('StatusText', () => {
|
||||
it('renders children text', () => {
|
||||
render(<StatusText variant="success">Online</StatusText>)
|
||||
expect(screen.getByText('Online')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders as a span element', () => {
|
||||
render(<StatusText variant="success">Status</StatusText>)
|
||||
const el = screen.getByText('Status')
|
||||
expect(el.tagName).toBe('SPAN')
|
||||
})
|
||||
|
||||
it('applies variant class', () => {
|
||||
render(<StatusText variant="error">Failed</StatusText>)
|
||||
expect(screen.getByText('Failed')).toHaveClass('error')
|
||||
})
|
||||
|
||||
it('applies bold class when bold=true', () => {
|
||||
render(<StatusText variant="success" bold>OK</StatusText>)
|
||||
expect(screen.getByText('OK')).toHaveClass('bold')
|
||||
})
|
||||
|
||||
it('does not apply bold class by default', () => {
|
||||
render(<StatusText variant="success">OK</StatusText>)
|
||||
expect(screen.getByText('OK')).not.toHaveClass('bold')
|
||||
})
|
||||
|
||||
it('accepts custom className', () => {
|
||||
render(<StatusText variant="muted" className="custom">Text</StatusText>)
|
||||
expect(screen.getByText('Text')).toHaveClass('custom')
|
||||
})
|
||||
|
||||
it('renders all 5 variant classes correctly', () => {
|
||||
const variants = ['success', 'warning', 'error', 'running', 'muted'] as const
|
||||
for (const variant of variants) {
|
||||
const { unmount } = render(
|
||||
<StatusText variant={variant}>{variant}</StatusText>
|
||||
)
|
||||
expect(screen.getByText(variant)).toHaveClass(variant)
|
||||
unmount()
|
||||
}
|
||||
})
|
||||
})
|
||||
20
src/design-system/primitives/StatusText/StatusText.tsx
Normal file
20
src/design-system/primitives/StatusText/StatusText.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import styles from './StatusText.module.css'
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
interface StatusTextProps {
|
||||
variant: 'success' | 'warning' | 'error' | 'running' | 'muted'
|
||||
bold?: boolean
|
||||
children: ReactNode
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function StatusText({ variant, bold = false, children, className }: StatusTextProps) {
|
||||
const classes = [
|
||||
styles.statusText,
|
||||
styles[variant],
|
||||
bold ? styles.bold : '',
|
||||
className ?? '',
|
||||
].filter(Boolean).join(' ')
|
||||
|
||||
return <span className={classes}>{children}</span>
|
||||
}
|
||||
@@ -30,6 +30,7 @@ export { Sparkline } from './Sparkline/Sparkline'
|
||||
export { Spinner } from './Spinner/Spinner'
|
||||
export { StatCard } from './StatCard/StatCard'
|
||||
export { StatusDot } from './StatusDot/StatusDot'
|
||||
export { StatusText } from './StatusText/StatusText'
|
||||
export { Tag } from './Tag/Tag'
|
||||
export { Textarea } from './Textarea/Textarea'
|
||||
export { TimeRangeDropdown } from './TimeRangeDropdown/TimeRangeDropdown'
|
||||
|
||||
Reference in New Issue
Block a user