feat(ui): update Button, Input, Tabs with Warm Precision interaction system

Button: 50ms transitions, accent focus ring at 2px offset, active
brightness darkening, no opacity-based disabled, border-accent hover
on outline variant, gap-1.5 for icon+text, radius-control (4px)

Input: bg-panel surface, border-default, radius-control, 50ms border
transition, accent focus outline at 2px offset, text-xs, no opacity
disabled

Tabs: accent bottom-border + accent-soft wash on active, text-xs,
50ms transitions, text-secondary inactive with hover to primary

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jason Staack
2026-03-21 13:34:36 -05:00
parent 8a77e69aa9
commit 0ee4416077
3 changed files with 9 additions and 9 deletions

View File

@@ -4,17 +4,17 @@ import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const buttonVariants = cva( const buttonVariants = cva(
'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50', 'inline-flex items-center justify-center gap-1.5 whitespace-nowrap font-medium transition-[background-color,border-color,color] duration-[50ms] ease-linear focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2 disabled:pointer-events-none disabled:text-text-muted disabled:border-border-subtle',
{ {
variants: { variants: {
variant: { variant: {
default: 'bg-[hsl(var(--accent-soft))] text-accent hover:bg-accent/20', default: 'bg-accent text-background active:brightness-90 rounded-[var(--radius-control)]',
solid: 'bg-accent text-white hover:bg-accent', solid: 'bg-accent text-background active:brightness-90 rounded-[var(--radius-control)]',
destructive: 'bg-error/15 text-error hover:bg-error/20', destructive: 'bg-error/15 text-error hover:bg-error/20 active:bg-error/25 rounded-[var(--radius-control)]',
outline: outline:
'border border-border bg-transparent text-text-secondary hover:bg-elevated hover:text-text-primary', 'border border-border-default bg-transparent text-text-secondary hover:border-accent active:bg-elevated rounded-[var(--radius-control)]',
secondary: 'bg-elevated text-text-secondary hover:text-text-primary', secondary: 'bg-elevated text-text-secondary hover:text-text-primary active:brightness-95 rounded-[var(--radius-control)]',
ghost: 'text-text-secondary hover:bg-elevated hover:text-text-primary', ghost: 'text-text-secondary hover:bg-elevated hover:text-text-primary active:bg-elevated rounded-[var(--radius-control)]',
link: 'text-accent underline-offset-4 hover:underline', link: 'text-accent underline-offset-4 hover:underline',
}, },
size: { size: {

View File

@@ -9,7 +9,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<input <input
type={type} type={type}
className={cn( className={cn(
'flex h-8 w-full rounded-md border border-border bg-elevated/50 px-3 py-1 text-sm text-text-primary placeholder:text-text-muted transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium focus:border-accent focus:outline-none disabled:cursor-not-allowed disabled:opacity-50', 'flex h-8 w-full rounded-[var(--radius-control)] border border-border-default bg-panel px-2.5 py-1.5 text-xs text-text-primary placeholder:text-text-muted transition-[border-color] duration-[50ms] ease-linear file:border-0 file:bg-transparent file:text-xs file:font-medium focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2 disabled:cursor-not-allowed disabled:text-text-muted disabled:border-border-subtle',
className, className,
)} )}
ref={ref} ref={ref}

View File

@@ -26,7 +26,7 @@ const TabsTrigger = React.forwardRef<
<TabsPrimitive.Trigger <TabsPrimitive.Trigger
ref={ref} ref={ref}
className={cn( className={cn(
'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium transition-all focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-[hsl(var(--accent-soft))] data-[state=active]:text-accent data-[state=active]:font-semibold data-[state=inactive]:text-text-muted data-[state=inactive]:hover:text-text-secondary', 'inline-flex items-center justify-center whitespace-nowrap px-3 py-1.5 text-xs font-medium transition-[background-color,border-color,color] duration-[50ms] ease-linear focus-visible:outline-none disabled:pointer-events-none disabled:text-text-muted data-[state=active]:border-b-2 data-[state=active]:border-accent data-[state=active]:text-text-primary data-[state=active]:font-medium data-[state=active]:bg-accent-soft/50 data-[state=inactive]:text-text-secondary data-[state=inactive]:hover:text-text-primary',
className, className,
)} )}
{...props} {...props}