feat: support conditional JSX expressions on className variants#44
feat: support conditional JSX expressions on className variants#44jrmybtlr wants to merge 5 commits into
Conversation
Transform conditional modifiers like className:hover={isActive ? 'a' : 'b'}
into prefixed className expressions, extract the resulting classes for the
Tailwind manifest, and merge multiple JSX class values safely with nested braces.
Co-authored-by: Jeremy Butler <jrmybtlr@users.noreply.github.com>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
useclassy-com | 8818fe8 | Commit Preview URL Branch Preview URL |
Jul 22 2026, 09:48 PM |
Add an interactive React demo for className:hover/{disabled} JSX
expressions, widen attribute typings for conditional values, and coerce
falsy interpolations when merging so `cond && 'class'` stays safe.
Co-authored-by: Jeremy Butler <jrmybtlr@users.noreply.github.com>
|
@copilot resolve the merge conflicts in this pull request |
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
Pull request overview
Adds React/JSX expression support for className:variant={...} / class:variant={...} so conditional variants are transformed and their prefixed Tailwind classes are extracted/manifested, aligning React behavior with existing quoted modifier support.
Changes:
- Extend class extraction/transform to rewrite string/template literals inside JSX expression-based modifier attributes (while leaving variable-only expressions untouched).
- Rewrite
mergeClassAttributesto use a balanced-brace scanner for JSX{...}values and preserve multiple dynamic class expressions (with falsy coercion to avoidfalsestringification). - Update docs + React demo (including TS typings) to showcase conditional variants.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/tests/core.test.ts | Adds/updates unit tests covering conditional modifier extraction/transform and multi-expression className merging behavior. |
| src/core.ts | Implements JSX expression modifier parsing/rewriting plus a more robust mergeClassAttributes parser for nested braces and multiple JSX class values. |
| README.md | Documents the new React conditional variant capability and provides input/output examples. |
| demos/react/src/react.d.ts | Widens demo typings for className:* / class:* attributes to permit conditional values (e.g., false). |
| demos/react/src/App.tsx | Adds an interactive “Conditional variants” demo showcasing ternary and && modifier expressions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…d method receivers - Implemented logic to prevent rewriting of comparison string operands and string method receivers within JSX expressions, ensuring they remain untouched during class attribute processing. - Added regression tests to verify that expressions like `status === 'active'` and `'primary'.includes(kind)` are correctly handled without modification. - Updated documentation to reflect changes in JSX conditional class rewrites.
Bring in security doc and Dependabot CI updates before final PR checks.
Summary
React variant attributes previously only accepted quoted strings (
className:hover="..."). Conditional forms likeclassName:hover={isActive ? 'bg-blue-500' : 'bg-gray-200'}were ignored entirely.This PR adds JSX expression support for
className:modifier={...}/class:modifier={...}:hover:…, including nested modifiers + partials)mergeClassAttributesnow uses a balanced-brace scanner so nested{…}(e.g.cn({ … })) merges correctly, and multiple JSX class values are preserved instead of dropping all but one(expr) || '') socond && 'class'does not stringifyfalseinto the class listExpressions with no string literals (e.g.
className:hover={hoverClasses}) are left unchanged so runtime variables are not corrupted.Demo
The React demo (
demos/react) now includes an interactive Conditional variants example:className:hover={isActive ? '…' : '…'}toggled by clickclassName:disabled={isDisabled && '…'}toggled by checkboxExample
Test plan
&&, nested modifiers, nested braces, variable-only left alone, multi-modifier merge)npm run build(library) succeedspnpm run buildincludeshover:bg-blue-500,hover:bg-zinc-700,disabled:opacity-40in CSS + manifest