Skip to content

Drop Tailwind for plain CSS modules - #624

Open
kcarnold wants to merge 1 commit into
mainfrom
chore/remove-tailwind
Open

Drop Tailwind for plain CSS modules#624
kcarnold wants to merge 1 commit into
mainfrom
chore/remove-tailwind

Conversation

@kcarnold

@kcarnold kcarnold commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Rebased onto main now that #621 and #623 have landed.

The app only ever used a thin layer of Tailwind utilities, mostly for layout and one-off colors. This ports the remaining ones to CSS modules alongside the styles they sit next to, and removes the toolchain.

Preflight is the load-bearing part

@import 'tailwindcss' brings in Tailwind's reset, and this app leans on it hard: nearly every CSS module assumes zeroed margin/padding/border and universal box-sizing: border-box, but only a handful declare box-sizing themselves. It also supplies font: inherit on form controls and a { color: inherit; text-decoration: inherit }. So preflight is vendored as src/preflight.css — verbatim, with --theme(--x, fallback) calls resolved to their fallbacks.

It stays in @layer base, where @import 'tailwindcss' put it. The layer matters as much as the contents: unlayered CSS beats layered CSS regardless of specificity, which is exactly what lets components/markdown/styles.module.css (from #621) put list markers and heading sizes back with a single class and no !important. Vendoring preflight unlayered would silently flip those contests. Verified @layer base survives into the emitted CSS.

Doc and comment updates

Four places attributed the reset to Tailwind. The mechanism they describe is unchanged — only the source moves, and @layer base still holds:

  • docs/markdown-rendering.md (intro + the preflight section)
  • frontend/CLAUDE.md
  • components/markdown/index.tsx
  • components/markdown/styles.module.css

editor/styles.css no longer exists, so references to it are gone too.

Build and dependency effects

  • 41 packages leave the lockfile, including the native @tailwindcss/oxide and lightningcss binaries for all 9 target platforms — the meaningful win for Docker build time and image size.
  • postcss.config.js collapses to reshaped's config, unwrapped.
  • eslint no longer references a tailwind.config.js that never existed here.

Also dropped as dead

Colors

Ported values are the v4 palette. Tailwind v4 ships colors in oklch, so v3 hex codes are wrong here — blue-300 is #8ec5ff, not #bfdbfe (that's blue-200), and blue-500, green-500 and red-600 all differ visibly. Values were converted from theme.css rather than transcribed, so this should be a pixel no-op and needs no snapshot regeneration.

Verified

npm run typecheck, npm run lint, npm test (239 passing), npm run format:check (unchanged at 5 pre-existing warnings), npm run build, and BUILD_TARGET=google-docs vite build.

🤖 Generated with Claude Code

Base automatically changed from chore/remove-dead-survey-code to main August 27, 2026 23:30
The app only ever used a thin layer of Tailwind utilities, mostly for
layout and one-off colors. This ports the remaining ones to CSS modules
alongside the styles they sit next to, and removes the toolchain.

Preflight is kept, vendored as `src/preflight.css` and left in
`@layer base` where `@import 'tailwindcss'` put it. All CSS modules here
are written against that reset -- universal `box-sizing: border-box`,
zeroed margin/padding/border, `font: inherit` on form controls, unstyled
links -- and only a handful declare `box-sizing` themselves. Removing
the import without keeping the reset would have restyled every page.

The layer matters as much as the contents: unlayered CSS beats layered
CSS regardless of specificity, which is what lets
`components/markdown/styles.module.css` put list markers and heading
sizes back with a single class and no `!important`. Vendoring preflight
unlayered would silently flip those contests.

The `@tailwindcss/typography` plugin is dropped outright: nothing ever
applied a `prose` class, so its `.prose` overrides in `taskpane.css`
were dead.

`editor/styles.css` had nothing left but the two Tailwind imports, so
`editor/index.tsx` now imports the reset directly.

Comments and docs that attributed the reset to Tailwind now point at
`src/preflight.css` -- the mechanism they describe is unchanged, and
`@layer base` still holds. Touches `docs/markdown-rendering.md`,
`frontend/CLAUDE.md`, and the two `components/markdown/` files.

Build/dependency effects:
- 41 packages leave the lockfile, including the native `@tailwindcss/
  oxide` and `lightningcss` binaries for all 9 target platforms.
- `postcss.config.js` is now just reshaped's config, unwrapped.
- eslint no longer references a `tailwind.config.js` that never existed.

Verified: typecheck, lint, 239 tests, and both `vite build` and
`BUILD_TARGET=google-docs vite build`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@kcarnold
kcarnold force-pushed the chore/remove-tailwind branch from 96159c8 to ff1e131 Compare August 27, 2026 23:38
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