Skip to content

Delegate smart_merge to the tailwind_merge gem#1

Merged
jeffdlange merged 1 commit into
mainfrom
delegate-smart-merge-to-tailwind-merge-gem
May 18, 2026
Merged

Delegate smart_merge to the tailwind_merge gem#1
jeffdlange merged 1 commit into
mainfrom
delegate-smart-merge-to-tailwind-merge-gem

Conversation

@jeffdlange

Copy link
Copy Markdown
Collaborator

Summary

Replaces the hand-rolled Tailwind conflict-resolution logic in smart_merge with a delegation to gjtorikian/tailwind_merge (the Ruby port of tailwind-merge). The public API is unchanged.

  • lib/view_component_css_dsl.rb: -165 lines net. Dropped SPACING_REGEX, SPACING_AXIS_MAP, BORDER_REGEX, CATEGORIES, KNOWN_MODIFIERS, MODIFIER_PATTERNS, plus spacing_info, detect_category, extract_modifier_prefix, known_modifier?. Added one module-level MERGER = TailwindMerge::Merger.new shared across the process.
  • view_component_css_dsl.gemspec: added tailwind_merge ~> 1.0 dependency.
  • CHANGELOG.md: noted under Changed (broader coverage) and Breaking (hidden semantics).
  • README.md: noted the delegation and added a JS-toggle visibility subsection pointing to the HTML5 hidden attribute pattern.
  • TODO.md: removed the resolved investigation item.

Why

  • Coverage: smart_merge only categorized ~14 utility groups. tailwind_merge covers every Tailwind utility group and tracks upstream Tailwind releases (1.5.0 ships TW 4.3 support, May 2026). Groups now correctly merged that weren't before: shadow-*, ring-*, gap-*, space-*, divide-*, z-*, opacity-*, leading-*, tracking-*, transition-*, scale-*, rotate-*, translate-*, blur-*, plus arbitrary-value negative spacing and stacked !important markers.
  • Parity confirmed: 16/16 spacing/border shorthand-vs-longhand cases produce identical output to the old logic (including responsive/state/stacked modifier prefixes).
  • Performance: measured 28–68× faster across realistic workloads (cache-miss path, repeated-input path, multi-arg form). The library's existing _css_cache/_css_merge_cache sit above this and continue to work unchanged.
  • Maintenance: stops reimplementing tailwind-merge from scratch every time a new utility group ships.

Breaking change

hidden is now treated as part of the display group, so "flex hidden" collapses to "hidden" (matching upstream tailwind-merge). The previous carve-out preserved both classes for JS-toggle patterns. The supported replacement is the HTML5 hidden attribute via the existing attribute DSL — :hidden is already in HTML_ATTR_KEYS, so callers can pass hidden: true or components can declare attribute hidden: -> { ... }. JS then toggles with element.toggleAttribute('hidden') instead of classList.toggle('hidden').

Test plan

  • bundle exec rspec — 139 examples, 0 failures (no spec changes needed)
  • bundle exec standardrb — clean
  • Direct parity test against old smart_merge on 40+ cases (spacing/border/modifiers/arbitrary/important/negative) — all spacing cases identical, all coverage-gap cases newly handled correctly
  • Forge audit (already done out-of-band): 3 sites rely on the old hidden carve-out and will be migrated separately after this lands

🤖 Generated with Claude Code

Drops the hand-rolled CATEGORIES/SPACING/modifier tables in favor of
gjtorikian/tailwind_merge, which mirrors tailwind-merge (JS) semantics
and tracks Tailwind utility groups upstream. The public API is unchanged
(smart_merge still takes a list of strings and returns a merged string),
but conflict resolution now covers every Tailwind utility group rather
than the subset previously encoded in CATEGORIES.

Breaking: `hidden` is now part of the display conflict group, so
`"flex hidden"` collapses to `"hidden"`. The previous carve-out was
non-standard; the recommended replacement for JS-toggle visibility is
the HTML5 `hidden` attribute via the existing `attribute` DSL.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jeffdlange jeffdlange merged commit 4ae59d1 into main May 18, 2026
5 checks passed
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