Skip to content

feat(module): add theme.unstyled option#6551

Draft
benjamincanac wants to merge 1 commit into
v4from
feat/theme-unstyled
Draft

feat(module): add theme.unstyled option#6551
benjamincanac wants to merge 1 commit into
v4from
feat/theme-unstyled

Conversation

@benjamincanac
Copy link
Copy Markdown
Member

🔗 Linked issue

Resolves #6169
Part of #4953

❓ Type of change

  • 📖 Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

Adds a build-time theme.unstyled option (next to transitions / prefix) that strips Nuxt UI's default theme classes from components.

Users have repeatedly asked to drop the default classes, either to bring their own design system on top of the components' logic/a11y, or to cut the HTML/bundle bloat (#6169 calls out both). Today that's impossible: app.config.ui and :ui only ever merge onto the defaults (tailwind-variants extend concatenates, twMerge only drops conflicting utilities), so non-conflicting defaults always survive.

This is solved at the Nuxt UI layer with a theme transform rather than in tailwind-variants:

  • One optiontheme.unstyled?: boolean in module.ts (default false).
  • One utilapplyUnstyled in src/utils/theme.ts blanks every leaf class in slots / variants / compoundVariants while keeping all keys, so slots stay callable and color / size / variant props still validate.
  • One transform — added as the third step in the existing applyDefaultVariantsapplyPrefixToObject chain in templates.ts (prod + dev paths).
  • Zero component changes — every component reads its theme from #build/ui/*, which is now blank, so empty slots mean no class strings in the JS bundle or the HTML. app.config.ui.* then merges cleanly onto empty slots, with no tailwind-merge fighting.

Shared by both the Nuxt module and the Vue/Vite plugin (same getTemplates pipeline).

Warning

unstyled strips structural classes too (positioning, transitions, flex/grid), not just cosmetic ones. Layout-heavy components like Modal, Drawer or Calendar need the user to re-supply layout, same model as PrimeVue's unstyled mode. This is documented.

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

Add a build-time `theme.unstyled` option that blanks every leaf class in
component themes before they're written to `#build/ui/*`. Components keep
their structure, slots and variant props (color/size/variant still validate),
but render with only the classes supplied via `class`, `ui` or `app.config.ui`.

Implemented as a third theme transform (`applyUnstyled`) in the existing
`applyDefaultVariants` -> `applyPrefixToObject` chain, so it requires zero
component changes and removes the default class strings from both the JS
bundle and the rendered HTML. Shared by the Nuxt module and the Vue/Vite plugin.
@github-actions github-actions Bot added the v4 #4488 label Jun 3, 2026
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jun 3, 2026

npm i https://pkg.pr.new/@nuxt/ui@6551

commit: a430997

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v4 #4488

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cant override styles

1 participant