Support custom class merging logic #893
Replies: 2 comments
-
|
This is what I'm currently doing... Simple button component: class Components::Button < Components::Base
DISABLED_CLASSES = "opacity-75 hover:opacity-75 cursor-not-allowed pointer-events-none".freeze
BASE_CLASSES = "flex gap-2 justify-center items-center text-center hover:opacity-90"
def view_template(&)
button(**merge_attributes(type: :button), &)
end
def all_classes = [
BASE_CLASSES,
(DISABLED_CLASSES if @attributes[:disabled] == true)
].compact
# Pull this code up to your base class so other components can use it:
TAILWIND_MERGER = ::TailwindMerge::Merger.new.freeze unless defined?(TAILWIND_MERGER)
def merge_attributes(**default_attributes)
attrs = mix({class: all_classes}.merge(default_attributes), @attributes)
attrs[:class] = TAILWIND_MERGER.merge(attrs[:class])
attrs
end
endNow you can do render Components::Button.new { "test" }
# <button class="flex gap-2 justify-center items-center text-center hover:opacity-90" type="button">test</button>
render Components::Button.new(class: "extra-class") { "test" }
# <button class="flex gap-2 justify-center items-center text-center hover:opacity-90 extra-class" type="button">test</button>
render Components::Button.new(class: "hover:opacity-70 gap-3 extra-class") { "test" }
# <button class="flex justify-center items-center text-center hover:opacity-70 gap-3 extra-class" type="button">test</button>
render Components::Button.new(class: "gap-3 extra-class", type: :submit, data_foo: "bar") { "test" }
# <button class="flex justify-center items-center text-center hover:opacity-90 gap-3 extra-class" type="submit" data-foo="bar">test</button>
render Components::Button.new(disabled: true) { "test" }
# <button class="flex gap-2 justify-center items-center text-center opacity-75 hover:opacity-75 cursor-not-allowed pointer-events-none" type="button" disabled>test</button>Tailwind merge can do its thing, you can pass in default attributes and override them, etc. |
Beta Was this translation helpful? Give feedback.
-
|
Sorry I never replied to the original question. The short answer is yes technically but "not really". You could technically define each HTML element again and have each of them call Defining a separate function to transform the attributes before they are passed to Phlex is the best option for now. If I may, though, I'd like to suggest an alternative to merging CSS classes that I think might serve you better in the long run. If you define a utility for your button like this. @utility button {
:where(&) {
@apply flex gap-2 justify-center items-center text-center hover:opacity-90;
}
:where(&.--disabled) {
@apply flex gap-2 justify-center items-center text-center hover:opacity-90;
}
}You can use it in your HTML like this. def view_template
button(class: ["button", ("--disabled" if @disabled), @class])
endBecause it’s a Tailwind utility, the CSS will only be generated if you actually use the I like to use the I like using Tailwind has three layers: @layer components {
.button {
@apply flex gap-2 justify-center items-center text-center hover:opacity-90;
&.--disabled {
@apply text-red-500;
}
}
}With this approach — especially with the utility — we have all the advantages of Tailwind.
But because we gave |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
The gem https://github.com/avo-hq/class_variants supports custom class merging logic (e.g. using the
tailwind_mergegem)Is there a way to achieve the same with phlex? So that I could run
TailwindMerge::Merger.new.merge(classes)on all inputs that get passed to an HTML element withclass:?Beta Was this translation helpful? Give feedback.
All reactions