feat(ui): visual polish primitives + token additions (Phase A)
Adds the design tokens the polish PRs (10a-e) will draw from:
shadow-xs/sm/md/lg/glow, radius scale tuned to spec, gradient utilities,
spring/smooth eases, and fast/base/slow durations. Introduces
StatusPill, KPITile, and EmptyState primitives plus a polished
PageHeader variant ('gradient') with optional eyebrow + KPI sub-line —
existing PageHeader callers stay on the plain variant.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
55
src/components/ui/status-pill.tsx
Normal file
55
src/components/ui/status-pill.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
import * as React from 'react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
/**
|
||||
* Status pill — a single visual primitive for "this thing is in state X" across
|
||||
* documents, signers, reservations, interests. Replaces ad-hoc Badge variants
|
||||
* sprinkled through detail pages so the colour mapping stays consistent.
|
||||
*/
|
||||
const statusPillVariants = cva(
|
||||
'inline-flex items-center gap-1.5 rounded-md border px-2 py-0.5 text-xs font-medium transition-colors',
|
||||
{
|
||||
variants: {
|
||||
status: {
|
||||
// Document/signer lifecycle
|
||||
pending: 'border-slate-200 bg-slate-100 text-slate-700',
|
||||
sent: 'border-brand-100 bg-brand-50 text-brand-700',
|
||||
partial: 'border-teal-light bg-teal-light/40 text-teal-dark',
|
||||
signed: 'border-success-border bg-success-bg text-success',
|
||||
completed: 'border-success-border bg-success-bg text-success',
|
||||
expired: 'border-warning-border bg-warning-bg text-warning',
|
||||
rejected: 'border-error-border bg-error-bg text-error',
|
||||
cancelled: 'border-slate-300 bg-slate-200 text-slate-600',
|
||||
declined: 'border-error-border bg-error-bg text-error',
|
||||
// Reservation / interest lifecycle
|
||||
active: 'border-success-border bg-success-bg text-success',
|
||||
archived: 'border-slate-200 bg-slate-100 text-slate-500',
|
||||
// Delivered (non-signature docs in hub)
|
||||
delivered: 'border-purple-light bg-purple-light/40 text-purple-dark',
|
||||
draft: 'border-slate-200 bg-white text-slate-600',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
status: 'pending',
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
export type StatusPillStatus = NonNullable<VariantProps<typeof statusPillVariants>['status']>;
|
||||
|
||||
interface StatusPillProps
|
||||
extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof statusPillVariants> {
|
||||
/** Optional leading dot — useful for "in-progress" style indicators. */
|
||||
withDot?: boolean;
|
||||
}
|
||||
|
||||
export function StatusPill({ status, withDot, className, children, ...props }: StatusPillProps) {
|
||||
return (
|
||||
<span className={cn(statusPillVariants({ status }), className)} {...props}>
|
||||
{withDot ? <span className="h-1.5 w-1.5 rounded-full bg-current" aria-hidden /> : null}
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user