diff --git a/src/index.css b/src/index.css index ad25b80..0295c40 100644 --- a/src/index.css +++ b/src/index.css @@ -16,6 +16,24 @@ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05); --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1); + + /* Status Backgrounds */ +--color-bg-danger: #fde8e8; +--color-bg-warning: #fef3c7; +--color-bg-success: #e6f4ea; +--color-bg-info: #e8f1fb; + +/* Status Text */ +--color-text-danger: #b91c1c; +--color-text-warning: #92400e; +--color-text-success: #166534; +--color-text-info: #1e3a8a; + +/* Status Borders */ +--color-border-danger: #f5c2c2; +--color-border-warning: #fde68a; +--color-border-success: #bbf7d0; +--color-border-info: #bfdbfe; } /* 2. Tailwind v4 bridge (CRITICAL) */ @@ -35,11 +53,23 @@ --color-border-secondary: var(--color-border-secondary); --color-border-tertiary: var(--color-border-tertiary); - /* Status */ - --color-danger: var(--color-danger); - --color-warning: var(--color-warning); - --color-success: var(--color-success); - --color-info: var(--color-info); + /* Status Backgrounds */ + --color-bg-danger: var(--color-bg-danger); + --color-bg-warning: var(--color-bg-warning); + --color-bg-success: var(--color-bg-success); + --color-bg-info: var(--color-bg-info); + + /* Status Text */ + --color-text-danger: var(--color-text-danger); + --color-text-warning: var(--color-text-warning); + --color-text-success: var(--color-text-success); + --color-text-info: var(--color-text-info); + + /* Status Borders */ + --color-border-danger: var(--color-border-danger); + --color-border-warning: var(--color-border-warning); + --color-border-success: var(--color-border-success); + --color-border-info: var(--color-border-info); } /* Disable transitions on first load (prevents flash) */ @@ -56,4 +86,4 @@ html[data-theme-loaded="true"] * { color 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease; -} +} \ No newline at end of file diff --git a/src/shared/Badge/Badge.stories.tsx b/src/shared/Badge/Badge.stories.tsx index a958c4c..a44286f 100644 --- a/src/shared/Badge/Badge.stories.tsx +++ b/src/shared/Badge/Badge.stories.tsx @@ -1,30 +1,125 @@ -import type { Meta, StoryObj } from '@storybook/react-vite' -import { Badge } from '.' +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { Badge } from '.'; const meta = { title: 'Shared/Primitives/Badge', component: Badge, tags: ['autodocs'], + argTypes: { variant: { control: 'select', - options: ['pending', 'escalated', 'resolved', 'dismissed', 'info'], + options: [ + 'default', + 'pending', + 'escalated', + 'resolved', + 'dismissed', + 'info', + 'success', + 'warning', + 'danger', + ], }, + size: { control: 'select', options: ['sm', 'md'], }, + + dot: { + control: 'boolean', + }, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + children: 'Default', + variant: 'default', + }, +}; + +export const Pending: Story = { + args: { + children: 'Pending', + variant: 'pending', + }, +}; + +export const Escalated: Story = { + args: { + children: 'Escalated', + variant: 'escalated', + }, +}; + +export const Resolved: Story = { + args: { + children: 'Resolved', + variant: 'resolved', }, -} satisfies Meta +}; -export default meta -type Story = StoryObj +export const Dismissed: Story = { + args: { + children: 'Dismissed', + variant: 'dismissed', + }, +}; + +export const Info: Story = { + args: { + children: 'Info', + variant: 'info', + }, +}; + +export const Success: Story = { + args: { + children: 'Success', + variant: 'success', + }, +}; + +export const Warning: Story = { + args: { + children: 'Warning', + variant: 'warning', + }, +}; -// one export per variant/state from your issue spec -export const Pending: Story = { args: { label: 'Pending', variant: 'pending' } } -export const Escalated: Story = { args: { label: 'Escalated', variant: 'escalated' } } -export const Resolved: Story = { args: { label: 'Resolved', variant: 'resolved' } } -export const Dismissed: Story = { args: { label: 'Dismissed', variant: 'dismissed' } } -export const Info: Story = { args: { label: 'Info', variant: 'info' } } -export const Small: Story = { args: { label: 'Pending', variant: 'pending', size: 'sm' } } -export const Medium: Story = { args: { label: 'Pending', variant: 'pending', size: 'md' } } +export const Danger: Story = { + args: { + children: 'Danger', + variant: 'danger', + }, +}; + +export const Small: Story = { + args: { + children: 'Small Badge', + variant: 'pending', + size: 'sm', + }, +}; + +export const Medium: Story = { + args: { + children: 'Medium Badge', + variant: 'pending', + size: 'md', + }, +}; + +export const Dot: Story = { + args: { + variant: 'success', + dot: true, + size: 'md', + }, +}; \ No newline at end of file diff --git a/src/shared/Badge/Badge.tsx b/src/shared/Badge/Badge.tsx index a84d9f4..acb63bf 100644 --- a/src/shared/Badge/Badge.tsx +++ b/src/shared/Badge/Badge.tsx @@ -1,38 +1,88 @@ -import { cva, type VariantProps } from 'class-variance-authority' +import React from 'react'; +import { cva, type VariantProps } from 'class-variance-authority'; const badge = cva( - // base styles applied to every variant - 'inline-flex items-center font-medium rounded-full border', + 'inline-flex items-center gap-1 font-medium rounded-full border transition-opacity', { variants: { variant: { - pending: 'bg-yellow-50 text-yellow-700 border-yellow-200', - escalated: 'bg-red-50 text-red-700 border-red-200', - resolved: 'bg-green-50 text-green-700 border-green-200', - dismissed: 'bg-gray-50 text-gray-500 border-gray-200', - info: 'bg-blue-50 text-blue-700 border-blue-200', + default: + 'bg-bg-secondary text-text-secondary border-border-secondary', + + warning: + 'bg-bg-warning text-text-warning border-border-warning', + + danger: + 'bg-bg-danger text-text-danger border-border-danger', + + success: + 'bg-bg-success text-text-success border-border-success', + + pending: + 'bg-bg-warning text-text-warning border-border-warning', + + escalated: + 'bg-bg-danger text-text-danger border-border-danger', + + resolved: + 'bg-bg-success text-text-success border-border-success', + + dismissed: + 'bg-bg-secondary text-text-tertiary border-border-secondary', + + info: + 'bg-bg-info text-text-info border-border-info', }, + size: { sm: 'px-2 py-0.5 text-xs', md: 'px-3 py-1 text-sm', }, }, + defaultVariants: { - variant: 'info', + variant: 'default', size: 'md', }, } -) +); export interface BadgeProps - extends React.HTMLAttributes, VariantProps { - label: string + extends React.HTMLAttributes, + VariantProps { + children?: React.ReactNode; + dot?: boolean; } -export function Badge({ label, variant, size, className, ...props }: BadgeProps) { +export function Badge({ + children, + variant, + size, + dot = false, + className, + ...props +}: BadgeProps) { + const dotSize = + size === 'sm' + ? 'w-1.5 h-1.5' + : 'w-2 h-2'; + return ( - - {label} + + {dot ? ( + + ) : ( + children + )} - ) -} + ); +} \ No newline at end of file