Skip to content

feat: Tailwind CSS v4 migration (rocketicons + ignition + nativewind v4)#150

Merged
programad merged 8 commits into
developfrom
feat/tailwind-v4
May 8, 2026
Merged

feat: Tailwind CSS v4 migration (rocketicons + ignition + nativewind v4)#150
programad merged 8 commits into
developfrom
feat/tailwind-v4

Conversation

@programad
Copy link
Copy Markdown
Contributor

Summary

Brings the @rocketicons/tailwind plugin, the ignition docs site, and the React Native side over to the Tailwind v4 / NativeWind v4 ecosystem.

  • @rocketicons/tailwind: upgraded plugin to TW v4 (CSS-first @plugin, @theme, @custom-variant model). Adds full prefix support documentation and comprehensive plugin test coverage (57 tests across index.test.ts, config-handler.test.ts, styles-generator.test.ts).
  • NativeWind: bumped v2 → v4.2.2 across the workspace; added a fresh Expo native-test app exercising the v4 runtime with the icons plugin so we don't regress the React Native path.
  • packages/core: index.native.tsx adjusted for NativeWind v4 className handling.
  • ignition: migrated to Tailwind v4 (CSS-first config in globals.css, dropped tailwind.config.ts, moved component styles into @layer components, dark variant via @custom-variant) and to Next.js 15 async params API across all route handlers and pages.
  • Bug fixes from the migration:
    • fix(ignition): restore TW v4 dark mode and sticky header — unlayered html, body { background-color: ... } was beating Tailwind utilities under v4's layer system, so <body> rendered white in dark mode (header looked gray over it, docs felt "light"); plus var(--spacing-N) no longer exists in v4 → .content-area lost its height cap → page scrolled and the lg:static header scrolled away. Wrapped base CSS in @layer base, switched to calc(var(--spacing) * N), capped .modal-context at viewport height on lg, added lg:min-h-0 down the flex chain so the cap propagates.
    • chore: add root dev scripts proxying to ignition workspace — convenience so npm run dev works from the repo root.

This is the v4-readiness branch we want on develop so the next developmain PR can publish a new rocketicons release with TW v4 support to npm.

Commits (8)

  • feat(tailwind): upgrade @rocketicons/tailwind plugin to Tailwind CSS v4
  • docs(tailwind): add TW v4 prefix support documentation
  • test(tailwind): add comprehensive test coverage for TW v4 plugin
  • feat: upgrade NativeWind v2→v4.2.2 + add native test Expo app
  • fix(native-test): add NativeWind type augmentation + agent commit policy
  • feat: migrate ignition to Tailwind CSS v4 + Next.js 15 async params
  • fix(ignition): restore TW v4 dark mode and sticky header
  • chore: add root dev scripts proxying to ignition workspace

Test plan

  • npm run test-all passes (verified locally and via the pre-push hook on the last two commits — 22 utils tests + 57 tailwind plugin tests + ignition/cli green)
  • Ignition dev server: dark/light/system theme toggle, <body> resolves to slate-900 in dark, sticky header on both /en/ and /en/docs/getting-started/ (verified via Playwright with computed-style assertions)
  • @rocketicons/tailwind plugin produces correct utilities for both web (TW v4) and native (NativeWind v4) targets
  • CI prepare-release / preview deploy runs cleanly (will be exercised by the merge into develop)

programad and others added 8 commits March 13, 2026 11:45
- Upgrade tailwindcss dependency from 3.4.1 to 4.2.1
- Add @tailwindcss/postcss as devDependency
- Replace config() API with theme() API for TW v4 PluginAPI
- Remove @rocketclimb/tw-utils dependency (sanitize inlined)
- Remove prefix interpolation (TW v4 handles prefixes via CSS)
- Infer PluginAPI type from createPlugin Parameters<>
- Rewrite integration tests to use @tailwindcss/postcss + @plugin
- Update config-handler test mocks for theme() API

BREAKING CHANGE: Plugin now requires tailwindcss >=4.0.0
TW v4 handles prefix automatically for addComponents() output.
Users configure prefix via @import 'tailwindcss' prefix(xp);
and the engine automatically prefixes generated selectors.
No manual prefix handling needed in plugin code.
Integration tests (22):
- Default class: inline-block, padding, .icon-ri scoping
- Size classes: test.each for all 11 sizes (xs through 7xl)
- Variants: outlined/filled with stroke/fill CSS rules
- Colors: sky-500 default color
- Safelisted: icon-default always present without content
- CSS structure: no unresolved @apply, proper @layer, clean output

Config-handler edge cases (10 new):
- Empty, null, string-only colors
- DEFAULT color handling
- No baseStyle, no variants
- Auto-500 shade selection and first-shade fallback
- Whitespace sanitization
- Compound color-size splitting (sky-500-base)

Styles-generator edge cases (8 new):
- Chaining, class merging, ordering
- Custom class prefix
- Native mode: prop merging, base classes, variant skipping

Test count: 14 → 57 (4x increase)
- Upgrade nativewind from 2.0.11 to 4.2.2 (stable, TW v4 compat)
- Update icons peerDeps: nativewind >=4, tailwindcss >=4
- Remove @rocketclimb/tw-utils from root and icons dependencies
- Add packages/native-test Expo app for native icon verification
  - NativeWind v4.2.2 + TW v4 + rocketicons showcase
  - Test page: 11 sizes, variants, colors, dark mode toggle
  - iOS only (macOS dev team), isolated from root workspaces
Three v4 migration regressions in ignition:

- Unlayered html/body bg rule was beating @layer utilities, so
  `bg-background dark:bg-background-dark` on <body> was overridden
  by `background-color: var(--color-white)` even when <html>.dark
  was set — body rendered white in dark mode, header (slate-900/0.7)
  looked gray over it, docs content area looked light. Wrap base
  styles in @layer base.
- `var(--spacing-16)` is undefined in v4 (only `--spacing` is
  exposed); the invalid calc dropped `.content-area` height, so the
  page scrolled instead of the inner container, and the lg:static
  header scrolled away. Switched to `calc(var(--spacing) * 16)`.
- `.modal-context` had `min-h: 100vh` (a floor), so on the home
  page the wrapper grew past viewport and the page scrolled.
  Cap at `height: 100vh` on lg:, and add `lg:min-h-0` down the
  flex chain so the cap propagates to the overflow-y-auto child.

Also dropped ~180 lines of duplicate component definitions that
were already inside @layer components above.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@programad programad merged commit d8fbef2 into develop May 8, 2026
1 check passed
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