Skip to content

feat(ui): add raw mode theme that strips decorative CSS#8039

Open
nikosdouvlis wants to merge 5 commits intonk/sandbox-preset-selectorfrom
nk/raw-mode-theme
Open

feat(ui): add raw mode theme that strips decorative CSS#8039
nikosdouvlis wants to merge 5 commits intonk/sandbox-preset-selectorfrom
nk/raw-mode-theme

Conversation

@nikosdouvlis
Copy link
Member

Summary

When LLMs or developers want to fully custom-style Clerk components to match a brand, the default theme's decorative CSS (shadows, transitions, gradients, border-radius) gets in the way. Every style needs an "UNDO" override before the desired style can be applied.

Raw mode strips all decorative CSS from component variants, defaultStyles, and sx props, leaving only structural layout properties (display, flex, grid, padding, margin, gap, position, etc). This gives a clean canvas where you only write what you WANT, not what you want + what you need to undo.

  • stripDecorativeStyles utility with a structural property allowlist
  • preserveContentRendering option for background-image/mask properties needed for icon rendering
  • Raw theme sets simpleStyles: true to skip the baseTheme layer and __internal_rawMode: true to trigger stripping
  • Grid template properties are stripped (users re-add layout via elements API)
  • 5 demo presets (modernSaas, darkPremium, darkPremiumDefault, terminalRaw, terminalDefault) wired into the sandbox preset selector

Key finding from the demo presets: raw mode is better for radical designs (terminal theme: ~160 lines, 0 UNDO overrides vs ~220 lines, ~30 UNDO overrides on default). Default theme is better for color-swap theming (10 variables + 3 element overrides vs ~40 element overrides on raw).

Depends on #8038.

Test plan

  • Verify raw theme renders SignIn with no decorative styles
  • Verify icons (checkmarks, social provider logos, arrows) still render correctly
  • Select each demo preset from the sandbox dropdown, verify they render correctly
  • Compare terminalRaw vs terminalDefault presets side by side

Add a "raw" theme that strips all decorative CSS (colors, shadows,
borders, fonts, transitions) from component variants while keeping
structural CSS (layout, flex, grid, position, sizing). This gives
components a plain-HTML feel as a blank canvas for custom styling
via the elements API.

Key changes:
- stripDecorativeStyles utility with structural property allowlist
- rawMode flag propagated through appearance context and theme
- createVariants strips variant output in raw mode
- makeCustomizable strips defaultStyles and sx (preserving icon content)
- Dev mode overlay hidden in raw mode
- Sandbox: theme selector, Tailwind toggle, initial theme loading fix
Most variable values are irrelevant in raw mode because
stripDecorativeStyles removes the CSS properties that consume them.
Only colorForeground and colorPrimaryForeground matter because they
feed CSS custom properties (--cl-icon-fill) that survive stripping
for masked provider icons.
Remove 'grid' from structural prefixes so gridTemplateColumns and
gridTemplateRows are stripped. This simplifies the OAuth button
grid (5+4 columns -> single column stack) and other grid layouts
into plain flowing content. Safe because Collapsible unmounts
content directly when animations:false (which raw mode sets).
LLMs can re-add grid templates via the elements API.
Replace broad prefix matching (background*, mask*) with an exact
property set for content-rendering preservation. This prevents
decorative properties like backgroundClip or backgroundOrigin from
leaking through while still preserving backgroundImage, maskImage,
and backgroundColor (needed for masked icon fills).

Re-add colorBackground and colorInput as transparent to raw theme
since backgroundColor survives stripping via the preserve set.
Why:
Need demo presets to compare raw mode vs default theme styling side
by side and document the friction points of each approach.

What changed:
- 5 presets: modernSaas (light, raw), darkPremium (dark, raw),
  darkPremiumDefault (dark, default), terminalRaw (CRT, raw),
  terminalDefault (CRT, default)
- Wire presets into the sandbox preset selector
- Inline friction log documenting element key discoverability,
  CSS bleed, and comparison metrics
@changeset-bot
Copy link

changeset-bot bot commented Mar 11, 2026

⚠️ No Changeset found

Latest commit: 654ed15

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Mar 11, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Mar 11, 2026 0:03am

Request Review

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant