refactor(ui): editorial monochrome design refresh (#473)
* refactor(ui): editorial monochrome design refresh Design-system layer only, no functional changes. Cascades app-wide from 8 files in the primitives + tokens layer. - Swap Fraunces → Hedvig Letters Serif for display typography (single-weight; drop font-medium from CardTitle and PageHeader) - Token sweep: pure white background, warm beige secondary (40 11% 89%), achromatic primary, calibrated 45 5% 85% border, halved-opacity shadows - Flatten Card: remove shadow, rounded-xl → rounded-lg, full-opacity border (was border-border/60) - Flatten Button: remove shadow-sm, remove active:scale-[0.98], drop outline border morph, transition-all 300ms → transition-colors 150ms - Soften Dialog overlay (bg-black/80 → bg-black/40 with dark variant) and use halved --shadow-md token on DialogContent - Sidebar: bg-card/90 → bg-background, full-opacity hairline border, warm-beige active state (bg-secondary), hover bg-secondary/60 - .hover-lift utility: replace translateY + box-shadow with flat background-color shift - PageHeader title: text-2xl font-medium → text-3xl md:text-4xl (no font-medium) - CLAUDE.md Brand & Aesthetic, Typography, and Forbidden Patterns sections rewritten to reflect new system Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(ui): address PR review - Remove dead .hover-lift utility (no callers; CLAUDE.md now bans hover-lift patterns, so leaving the class would contradict the docs) - Bump Dialog overlay bg-black/40 → bg-black/50 — gives a more perceptible separation layer over the new pure-white background while keeping the lighter editorial feel Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
2ed8096150
commit
ba45b8f661
@@ -188,7 +188,7 @@ export default function DashboardNav({ companyName: _companyName, entityType, un
|
||||
<>
|
||||
{/* Desktop sidebar */}
|
||||
<aside className="hidden md:fixed md:inset-y-0 md:flex md:w-64 md:flex-col">
|
||||
<div className="flex min-h-0 flex-1 flex-col border-r border-border/30 bg-card/90">
|
||||
<div className="flex min-h-0 flex-1 flex-col border-r border-border bg-background">
|
||||
<div className="flex flex-1 flex-col overflow-y-auto pt-7 pb-4">
|
||||
{/* Company switcher */}
|
||||
<div className="px-5 mb-8">
|
||||
@@ -235,8 +235,8 @@ export default function DashboardNav({ companyName: _companyName, entityType, un
|
||||
? cn(
|
||||
'transition-colors duration-150',
|
||||
active
|
||||
? 'bg-primary/12 text-foreground font-medium'
|
||||
: 'text-muted-foreground hover:text-foreground hover:bg-muted/40'
|
||||
? 'bg-secondary text-foreground font-medium'
|
||||
: 'text-muted-foreground hover:text-foreground hover:bg-secondary/60'
|
||||
)
|
||||
: 'text-muted-foreground/40 cursor-not-allowed'
|
||||
)
|
||||
@@ -306,8 +306,8 @@ export default function DashboardNav({ companyName: _companyName, entityType, un
|
||||
? cn(
|
||||
'transition-colors duration-150',
|
||||
active
|
||||
? 'bg-primary/12 text-foreground font-medium'
|
||||
: 'text-muted-foreground hover:text-foreground hover:bg-muted/40'
|
||||
? 'bg-secondary text-foreground font-medium'
|
||||
: 'text-muted-foreground hover:text-foreground hover:bg-secondary/60'
|
||||
)
|
||||
: 'text-muted-foreground/40 cursor-not-allowed'
|
||||
)
|
||||
@@ -364,8 +364,8 @@ export default function DashboardNav({ companyName: _companyName, entityType, un
|
||||
? cn(
|
||||
'transition-colors duration-150',
|
||||
active
|
||||
? 'bg-primary/12 text-foreground font-medium'
|
||||
: 'text-muted-foreground hover:text-foreground hover:bg-muted/40'
|
||||
? 'bg-secondary text-foreground font-medium'
|
||||
: 'text-muted-foreground hover:text-foreground hover:bg-secondary/60'
|
||||
)
|
||||
: 'text-muted-foreground/40 cursor-not-allowed'
|
||||
)
|
||||
@@ -403,8 +403,8 @@ export default function DashboardNav({ companyName: _companyName, entityType, un
|
||||
? cn(
|
||||
'transition-colors duration-150',
|
||||
active
|
||||
? 'bg-primary/12 text-foreground font-medium'
|
||||
: 'text-muted-foreground hover:text-foreground hover:bg-muted/40'
|
||||
? 'bg-secondary text-foreground font-medium'
|
||||
: 'text-muted-foreground hover:text-foreground hover:bg-secondary/60'
|
||||
)
|
||||
: 'text-muted-foreground/40 cursor-not-allowed'
|
||||
)
|
||||
@@ -430,7 +430,7 @@ export default function DashboardNav({ companyName: _companyName, entityType, un
|
||||
</div>
|
||||
|
||||
{/* Support + Logout */}
|
||||
<div className="flex-shrink-0 px-3 py-3 border-t border-border/30 space-y-1">
|
||||
<div className="flex-shrink-0 px-3 py-3 border-t border-border space-y-1">
|
||||
<div className="px-3 py-1.5">
|
||||
<SupportLink variant="muted" />
|
||||
</div>
|
||||
@@ -762,7 +762,7 @@ export default function DashboardNav({ companyName: _companyName, entityType, un
|
||||
</div>
|
||||
|
||||
{/* Support + Logout */}
|
||||
<div className="px-2 py-2 mt-1 border-t border-border/30 space-y-1">
|
||||
<div className="px-2 py-2 mt-1 border-t border-border space-y-1">
|
||||
<div className="px-3 py-2">
|
||||
<SupportLink variant="muted" />
|
||||
</div>
|
||||
|
||||
@@ -4,16 +4,16 @@ import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center whitespace-nowrap text-sm font-medium transition-all duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50",
|
||||
"inline-flex items-center justify-center whitespace-nowrap text-sm font-medium transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"bg-primary text-primary-foreground shadow-sm hover:bg-primary/80 active:scale-[0.98]",
|
||||
"bg-primary text-primary-foreground hover:bg-primary/90",
|
||||
destructive:
|
||||
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/80 active:scale-[0.98]",
|
||||
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||
outline:
|
||||
"border border-input bg-transparent hover:bg-secondary hover:border-secondary-foreground/20",
|
||||
"border border-input bg-transparent hover:bg-secondary",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground hover:bg-secondary/70",
|
||||
ghost:
|
||||
@@ -21,7 +21,7 @@ const buttonVariants = cva(
|
||||
link:
|
||||
"text-primary underline-offset-4 hover:underline",
|
||||
success:
|
||||
"bg-success text-success-foreground shadow-sm hover:bg-success/80 active:scale-[0.98]",
|
||||
"bg-success text-success-foreground hover:bg-success/90",
|
||||
},
|
||||
size: {
|
||||
default: "h-10 px-5 py-2 rounded-lg",
|
||||
|
||||
@@ -8,7 +8,7 @@ const Card = React.forwardRef<
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"rounded-xl border border-border/60 bg-card text-card-foreground shadow-[var(--shadow-sm)]",
|
||||
"rounded-lg border border-border bg-card text-card-foreground",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -35,7 +35,7 @@ const CardTitle = React.forwardRef<
|
||||
<h3
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"font-display text-xl font-medium leading-none tracking-tight",
|
||||
"font-display text-xl leading-none tracking-tight",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -20,7 +20,7 @@ const DialogOverlay = React.forwardRef<
|
||||
<DialogPrimitive.Overlay
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
"fixed inset-0 z-50 bg-black/50 dark:bg-black/60 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -37,7 +37,7 @@ const DialogContent = React.forwardRef<
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 max-h-[calc(100dvh-2rem)] overflow-y-auto data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-[var(--shadow-md)] duration-200 max-h-[calc(100dvh-2rem)] overflow-y-auto data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -10,7 +10,7 @@ export function PageHeader({ title, description, action }: PageHeaderProps) {
|
||||
return (
|
||||
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between mb-8">
|
||||
<div>
|
||||
<h1 className="font-display text-2xl font-medium tracking-tight">{title}</h1>
|
||||
<h1 className="font-display text-3xl md:text-4xl tracking-tight">{title}</h1>
|
||||
{description && (
|
||||
<p className="text-muted-foreground mt-1 text-balance">{description}</p>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user