Skip to content

feat: support conditional JSX expressions on className variants#44

Open
jrmybtlr wants to merge 5 commits into
mainfrom
cursor/jsx-conditional-variants-1ea7
Open

feat: support conditional JSX expressions on className variants#44
jrmybtlr wants to merge 5 commits into
mainfrom
cursor/jsx-conditional-variants-1ea7

Conversation

@jrmybtlr

@jrmybtlr jrmybtlr commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

React variant attributes previously only accepted quoted strings (className:hover="..."). Conditional forms like className:hover={isActive ? 'bg-blue-500' : 'bg-gray-200'} were ignored entirely.

This PR adds JSX expression support for className:modifier={...} / class:modifier={...}:

  • String / static template literals inside the expression are rewritten with the variant prefix (hover:…, including nested modifiers + partials)
  • Prefixed classes are extracted into the Tailwind manifest
  • mergeClassAttributes now 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
  • Falsy interpolations are coerced ((expr) || '') so cond && 'class' does not stringify false into the class list

Expressions 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 click
  • className:disabled={isDisabled && '…'} toggled by checkbox
  • Attribute typings widened to allow conditional values

Example

// Input
<button
  className="px-4 py-2"
  className:hover={isActive ? 'bg-blue-500' : 'bg-gray-200'}
/>

// Output
<button
  className={`px-4 py-2 ${(isActive ? 'hover:bg-blue-500' : 'hover:bg-gray-200') || ''}`}
/>

Test plan

  • Unit tests for extract / transform / merge of conditional modifiers (ternary, &&, nested modifiers, nested braces, variable-only left alone, multi-modifier merge)
  • Existing suite green: 190 tests passed
  • npm run build (library) succeeds
  • React demo pnpm run build includes hover:bg-blue-500, hover:bg-zinc-700, disabled:opacity-40 in CSS + manifest
Open in Web Open in Cursor 

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>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 17, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

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>
@jrmybtlr

Copy link
Copy Markdown
Owner Author

@copilot resolve the merge conflicts in this pull request

Copilot AI commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved in 8964962 by merging origin/main into this branch and fixing all merge conflicts in README.md, src/core.ts, src/tests/core.test.ts, and removing tasks/todo.md per main.

@jrmybtlr
jrmybtlr marked this pull request as ready for review July 20, 2026 22:39
@cursor

cursor Bot commented Jul 20, 2026

Copy link
Copy Markdown

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 mergeClassAttributes to use a balanced-brace scanner for JSX {...} values and preserve multiple dynamic class expressions (with falsy coercion to avoid false stringification).
  • 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.

Comment thread src/core.ts Outdated
Comment thread src/core.ts
jrmybtlr added 2 commits July 21, 2026 19:34
…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.
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.

4 participants