Skip to content

Feat: cx function from clsx #285#286

Merged
github-actions[bot] merged 1 commit intomainfrom
cx-fn
Jan 11, 2026
Merged

Feat: cx function from clsx #285#286
github-actions[bot] merged 1 commit intomainfrom
cx-fn

Conversation

@black7375
Copy link
Contributor

@black7375 black7375 commented Jan 11, 2026

Description

clsx function to cx

Related Issue

Summary by CodeRabbit

  • New Features

    • Added a conditional class-name utility to the CSS package and exported it from the package entry point.
    • Added TypeScript types for ClassValue, ClassArray, and ClassDictionary to enable type-safe class composition.
  • Chores

    • Added the runtime dependency "clsx" to the CSS package.

✏️ Tip: You can customize this high-level summary in your review settings.

Additional context

Checklist

@changeset-bot
Copy link

changeset-bot bot commented Jan 11, 2026

⚠️ No Changeset found

Latest commit: d7cf9b5

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

@coderabbitai
Copy link

coderabbitai bot commented Jan 11, 2026

📝 Walkthrough

Walkthrough

Adds a clsx-based cx utility to the CSS package, with TypeScript types and exports, a package dependency, and embedded Vitest tests for the new module.

Changes

Cohort / File(s) Summary
Dependency Management
packages/css/package.json
Added runtime dependency clsx (^2.1.1).
Type Definitions
packages/css/src/classname/types.ts
Added ClassValue, ClassArray, and ClassDictionary type exports.
Core Implementation & Tests
packages/css/src/classname/cx.ts
New module re-exporting clsx as cx with JSDoc and embedded Vitest tests covering variadic, conditional, object, array, and mixed inputs.
Local Re-exports
packages/css/src/classname/index.ts
Re-exported cx and types (ClassValue, ClassArray, ClassDictionary).
Package Public API
packages/css/src/index.ts
Exposed cx and its types from package root.

Sequence Diagram(s)

(omitted — changes are local library additions without multi-component sequential interactions)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Poem

🐰 A little cx hops into the patch,

With clsx in paw and types to match,
It joins the bundle, neat and spry,
Tests all tidy — watch it fly! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is largely incomplete. While it includes the required template sections, most are empty or minimal. Only the Description section contains brief content ('clsx function to cx'), and Related Issue references #285. Additional context, checklist, and reviewer guidance are absent. Expand the description with details about what the cx function does, why it's being added, implementation notes, and checklist items for reviewers to evaluate.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a cx function based on clsx to the codebase, with reference to issue #285.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

Triggered from #286 by @​black7375.

Checking if we can fast forward main (236463b) to cx-fn (0209273).

Target branch (main):

commit 236463ba62ad15c5ebb0bda3dc89e9d1e36e4eff (HEAD -> main, origin/main)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Sat Oct 18 00:00:00 2025 +0900

    Fix: `theme` - composite value

Pull request (cx-fn):

commit 02092733b74affb4c920317ab8bfff59dd9ce239 (pull_request/cx-fn)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Sat Nov 22 00:00:00 2025 +0900

    Feat: `cx` function from clsx #285

Can't fast forward main (236463b) to cx-fn (0209273). main (236463b) is not a direct ancestor of cx-fn (0209273). Branches appear to have diverged at 1bb5010:

* 02092733b74affb4c920317ab8bfff59dd9ce239 Feat: `cx` function from clsx #285
| * 236463ba62ad15c5ebb0bda3dc89e9d1e36e4eff Fix: `theme` - composite value
| * 60c2a59bc5cd079ce5bf980b6cc397714bc2a09e Fix: Theme - `alias` value
| * 26546b1a08cecbbaba4a4895d09657bdc7e7a633 Chore: update eslint config as consist
|/  
* 1bb50106844d162d26f1f470ef0cae0565461708 Refactor: restrict `rules()` to function-style compoundVariants #245

commit 1bb50106844d162d26f1f470ef0cae0565461708
Author: JeongJun <rgfdds98@gmail.com>
Date:   Wed Oct 15 00:00:00 2025 +0900

    Refactor: restrict `rules()` to function-style compoundVariants #245

Rebase locally, and then force push to cx-fn.

@github-actions
Copy link
Contributor

Triggered from #286 by @​black7375.

Checking if we can fast forward main (236463b) to cx-fn (ecd8576).

Target branch (main):

commit 236463ba62ad15c5ebb0bda3dc89e9d1e36e4eff (HEAD -> main, origin/main)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Sat Oct 18 00:00:00 2025 +0900

    Fix: `theme` - composite value

Pull request (cx-fn):

commit ecd8576c32ccd2327072f662eecdd525a909b0f6 (pull_request/cx-fn)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Sat Nov 22 00:00:00 2025 +0900

    Feat: `cx` function from clsx #285

Can't fast forward main (236463b) to cx-fn (ecd8576). main (236463b) is not a direct ancestor of cx-fn (ecd8576). Branches appear to have diverged at 1bb5010:

* ecd8576c32ccd2327072f662eecdd525a909b0f6 Feat: `cx` function from clsx #285
| * 236463ba62ad15c5ebb0bda3dc89e9d1e36e4eff Fix: `theme` - composite value
| * 60c2a59bc5cd079ce5bf980b6cc397714bc2a09e Fix: Theme - `alias` value
| * 26546b1a08cecbbaba4a4895d09657bdc7e7a633 Chore: update eslint config as consist
|/  
* 1bb50106844d162d26f1f470ef0cae0565461708 Refactor: restrict `rules()` to function-style compoundVariants #245

commit 1bb50106844d162d26f1f470ef0cae0565461708
Author: JeongJun <rgfdds98@gmail.com>
Date:   Wed Oct 15 00:00:00 2025 +0900

    Refactor: restrict `rules()` to function-style compoundVariants #245

Rebase locally, and then force push to cx-fn.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @packages/css/src/classname/cx.ts:
- Around line 31-129: The test block opened by the conditional if
(import.meta.vitest) { in the cx tests is missing its closing brace; fix by
adding a matching } (and optional newline) at the end of the block to properly
terminate the if (import.meta.vitest) { ... } scope so the file parses and CI
passes.

In @packages/css/src/classname/types.ts:
- Around line 17-22: The doc/type mismatch: update the ClassDictionary type to
enforce boolean values by replacing export type ClassDictionary = Record<string,
unknown>; with export type ClassDictionary = Record<string, boolean>; and adjust
the JSDoc/example to reflect boolean conditions (e.g., { 'bg-blue-500': true,
'text-white': false }) so the type and comment are consistent; if you prefer to
allow truthy/falsy values instead, alternatively change the JSDoc wording to
“truthy/falsey conditions” rather than tightening the type.
🧹 Nitpick comments (1)
packages/css/src/classname/cx.ts (1)

31-129: Consider moving in-source tests to a *.test.ts file to avoid shipping them in library output.
The import.meta.vitest gate prevents execution, but the test code still tends to end up in published artifacts unless your build strips it.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 236463b and 0209273.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (5)
  • packages/css/package.json
  • packages/css/src/classname/cx.ts
  • packages/css/src/classname/index.ts
  • packages/css/src/classname/types.ts
  • packages/css/src/index.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-10-09T13:00:38.449Z
Learnt from: black7375
Repo: mincho-js/mincho PR: 113
File: packages/css/src/index.ts:33-33
Timestamp: 2024-10-09T13:00:38.449Z
Learning: `recipe` is properly exported from './rules' in `packages/css/src/rules/index.ts`.

Applied to files:

  • packages/css/src/index.ts
🪛 Biome (2.1.2)
packages/css/src/classname/cx.ts

[error] 129-129: expected } but instead the file ends

the file ends here

(parse)

🪛 GitHub Actions: CI
packages/css/src/classname/cx.ts

[error] 130-130: TypeScript error TS1005: '}' expected.

🔇 Additional comments (4)
packages/css/src/index.ts (1)

61-66: Public API export looks good; please ensure the build actually emits classname/index.{mjs,cjs,d.ts} as referenced.
Main risk is packaging/emit configuration, not TS syntax here.

packages/css/src/classname/index.ts (1)

1-3: Clean re-export surface for classname.

packages/css/src/classname/cx.ts (1)

1-30: No action needed on clsx import. The import { clsx } syntax is correct—clsx v2.1.1 exports both a default export and a named clsx export, properly typed for TypeScript.

Likely an incorrect or invalid review comment.

packages/css/package.json (1)

85-89: No issues found. The clsx v2.1.1 version is compatible with your ESM+CJS build setup. The codebase correctly uses the named import (import { clsx } from "clsx"), which is the recommended approach for v2 and works cleanly for both CommonJS and ES module consumers without requiring esModuleInterop. The package's exports map properly handles both output formats.

Comment on lines +17 to +22
/**
* Object with class names as keys and boolean conditions as values
* @example { 'bg-blue-500': true, 'text-white': isActive }
*/
export type ClassDictionary = Record<string, unknown>;

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Docs/type mismatch: ClassDictionary values aren’t necessarily boolean.
Either tighten the type to booleans (and maybe ClassValue) or adjust the doc to “truthy/falsey conditions”.

Proposed doc fix (minimal)
 /**
- * Object with class names as keys and boolean conditions as values
+ * Object with class names as keys and truthy/falsey conditions as values
  * @example { 'bg-blue-500': true, 'text-white': isActive }
  */
 export type ClassDictionary = Record<string, unknown>;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Object with class names as keys and boolean conditions as values
* @example { 'bg-blue-500': true, 'text-white': isActive }
*/
export type ClassDictionary = Record<string, unknown>;
/**
* Object with class names as keys and truthy/falsey conditions as values
* @example { 'bg-blue-500': true, 'text-white': isActive }
*/
export type ClassDictionary = Record<string, unknown>;
🤖 Prompt for AI Agents
In @packages/css/src/classname/types.ts around lines 17 - 22, The doc/type
mismatch: update the ClassDictionary type to enforce boolean values by replacing
export type ClassDictionary = Record<string, unknown>; with export type
ClassDictionary = Record<string, boolean>; and adjust the JSDoc/example to
reflect boolean conditions (e.g., { 'bg-blue-500': true, 'text-white': false })
so the type and comment are consistent; if you prefer to allow truthy/falsy
values instead, alternatively change the JSDoc wording to “truthy/falsey
conditions” rather than tightening the type.

@github-actions
Copy link
Contributor

Triggered from #286 by @​black7375.

Checking if we can fast forward main (236463b) to cx-fn (d7cf9b5).

Target branch (main):

commit 236463ba62ad15c5ebb0bda3dc89e9d1e36e4eff (HEAD -> main, origin/main)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Sat Oct 18 00:00:00 2025 +0900

    Fix: `theme` - composite value

Pull request (cx-fn):

commit d7cf9b54ceed3bbb251661ee542372082074e044 (pull_request/cx-fn)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Sat Nov 22 00:00:00 2025 +0900

    Feat: `cx` function from clsx #285

It is possible to fast forward main (236463b) to cx-fn (d7cf9b5). If you have write access to the target repository, you can add a comment with /fast-forward to fast forward main to cx-fn.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/css/src/classname/cx.ts (1)

3-28: Clarify "duplicates preserved" and add test coverage.

The JSDoc states that the function returns "merged class name string with duplicates preserved" (line 7). While technically accurate (clsx doesn't deduplicate), this phrasing may confuse readers about whether duplicate handling is intentional behavior.

Additionally, the test suite doesn't include a case that explicitly verifies duplicate preservation, such as:

expect(cx("foo", "foo", "bar")).toBe("foo foo bar");

Consider either:

  1. Clarifying the JSDoc to explicitly state that duplicates are not removed (e.g., "without deduplication")
  2. Adding a test case that demonstrates this behavior
📝 Suggested improvements

JSDoc clarification:

- * @returns Merged class name string with duplicates preserved
+ * @returns Merged class name string (duplicates are not removed)

Additional test case:

it("preserves duplicate class names", () => {
  expect(cx("foo", "foo", "bar")).toBe("foo foo bar");
  expect(cx("foo", { foo: true })).toBe("foo foo");
});
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ecd8576 and d7cf9b5.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (5)
  • packages/css/package.json
  • packages/css/src/classname/cx.ts
  • packages/css/src/classname/index.ts
  • packages/css/src/classname/types.ts
  • packages/css/src/index.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/css/src/index.ts
  • packages/css/src/classname/index.ts
  • packages/css/src/classname/types.ts
  • packages/css/package.json
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-12-03T11:16:32.528Z
Learnt from: black7375
Repo: mincho-js/mincho PR: 134
File: packages/transform-to-vanilla/src/transform.ts:49-51
Timestamp: 2024-12-03T11:16:32.528Z
Learning: In projects that target both CommonJS and ES modules, adjusting the TypeScript `module` option may not be feasible. Therefore, using `ts-ignore` comments to suppress TypeScript errors related to `import.meta` is acceptable.

Applied to files:

  • packages/css/src/classname/cx.ts
🧬 Code graph analysis (1)
packages/css/src/classname/cx.ts (2)
packages/css/src/classname/index.ts (1)
  • cx (1-1)
packages/css/src/index.ts (1)
  • cx (61-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: typecheck
🔇 Additional comments (3)
packages/css/src/classname/cx.ts (3)

29-29: Clean re-export pattern.

The re-export pattern export const cx = clsx; is idiomatic and will correctly inherit types from the clsx library. This approach keeps the API surface simple while maintaining full type safety.


31-130: Comprehensive test coverage with appropriate use of ts-ignore.

The test suite is thorough and well-structured:

  • Covers all major use cases (strings, objects, arrays, mixed inputs, edge cases)
  • Uses type assertions to verify type safety
  • Aligns with JSDoc examples for consistency
  • Employs describe.concurrent for efficient parallel execution

The @ts-ignore comments for import.meta.vitest are acceptable based on project learnings, as this is a known issue in dual CommonJS/ES module environments.

Based on learnings: Using ts-ignore comments for import.meta is acceptable in this project's build configuration.


1-1: The import of clsx is secure and appropriately versioned. Version 2.1.1 is the latest release with no known security vulnerabilities or compatibility concerns.

@black7375
Copy link
Contributor Author

/fast-forward

@github-actions
Copy link
Contributor

Triggered from #286 (comment) by @​black7375.

Trying to fast forward main (236463b) to cx-fn (d7cf9b5).

Target branch (main):

commit 236463ba62ad15c5ebb0bda3dc89e9d1e36e4eff (HEAD -> main, origin/main)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Sat Oct 18 00:00:00 2025 +0900

    Fix: `theme` - composite value

Pull request (cx-fn):

commit d7cf9b54ceed3bbb251661ee542372082074e044 (pull_request/cx-fn)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Sat Nov 22 00:00:00 2025 +0900

    Feat: `cx` function from clsx #285

Fast forwarding main (236463b) to cx-fn (d7cf9b5).

$ git push origin d7cf9b54ceed3bbb251661ee542372082074e044:main
To https://github.com/mincho-js/mincho.git
   236463b..d7cf9b5  d7cf9b54ceed3bbb251661ee542372082074e044 -> main

@github-actions github-actions bot merged commit d7cf9b5 into main Jan 11, 2026
11 of 12 checks passed
@github-actions github-actions bot deleted the cx-fn branch January 11, 2026 10:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant