Skip to content

chore: upgrade Tailwind CSS from v3 to v4#308

Merged
SimplicityGuy merged 8 commits intomainfrom
chore/tailwind-v4
Apr 16, 2026
Merged

chore: upgrade Tailwind CSS from v3 to v4#308
SimplicityGuy merged 8 commits intomainfrom
chore/tailwind-v4

Conversation

@SimplicityGuy
Copy link
Copy Markdown
Owner

Summary

  • Upgrade Tailwind CSS from v3 to v4 across dashboard and explore services
  • Adopt v4-native CSS-first configuration (@import, @plugin, @source, @theme, @utility)
  • Switch CLI package from `tailwindcss` to `@tailwindcss/cli`
  • Fix two real bugs surfaced during migration

What changed

v3 → v4 patterns

v3 v4
`tailwind.config.js` (deleted) `@theme`/`@plugin`/`@source` in CSS
`@tailwind base/components/utilities` `@import "tailwindcss"`
`require("@tailwindcss/forms")` `@plugin "@tailwindcss/forms"`
`content: [...]` `@source "..."`
`theme.extend.colors` `@theme { --color-*: ... }`
`@layer components { .btn-base { @apply ... } }` `@utility btn-base { @apply ... }`
`tailwindcss@^3` `@tailwindcss/cli@^4`

Bugs fixed

  1. dashboard/Dockerfile — `admin.html`/`admin.js` were referenced as `@source` (and previously in v3's `content` array) but never copied into the `css-builder` stage. Pre-existing bug — silently dropped any Tailwind classes used exclusively in admin files.
  2. explore/tailwind.input.css — In v4, classes defined in `@layer components` cannot be `@apply`'d from other classes. Switched all 14 button/badge/spinner/form classes to `@utility` so `.btn-primary` can compose `.btn-base`.

Files

  • `dashboard/tailwind.input.css` — v4 CSS-first format
  • `dashboard/tailwind.config.js` — deleted
  • `dashboard/Dockerfile` — v4 CLI + admin file copy fix
  • `explore/tailwind.input.css` — v4 CSS-first format with `@theme` colors and `@utility` components
  • `explore/tailwind.config.js` — deleted
  • `explore/Dockerfile` — v4 CLI
  • `docs/dockerfile-standards.md` — updated example
  • `.gitignore` — added `explore/static/tailwind.css`

Test plan

  • `docker build -f dashboard/Dockerfile .` succeeds (Tailwind v4.2.2 generates 32KB CSS)
  • `docker build -f explore/Dockerfile .` succeeds (generates 36KB CSS, `btn-primary` correctly inlines `btn-base` styles)
  • All pre-commit hooks pass
  • Visual smoke test: bring up dashboard at :8003 and verify form inputs, buttons, and admin tab render correctly
  • Visual smoke test: bring up explore at :8006 and verify primary/outline buttons, badges, spinner, and form inputs render correctly with the design system colors

Notes

  • v4 requires browsers: Safari 16.4+, Chrome 111+, Firefox 128+
  • The CSS-variable indirection pattern (`--color-cyan-500: var(--cyan-500)`) is preserved exactly from v3 — runtime theming via `styles.css` continues to work

Replace tailwind.config.js with @import/@plugin/@source directives in
tailwind.input.css. The JS config is no longer needed.
Switch from tailwindcss@^3 to @tailwindcss/cli@^4. Remove --config flag
since configuration is now in the CSS input file.
The tailwind.input.css @source directives reference admin.html and
admin.js, but they were not being copied into the css-builder stage.
This pre-existing gap (the v3 tailwind.config.js content array listed
all four files but only two were copied) caused any Tailwind utility
classes used exclusively in admin.* files to be omitted from the
generated stylesheet.
Replace tailwind.config.js with @import/@plugin/@source/@theme directives
in tailwind.input.css. Custom colors move from theme.extend.colors to
@theme { --color-*: ... } block. Component layer classes unchanged.
Switch from tailwindcss@^3 to @tailwindcss/cli@^4. Remove --config flag
since configuration is now in the CSS input file.
Update docs/dockerfile-standards.md CSS builder example to reflect the
Tailwind v4 CLI invocation. Add explore/static/tailwind.css to .gitignore
so the generated stylesheet (built only inside Docker) is not accidentally
committed if a developer runs the CLI locally.
In Tailwind v4, classes defined in @layer components cannot be applied
via @apply from other classes. The build failed with "Cannot apply
unknown utility class 'btn-base'" when trying to compose .btn-primary
from .btn-base.

Switching all 14 component classes to v4's new @Utility directive lets
them participate in @apply composition. The generated CSS correctly
inlines the base styles into each variant (verified: btn-primary in the
output contains the full inline-flex/padding/transition cascade from
btn-base).
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions
Copy link
Copy Markdown
Contributor

E2E Coverage (firefox)

Totals Coverage
Statements: 46.5% ( 1241 / 2669 )
Lines: 46.5% ( 1241 / 2669 )

StandWithUkraine

@github-actions
Copy link
Copy Markdown
Contributor

E2E Coverage (chromium)

Totals Coverage
Statements: 46.5% ( 1241 / 2669 )
Lines: 46.5% ( 1241 / 2669 )

StandWithUkraine

@github-actions
Copy link
Copy Markdown
Contributor

E2E Coverage (webkit)

Totals Coverage
Statements: 46.5% ( 1241 / 2669 )
Lines: 46.5% ( 1241 / 2669 )

StandWithUkraine

@github-actions
Copy link
Copy Markdown
Contributor

E2E Coverage (webkit - iPhone 15)

Totals Coverage
Statements: 46.5% ( 1241 / 2669 )
Lines: 46.5% ( 1241 / 2669 )

StandWithUkraine

@github-actions
Copy link
Copy Markdown
Contributor

E2E Coverage (webkit - iPad Pro 11)

Totals Coverage
Statements: 46.5% ( 1241 / 2669 )
Lines: 46.5% ( 1241 / 2669 )

StandWithUkraine

@SimplicityGuy SimplicityGuy merged commit a464b9c into main Apr 16, 2026
57 checks passed
@SimplicityGuy SimplicityGuy deleted the chore/tailwind-v4 branch April 16, 2026 03:24
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