Skip to content

feat: consumer stylesheet override + warm professional default theme#16

Merged
ronaldtse merged 4 commits into
mainfrom
feat/custom-css-and-theme-revamp
Jul 18, 2026
Merged

feat: consumer stylesheet override + warm professional default theme#16
ronaldtse merged 4 commits into
mainfrom
feat/custom-css-and-theme-revamp

Conversation

@ronaldtse

Copy link
Copy Markdown
Contributor

Summary

Two related styling deliverables.

1. Consumer stylesheet override (bug fix)

The package gave consumers no way to inject their own CSS: with injectRoutes: true every layout comes from the package, so a consumer's override.css was dead code (tc184sc4's font overrides never loaded — reported as 'site lost its styling').

  • Integration detects theme.customCss (explicit path, resolved against the consumer root) or <root>/src/styles/override.css (convention) and exposes it as virtual:edoxen-custom-css (re-imported by absolute path, so the consumer's own CSS pipeline — Tailwind/PostCSS — applies; external @import URLs like webfonts stay).
  • BaseLayout imports it after base.css, so consumers win the cascade.
  • Build log line: Custom stylesheet: <path>.

2. Warm professional default theme

The default look was ~100 lines of bare globals. Full revamp:

  • styles/base.css rewritten (117 → ~600 lines): warm paper/charcoal design, serif display stack (system stacks only — no webfont dependency), accent-dash eyebrows, pill nav/badges/facet chips, soft-shadow hover-lift cards, booktabs tables, skip link, :focus-visible rings, prefers-reduced-motion, island styles centralized (also fixes the [lang] decisions page that lacked them), ink-safe print stylesheet. Only consumes --edoxen-* with fallbacks — config + override.css always win.
  • New default tokens (schema.ts, documented): warm bg #faf8f6, stone text #292524, deep warm teal accent #0f766e (4.9:1 AA on paper), radius 0.5rem; matching dark theme (warm charcoal, teal #2dd4bf).
  • Components polished (no class hooks renamed): pill badges, sticky-header tables, timeline dots/connectors, segmented locale tabs, editorial home recent-list. Five components (MeetingTimes/MinutesSection/StatementList/DeclarationList/ScheduleTable) rewritten from dead Tailwind utility classes (never compiled — no Tailwind pipeline) to scoped token-driven styles.
  • examples/standalone is now the full styling showcase (explicit light+dark sienna palette, radius, logos, nav/social/bodies, all features) with a commented src/styles/override.css reference (Fraunces webfont + token overrides + custom rule).
  • README theming section rewritten: default look, cascade, grouped token tables, override.css/customCss, dark mode, per-example matrix.

Verification

  • pnpm -F @edoxen/browser test: 112/112 · pnpm typecheck: clean · pnpm test:e2e: 21/21
  • examples/minimal + standalone build; standalone dist verified to contain sienna tokens, logo, Fraunces override + webfont import, and the CSS asset is linked from every page
  • Playwright screenshot review in light+dark, both examples, print emulation (2 real bugs found & fixed: print token specificity, dark chip contrast)

Changeset included (patch → 0.1.8).

…tion)

The package gave consumers no way to inject their own CSS: with
injectRoutes: true every layout comes from the package, so a
consumer's override.css was dead code (tc184sc4's font overrides
never loaded).

- integration detects theme.customCss (explicit, resolved against
  the consumer root) or <root>/src/styles/override.css (convention),
  and exposes it as virtual:edoxen-custom-css via the existing
  inline vite plugin (re-imported by absolute path so the consumer's
  CSS pipeline applies)
- BaseLayout imports it after base.css so consumers win the cascade
- logs 'Custom stylesheet: <path>' at build time

Verified in tc184sc4: DM Sans + font tokens now land in built pages.
Replace the bare ~100-line base stylesheet with a complete "elegant
professional warm" theme that stands on its own with no consumer CSS:

- warm paper canvas (#faf8f6), warm charcoal ink (stone), deep warm
  teal accent (#0f766e); dark theme is a warm charcoal (never
  blue-black) with a bright teal accent — all new defaults live in the
  theme schema and meet WCAG AA against their paired background
- serif display headings from system font stacks only (Iowan/Palatino/
  Georgia — no webfont dependency), tightened letter-spacing, accent
  dash eyebrow on section h2, overline dt labels, tabular numerals
- pill nav links with hover wash, muted multi-column footer, soft-
  tinted pill badges, cards with warm hairline + soft shadow + hover
  lift, booktabs-style tables (sticky header, row hover), dotted
  decade timeline, facet chips, styled search island (moved from the
  decisions page into base.css so [lang] routes get it too)
- MeetingTimes/MinutesSection/StatementList/DeclarationList/
  ScheduleTable rewritten from dead Tailwind utility classes (no
  Tailwind pipeline is wired) to scoped .edoxen-* token-driven styles
- visible :focus-visible rings, prefers-reduced-motion, skip link,
  ink-safe print stylesheet (tokens re-pointed so dark-mode visitors
  still print black-on-white; islands and chrome drop out)
- base.css only consumes --edoxen-* via var(--edoxen-x, fallback) and
  never re-declares consumer-settable tokens, so generateCssTokens
  and the consumer override stylesheet always win the cascade

tokens.ts needed no change (it holds no values; schema.ts owns the
defaults). Class hooks (.edoxen-header/__brand/__nav, .edoxen-main,
.edoxen-footer, .edoxen-decision-list*, search-filter, badges,
tables, urn-copy, theme-toggle, print styles) are unchanged.
- README Theming section rewritten: default-look description, cascade
  explanation (config tokens → base.css fallbacks → override.css),
  grouped token reference (colors, dark palette, typography, shape,
  customProperties hooks), override.css convention + theme.customCss,
  dark mode, and a per-example demonstration matrix
- examples/standalone is now the full theming showcase: explicit
  light+dark palette (warm sienna), radius, logo placeholders
  (public/logo.svg), nav, social, bodies with brand colors, feature
  flags, and a commented src/styles/override.css demonstrating the new
  consumer override mechanism (webfont import + token overrides + one
  custom rule)
- examples/minimal intentionally untouched: it demonstrates the new
  default theme with zero overrides
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant