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:
Jakob Wennberg
2026-05-13 23:01:53 +02:00
committed by GitHub
co-authored by Claude Opus 4.7
parent 2ed8096150
commit ba45b8f661
8 changed files with 63 additions and 71 deletions
+22 -37
View File
@@ -11,35 +11,35 @@
:root {
color-scheme: light;
/* Grayscale Chrome Palette */
/* Grayscale Chrome Palette — paper white + warm beige */
--background: 0 0% 97%;
--background: 0 0% 100%;
--foreground: 0 0% 9%;
--card: 0 0% 99%;
--card: 0 0% 100%;
--card-foreground: 0 0% 9%;
--popover: 0 0% 99%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 9%;
--primary: 210 5% 25%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 100%;
--secondary: 0 0% 94%;
--secondary: 40 11% 89%; /* Warm beige paper chip */
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 92%;
--muted: 40 8% 93%;
--muted-foreground: 0 0% 40%;
--accent: 0 0% 92%;
--accent: 40 8% 93%;
--accent-foreground: 0 0% 9%;
--destructive: 6 36% 48%; /* Muted terracotta */
--destructive-foreground: 0 0% 100%;
--border: 0 0% 90%;
--input: 0 0% 90%;
--ring: 210 5% 25%;
--border: 45 5% 85%;
--input: 45 5% 85%;
--ring: 0 0% 9%;
/* Radius */
--radius: 0.5rem;
@@ -61,13 +61,13 @@
--chart-4: 0 0% 50%;
/* Custom tokens */
--font-display: var(--font-fraunces), Georgia, serif;
--font-display: var(--font-hedvig-serif), Georgia, serif;
--font-body: var(--font-geist-sans), system-ui, sans-serif;
/* Shadows — cool-toned */
--shadow-sm: 0 1px 3px rgba(15, 23, 42, 0.06), 0 1px 2px rgba(15, 23, 42, 0.04);
--shadow-md: 0 4px 12px rgba(15, 23, 42, 0.06);
--shadow-lg: 0 12px 40px rgba(15, 23, 42, 0.08);
/* Shadows — barely-there; chrome relies on hairline borders */
--shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.03), 0 1px 1px rgba(15, 23, 42, 0.02);
--shadow-md: 0 4px 12px rgba(15, 23, 42, 0.03);
--shadow-lg: 0 12px 40px rgba(15, 23, 42, 0.05);
/* Animation */
--ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94);
@@ -83,13 +83,13 @@
--background: 0 0% 7%;
--foreground: 0 0% 87%;
--card: 0 0% 10%;
--card: 0 0% 11%;
--card-foreground: 0 0% 87%;
--popover: 0 0% 10%;
--popover: 0 0% 11%;
--popover-foreground: 0 0% 87%;
--primary: 210 4% 82%;
--primary: 0 0% 87%;
--primary-foreground: 0 0% 7%;
--secondary: 0 0% 14%;
@@ -104,9 +104,9 @@
--destructive: 6 32% 56%;
--destructive-foreground: 0 0% 100%;
--border: 0 0% 18%;
--input: 0 0% 18%;
--ring: 210 4% 82%;
--border: 45 4% 18%;
--input: 45 4% 18%;
--ring: 0 0% 87%;
--success: 155 22% 48%;
--success-foreground: 0 0% 100%;
@@ -278,17 +278,6 @@ h1, h2, h3 {
animation: scaleIn var(--duration-base) var(--ease-out);
}
/* Refined hover effects */
.hover-lift {
transition: transform var(--duration-fast) var(--ease-out),
box-shadow var(--duration-fast) var(--ease-out);
}
.hover-lift:hover {
transform: translateY(-1px);
box-shadow: var(--shadow-md);
}
/* Soft focus states */
.focus-ring:focus-visible {
outline: none;
@@ -357,8 +346,4 @@ input[type="number"] {
animation: none;
opacity: 1;
}
.hover-lift:hover {
transform: none;
}
}
+5 -4
View File
@@ -1,6 +1,6 @@
import type { Metadata, Viewport } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import { Fraunces } from "next/font/google";
import { Hedvig_Letters_Serif } from "next/font/google";
import Script from "next/script";
import { Toaster } from "@/components/ui/toaster";
import { ThemeProvider } from "@/components/theme-provider";
@@ -23,10 +23,11 @@ const geistMono = Geist_Mono({
subsets: ["latin"],
});
const fraunces = Fraunces({
variable: "--font-fraunces",
const hedvigSerif = Hedvig_Letters_Serif({
variable: "--font-hedvig-serif",
subsets: ["latin"],
display: "swap",
weight: "400",
});
export function generateMetadata(): Metadata {
@@ -59,7 +60,7 @@ export default function RootLayout({
}>) {
const branding = getBranding();
return (
<html lang="sv" translate="no" suppressHydrationWarning className={`${geistSans.variable} ${geistMono.variable} ${fraunces.variable}`}>
<html lang="sv" translate="no" suppressHydrationWarning className={`${geistSans.variable} ${geistMono.variable} ${hedvigSerif.variable}`}>
<head>
<meta name="google" content="notranslate" />
<link rel="apple-touch-icon" href={branding.appleTouchIconPath} />