Skip to content

Add cn utility for Tailwind class management#397

Open
mohammad-hussein-dev wants to merge 2 commits into
widgetify-app:mainfrom
mohammad-hussein-dev:feat/add-cn-utility
Open

Add cn utility for Tailwind class management#397
mohammad-hussein-dev wants to merge 2 commits into
widgetify-app:mainfrom
mohammad-hussein-dev:feat/add-cn-utility

Conversation

@mohammad-hussein-dev

Copy link
Copy Markdown

(I've reviewed the contributing guidelines and followed them.)

✨ Add cn utility for conflict-free Tailwind class management

🎯 What

Introduces a robust cn() utility function and refactors three components to use it.

Utility: src/utils/cn.ts — combines clsx + tailwind-merge
Components refactored: Button, Checkbox, Chip
Test coverage: 17 tests, 100% coverage (lines, branches, functions, statements)

🤔 Why

Manual class concatenation (${a} ${b} ${c}) breaks silently when Tailwind utilities conflict:

  • p-4 p-2 → only p-4 takes effect (silent failure)
  • text-red-500 text-blue-500 → unpredictable results

tailwind-merge resolves conflicts deterministically (last wins). clsx removes boilerplate.

✅ What's Changed

  1. New utility (src/utils/cn.ts): 15 lines, fully documented with TSDoc
  2. Refactored components: Button, Checkbox, Chip — cleaner class composition
  3. Unit tests (src/utils/__tests__/cn.test.ts): 17 tests covering edge cases
  4. CI/CD (.github/workflows/cn-utility.yml): Biome lint, TypeScript check, vitest, build

🧪 Testing

All 17 tests pass with 100% coverage:

  • ✓ Basic merging (strings, conditionals, objects, arrays)
  • ✓ Falsy values (undefined, null, false dropped correctly)
  • ✓ Tailwind conflicts (padding, colors resolved last-wins)
  • ✓ Edge cases (nested arrays, mixed types, ordering)

Run locally:

bunx vitest run --coverage

📚 Documentation

  • TSDoc in cn.ts: @param, @returns, @example tags for IDE IntelliSense
  • Inline comments in refactored components explain state-based styling
  • README: See /src/utils/cn.ts for usage examples

🔄 Backward Compatibility

✓ No breaking changes — components render identically to before
✓ Gradual adoption possible — other components can use cn() in follow-up PRs
✓ Optional — classNameOverrides still work perfectly

Closes

Closes #127

FEATURES:
- Add cn.ts: combines clsx + tailwind-merge for conflict-free class merging
- Refactor Button, Checkbox, Chip components to use cn() utility
- Comprehensive unit tests (17 tests, 100% coverage)
- TSDoc documentation with @param, @returns, @example tags
- GitHub Actions CI/CD workflow (lint, type-check, test, build)

TECHNICAL DETAILS:
- Uses clsx for conditional class composition
- Uses tailwind-merge for intelligent Tailwind class conflict resolution
- Supports strings, arrays, objects, and falsy values
- Memoized Checkbox component to prevent unnecessary re-renders
- Full TypeScript support with ClassValue type exports

TESTING:
- Unit tests cover: basic merging, conditional classes, falsy values
- Tailwind conflict resolution tested across padding, colors, complex scenarios
- Edge cases: deeply nested arrays, mixed input types, class ordering
- v8 coverage tool: 100% lines, branches, functions, statements

CI/CD:
- Biome linting and formatting
- TypeScript type checking (tsc --noEmit)
- Vitest with coverage reporting
- WXT extension build validation

Closes widgetify-app#127
@mohammad-hussein-dev

Copy link
Copy Markdown
Author

Hi @sajjadmrx, this PR is ready for review whenever you have time.
It addresses #127 by adding a cn utility and refactoring three components as a demonstration.
All tests pass with 100% coverage, and I've kept the changes minimal as requested.

Let me know if you'd like any adjustments. Thanks!

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.

[Development]: Add a TailwindCSS Class Merger Utility

1 participant