Skip to content

ADR Styling and UI Framework

Vladimir Kromm edited this page Aug 27, 2026 · 5 revisions

status: implemented decided: 2026-08-26 decision: "Target state: Tailwind CSS + shadcn/ui (Radix-based). #117 lands the foundation; #118 migrates the rest against a written guideline." related_issues: [76, 117, 118, 54, 46]

ADR: Styling & UI Framework Approach

Status: Implemented Related: Architecture · Contributing-UI-Guidelines · GitHub #76 (this spike) · #117 (foundation) · #118 (compliance) · follow-up from #54 (Next.js migration) · part of #46

Context

The Next.js migration (#54) kept CSS Modules as-is to stay in scope, leaving styling and components undecided. Current state:

  • 15 *.module.css files (src/screens/, src/components/), all hand-written, no shared primitives.
  • No shared Button/Input/etc. layer — every screen builds its own controls.
  • ShareModal.tsx (a representative interactive component) has no focus trap, no Escape-to-close, no role="dialog"/aria-modal, and no focus return on close.
  • Codebase is expected to grow; migration cost compounds with every new component added under the old approach.

This ADR fixes one target state for styling and components, recorded operationally in Contributing-UI-Guidelines, so new work has a single direction instead of a per-change judgment call.

Options Considered

Styling

Criterion CSS Modules (status quo) Tailwind CSS Winner
Setup cost Built into Next.js, zero config Needs Tailwind config + PostCSS (one-time) CSS Modules
Cost to bring existing code to target state None — already written ~15 files rewritten as utility classes CSS Modules
shadcn/ui compatibility Not supported — shadcn ships Tailwind-styled components Native Tailwind
AI-assisted edit consistency Less represented in LLM training data Majority of AI-generated Next.js/React code in 2026 uses Tailwind Tailwind
Next.js ecosystem adoption, 2026 Minority choice for new projects Majority choice for new projects Tailwind
Bundle size at this project's scale Negligible Negligible Tie

Components

Criterion Hand-rolled (status quo) Radix UI (bare, unstyled) shadcn/ui Winner
Accessibility (focus trap, ARIA, keyboard nav) Missing — confirmed gap in ShareModal.tsx Correct out of the box Correct (built on Radix) Radix / shadcn
Shared Button/Input/Dialog set None exists None — each primitive hand-styled from scratch Ships pre-styled, copy-in shadcn/ui
Ownership / lock-in Full (all in-repo) Full (plain npm dependency) Full — components are copied into the repo, not installed as a black box Tie
Time to a working primitives layer N/A, not built Slow — style every primitive by hand Fast — CLI copies ready components shadcn/ui
Styling-system dependency None None (unstyled) Assumes Tailwind Radix, but moot — Tailwind already wins above

Decision

Tailwind CSS + shadcn/ui, shadcn's Radix-based components as the shared primitives layer (Button, Input, Select, Dialog, etc.).

  • Tailwind over CSS Modules: wins 3 of 5 non-tied criteria above, and is a hard prerequisite for shadcn/ui, which wins the components comparison outright.
  • shadcn/ui over bare Radix: same accessibility fix, but ships a real component set immediately instead of requiring every primitive to be hand-styled first.
  • Rollout, not a rewrite: #117 installs the tooling and pilots the pattern on ShareModal — the one component with a confirmed, concrete accessibility gap. #118 migrates the remaining CSS Modules and hand-rolled components against Contributing-UI-Guidelines as its own follow-up, not a single large rewrite.

Consequences

  • New UI work uses Tailwind + shadcn/ui — no new *.module.css files, no new hand-rolled interactive components.
  • ShareModal, UploadModal, and the remaining *.module.css files migrate via #117 (foundation + ShareModal pilot) and #118 (the rest).
  • Contributing-UI-Guidelines is the operational reference: when to use a shadcn primitive vs. custom composition, Tailwind conventions, design-token definitions.
  • CLAUDE.md's tech stack line changes from "CSS Modules" to "Tailwind CSS + shadcn/ui" once #117 and #118 land.

Sources / further reading

Researched August 2026: Tailwind vs CSS Modules tradeoffs (bundle size, DX, AI-tooling fit) and Radix UI vs shadcn/ui vs hand-rolled components for small Next.js projects, cross-referenced against this repo's actual CSS Module usage and the accessibility gap in ShareModal.tsx. Ecosystem-adoption claims move fast — re-verify against current sources before treating "majority choice" as settled fact.