Skip to content

refactor: Replace clsx & tailwind-merge with clswind#27

Open
iubns wants to merge 3 commits intoui-layouts:mainfrom
iubns:main
Open

refactor: Replace clsx & tailwind-merge with clswind#27
iubns wants to merge 3 commits intoui-layouts:mainfrom
iubns:main

Conversation

@iubns
Copy link
Copy Markdown

@iubns iubns commented Mar 18, 2026

Summary

This PR simplifies the class merging utility by replacing the combination of clsx and tailwind-merge with the single clswind package.

Changes

  • Removed clsx and tailwind-merge dependencies.
  • Installed clswind as a replacement.
  • Updated utils.ts to re-export cn from clswind instead of the manual implementation.
  • Updated README.md and "Get Started" documentation to remove unnecessary utility setup instructions.

Benefits

  • Reduces the number of direct dependencies.
  • Simplifies the installation and setup process for users (improved Developer Experience).

Notes

The behavior of the cn utility remains identical, ensuring backward compatibility with all existing components.

Summary by CodeRabbit

  • Refactor

    • Switched to an external utility package for shared helpers, consolidating imports across the site.
  • Style

    • Minor formatting and string-quoting cleanups applied for consistency.
  • Documentation

    • Updated installation instructions and dependency list to reflect the new package.

@netlify
Copy link
Copy Markdown

netlify bot commented Mar 18, 2026

Deploy Preview for cursify-main ready!

Name Link
🔨 Latest commit d334aa4
🔍 Latest deploy log https://app.netlify.com/projects/cursify-main/deploys/69ba5d6dcfdd8000089f6968
😎 Deploy Preview https://deploy-preview-27--cursify-main.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify bot commented Mar 18, 2026

Deploy Preview for cursify ready!

Name Link
🔨 Latest commit d334aa4
🔍 Latest deploy log https://app.netlify.com/projects/cursify/deploys/69ba5d6d762b8b00081dee42
😎 Deploy Preview https://deploy-preview-27--cursify.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 18, 2026

📝 Walkthrough

Walkthrough

Migrates the project from a local cn utility (using clsx + tailwind-merge) to the external clswind package: updates imports across components, removes the local cn implementation, and adjusts package.json and docs/install instructions. Minor formatting and string-quote normalizations applied.

Changes

Cohort / File(s) Summary
Component imports (cn → clswind)
app/(docs-page)/components/[...slug]/page.tsx, components/website/code-components/*, components/website/ui/*, components/website/*, mdx-components.tsx, registry/components/cursor/common/magnetic-cursor.tsx, components/progressive-blur.tsx
Replaced imports of cn from local @/lib/utils (or ./lib/utils) with import { cn } from 'clswind'. Mostly identical usage preserved; several files include minor JSX/className/quoting reformatting.
Docs & README updates
README.md, app/(docs-page)/get-started/page.mdx
Updated installation instructions to npm install motion clswind; removed the example utils.ts snippet that showed cn implementation; author social link formatting adjusted; minor whitespace changes.
Package manifest
package.json
Removed clsx and tailwind-merge deps, added/replaced with clswind.
Local utility removal
lib/utils.ts
Removed exported cn(...inputs: ClassValue[]) and its imports (ClassValue, clsx, twMerge); retained other utilities (debounce, throttle, siteConfig).
Minor prop/type formatting
components/website/code-components/component-preview.tsx, components/progressive-blur.tsx
Small signature/typing and formatting tweaks (trailing comma in props destructure, HTMLMotionProps quoting change, gradient join spacing).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped from utils to clswind today,
Swapped merges and clsx on my merry way.
Imports aligned and docs trimmed neat,
A lighter bundle — my paws tap a beat. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: replacing clsx and tailwind-merge with clswind across the entire codebase.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

You can get early access to new features in CodeRabbit.

Enable the early_access setting to enable early access features such as new models, tools, and more.

Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/website/ui/spotlight.tsx`:
- Line 4: The import "import { cn } from 'clswind'" references a package that
doesn't exist on public registries; verify whether "clswind" is intended to be
an internal/monorepo module or a typo and update accordingly: if it's internal,
ensure the package is published/linked and that the build config (registry,
workspace, or path alias) exposes it; if it's a typo, replace the import with
the correct utility (e.g., the project's actual classnames helper) and update
usages of the "cn" symbol in this file to match; also update package.json to
point to the correct dependency or remove the invalid entry.

In `@package.json`:
- Line 33: The dependency "clswind" in package.json is unresolved; confirm
whether "clswind" is a private package or a typo and fix all imports that expect
a cn utility. If it's private, ensure your registry/build environment can
resolve "clswind" and update bun.lock; if it's a typo replace the dependency
with the correct package (e.g., "clsx" or "classnames") and update imports using
cn accordingly; if no external package exists, restore the local utility
implementation (export cn that wraps twMerge(clsx(...)) or equivalent) and
replace imports referencing cn so all files that import cn continue to work.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fd619c46-ade6-4e10-8082-6e793e4a6038

📥 Commits

Reviewing files that changed from the base of the PR and between 129f5a9 and 04f9d10.

📒 Files selected for processing (27)
  • README.md
  • app/(docs-page)/components/[...slug]/page.tsx
  • app/(docs-page)/get-started/page.mdx
  • components/website/code-components/component-code-preview.tsx
  • components/website/code-components/component-preview.tsx
  • components/website/code-components/copy-button.tsx
  • components/website/code-components/copy-npm-button.tsx
  • components/website/code-components/pre-code.tsx
  • components/website/code-components/pre-coded.tsx
  • components/website/dropdown-menu.tsx
  • components/website/footer.tsx
  • components/website/moibile-header.tsx
  • components/website/searchbar.tsx
  • components/website/theme-switch.tsx
  • components/website/ui/banner.tsx
  • components/website/ui/button.tsx
  • components/website/ui/dialog.tsx
  • components/website/ui/dropdown.tsx
  • components/website/ui/navigation-menu.tsx
  • components/website/ui/scroll-area.tsx
  • components/website/ui/spotlight.tsx
  • components/website/ui/tabs.tsx
  • components/website/vaul-sidebar.tsx
  • lib/utils.ts
  • mdx-components.tsx
  • package.json
  • registry/components/cursor/common/magnetic-cursor.tsx
💤 Files with no reviewable changes (1)
  • lib/utils.ts

'use client';

import { cn } from '@/lib/utils';
import { cn } from 'clswind';
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

For clswind (the version used in this PR), does it officially support import { cn } from 'clswind' in TypeScript/ESM, and does its merge behavior match clsx + tailwind-merge for conflicting Tailwind classes?

💡 Result:

No, clswind does not officially support import { cn } from 'clswind' in TypeScript/ESM, and its merge behavior cannot be confirmed to match clsx + tailwind-merge. No official package, documentation, or repository for a Tailwind class utility named "clswind" was found across npm, GitHub, or general web searches. Similar packages exist (e.g., classwind, colorwind, clb), but none match the exact name or described features with authoritative evidence.

Citations:


🏁 Script executed:

# First, confirm the actual import in the spotlight.tsx file
cat -n components/website/ui/spotlight.tsx | head -10

Repository: ui-layouts/cursify

Length of output: 274


🏁 Script executed:

# Check if clswind is in package.json
rg '"clswind"' package.json || echo "No clswind found in package.json"

Repository: ui-layouts/cursify

Length of output: 88


🏁 Script executed:

# Check lock files for clswind
rg 'clswind' package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null | head -20 || echo "No clswind in lock files"

Repository: ui-layouts/cursify

Length of output: 44


🏁 Script executed:

# Search for similar package names that might be alternatives
rg -i 'class|clsx|cn.*wind' package.json | grep -E '"[^"]*":'

Repository: ui-layouts/cursify

Length of output: 147


🏁 Script executed:

# Check if clswind is a local package in the repo
fd -type f 'clswind' . 2>/dev/null || echo "No local clswind directory"

Repository: ui-layouts/cursify

Length of output: 88


🏁 Script executed:

# Search for clswind in node_modules or any local implementation
rg 'export.*cn' --type ts --type js | grep -i clswind || echo "Searching for cn export"

Repository: ui-layouts/cursify

Length of output: 85


🏁 Script executed:

# Check package.json for clswind details (full entry)
cat -n package.json | grep -A2 -B2 'clswind'

Repository: ui-layouts/cursify

Length of output: 239


🏁 Script executed:

# Search for any clswind references throughout the codebase
rg 'clswind' --type ts --type tsx --type js

Repository: ui-layouts/cursify

Length of output: 89


🏁 Script executed:

# Search for clswind references more broadly
rg 'clswind' --no-type 2>/dev/null | head -30

Repository: ui-layouts/cursify

Length of output: 44


🏁 Script executed:

# Look at imports using cn from clswind across the codebase
rg 'from.*clswind' --no-type 2>/dev/null

Repository: ui-layouts/cursify

Length of output: 44


🏁 Script executed:

# Check if maybe it's a typo and should be something else (clsx, classnames, etc)
cat package.json | rg -A1 -B1 'class|clsx|cn'

Repository: ui-layouts/cursify

Length of output: 282


🏁 Script executed:

# Let's search more carefully - maybe it's a version mismatch
# Try to see what's actually imported
grep -r "import.*cn.*from" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" .

Repository: ui-layouts/cursify

Length of output: 50376


🏁 Script executed:

# Check if clswind might be under a different name or if there's a typo
# Look at the exact package.json structure around clswind
sed -n '25,40p' package.json

Repository: ui-layouts/cursify

Length of output: 596


Verify clswind is a legitimate npm package before merge.

Line 4 imports import { cn } from 'clswind', but clswind does not appear to exist on npm or any public package registry. The package is pinned to version ^26.12.3 in package.json, yet no official package matching this name or version could be found. If clswind is a private registry package or internal monorepo module, ensure it is properly configured for the build environment. Otherwise, this import will fail at runtime.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/website/ui/spotlight.tsx` at line 4, The import "import { cn }
from 'clswind'" references a package that doesn't exist on public registries;
verify whether "clswind" is intended to be an internal/monorepo module or a typo
and update accordingly: if it's internal, ensure the package is published/linked
and that the build config (registry, workspace, or path alias) exposes it; if
it's a typo, replace the import with the correct utility (e.g., the project's
actual classnames helper) and update usages of the "cn" symbol in this file to
match; also update package.json to point to the correct dependency or remove the
invalid entry.

Comment thread package.json
Copy link
Copy Markdown

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

🧹 Nitpick comments (1)
components/progressive-blur.tsx (1)

52-52: Trailing space in className string.

There's a trailing space at the end of the className string. While harmless, it's unnecessary.

✨ Suggested cleanup
-            className='pointer-events-none absolute inset-0 rounded-[inherit] '
+            className='pointer-events-none absolute inset-0 rounded-[inherit]'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/progressive-blur.tsx` at line 52, The className string in the
ProgressiveBlur component contains an unnecessary trailing space
("pointer-events-none absolute inset-0 rounded-[inherit] "), remove the trailing
space so the value becomes "pointer-events-none absolute inset-0
rounded-[inherit]" to clean up the markup; update the JSX element where
className is set (the element with className='pointer-events-none absolute
inset-0 rounded-[inherit] ') to use the trimmed string.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@components/progressive-blur.tsx`:
- Line 52: The className string in the ProgressiveBlur component contains an
unnecessary trailing space ("pointer-events-none absolute inset-0
rounded-[inherit] "), remove the trailing space so the value becomes
"pointer-events-none absolute inset-0 rounded-[inherit]" to clean up the markup;
update the JSX element where className is set (the element with
className='pointer-events-none absolute inset-0 rounded-[inherit] ') to use the
trimmed string.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c01db266-cd55-46f4-a369-cd5519838795

📥 Commits

Reviewing files that changed from the base of the PR and between 04f9d10 and d334aa4.

📒 Files selected for processing (1)
  • components/progressive-blur.tsx

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.

1 participant