From 9b01c69fd93978aaa4235740c52dd7c2b284f27d Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Fri, 1 Nov 2024 11:48:52 +0200 Subject: [PATCH 1/4] chore: update readme for v1 --- readme.md | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 175 insertions(+), 8 deletions(-) diff --git a/readme.md b/readme.md index b4b5209..0e9d1e9 100644 --- a/readme.md +++ b/readme.md @@ -40,30 +40,34 @@ We create an object from the class or helper where we define the configuration u ## Example -Below we implement the [button component](https://tailwindui.com/components/application-ui/elements/buttons) from Tailwind UI. +Below we'll implement the [button component](https://tailwindui.com/components/application-ui/elements/buttons) from Tailwind UI. ```ruby # Define the variants and defaults button_classes = ClassVariants.build( base: "inline-flex items-center rounded border border-transparent font-medium text-white hover:text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2", variants: { + color: { + indigo: "bg-indigo-600 hover:bg-indigo-700 focus:ring-indigo-500", + red: "bg-red-600 hover:bg-red-700 focus:ring-red-500", + blue: "bg-blue-600 hover:bg-blue-700 focus:ring-blue-500", + }, size: { sm: "px-2.5 py-1.5 text-xs", md: "px-3 py-2 text-sm", lg: "px-4 py-2 text-sm", xl: "px-4 py-2 text-base", }, - color: { - indigo: "bg-indigo-600 hover:bg-indigo-700 focus:ring-indigo-500", - red: "bg-red-600 hover:bg-red-700 focus:ring-red-500", - blue: "bg-blue-600 hover:bg-blue-700 focus:ring-blue-500", - }, + compound_variants: [ + { color: :red, border: true, class: "border-red-800" }, + { color: :blue, border: true, class: "border-blue-800" } + ] # A variant whose value is a string will be expanded into a hash that looks # like { true => "classes" } - block: "w-full justify-center", + icon: "w-full justify-center", # Unless the key starts with !, in which case it will expand into # { false => "classes" } - "!block": "w-auto", + "!icon": "w-auto", }, defaults: { size: :md, @@ -100,6 +104,157 @@ button_classes.render(color: :red) # => "inline-flex items-center rounded bg-red button_classes.render(color: :red, border: true) # => "inline-flex items-center rounded bg-red-600 border border-red-600" ``` +TODO: tailwind merge + +## Block configurations + +You might have scenarios where you have more advanced conditionals and you'd like to configure the classes using the block notation. + +```ruby +alert_classes = ClassVariants.build do + # base + base "..." + + # variant + variant color: :red, class: "..." + + # compound variant + variant type: :button, color: :red, class: "..." + + # defaults + defaults color: :red, type: :button +end + +# usage +alert_classes.render(color: :red, type: :button) +``` + +## Slots + +You might have components which have multiple slots or places where you'd like to use conditional classes. +`class_variants` supports that through slots. + +```ruby +# Example + +alert_classes = ClassVariants.build do + # base with slots + base do + slot :head, class: "..." + slot :body, class: "..." + end + + # variant with slots + variant color: :red do + slot :head, class: "..." + slot :body, class: "..." + end + + # compound variant with slots + variant type: :button, color: :red do + slot :head, class: "..." + slot :body, class: "..." + end + + # set defaults + defaults color: :red, type: :button +end +``` + +```erb +
+
+ Head of alert +
+
+ Body of alert +
+
+``` + +## Full API + +```ruby +# Configuration +alert_classes = ClassVariants.build( + base: "...", + variants: { + color: { + red: "...", + black: "..." + }, + type: { + button: "...", + link: "..." + } + }, + compound_variants: [], + defaults: { + color: :red, + type: :button + } +) do + # base without slots + base "..." + + # base with slots + base do + slot :head, class: "..." + slot :body, class: "..." + end + + # variant without slots + variant color: :red, class: "..." + + # variant with slots + variant color: :red do + slot :head, class: "..." + slot :body, class: "..." + end + + # compound variant without slots + variant type: :button, color: :red, class: "..." + + # compound variant with slots + variant type: :button, color: :red do + slot :head, class: "..." + slot :body, class: "..." + end + + # option 1 (my favorite) + defaults color: :red, type: :button + + # option 2 + defaults do + color :red + type :button + end +end + +# Usage + +# renders the defaults +alert_classes.render + +# render default slot with custom variants +alert_classes.render(color: :red) + +# render slot with defaults variants +alert_classes.render(:body) + +# render slot with custom variants +alert_classes.render(:body, color: :red) + +# if slot not exist, throw error? return empty classes? +alert_classes.render(:non_existent_slot, color: :red) + +# render default slot with custom class (will be merged) +alert_classes.render(class: "...") + +# render slot with custom class (will be merged) +alert_classes.render(:body, class: "...") +``` + ## Use with Rails ```ruby @@ -135,6 +290,18 @@ end <%= link_to :Avo, "https://avohq.io", class: button_classes.render(color: :red, size: :xl) %> ``` +## TailwindMerge + +By default, the classes are merged using `concat`, but you can use the awesome [TailwindMerge](https://github.com/gjtorikian/tailwind_merge) gem. +Install the gem using `bundle add tailwind_merge` and use this configuration to enable it. + +```ruby +ClassVariants.configure do |config| + config.tw_merge = true # by default is false + config.tw_merge_config = {} # by default is nil +end +``` + ### Output ![](sample.jpg) From 4069e6d5e6f38c04228b79fc4dd277b832200990 Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Fri, 1 Nov 2024 11:55:09 +0200 Subject: [PATCH 2/4] wip --- readme.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/readme.md b/readme.md index 0e9d1e9..5fe01a9 100644 --- a/readme.md +++ b/readme.md @@ -38,8 +38,6 @@ We create an object from the class or helper where we define the configuration u 1. The `compound_variants` keyword argument where we declare the compound variants with their conditions and classes 1. The `defaults` keyword argument (optional) where we declare the default value for each variant. -## Example - Below we'll implement the [button component](https://tailwindui.com/components/application-ui/elements/buttons) from Tailwind UI. ```ruby @@ -82,7 +80,7 @@ button_classes.render button_classes.render(color: :red, size: :xl, icon: true) ``` -### Compound Variants +## Compound Variants ```ruby button_classes = ClassVariants.build( @@ -104,7 +102,22 @@ button_classes.render(color: :red) # => "inline-flex items-center rounded bg-red button_classes.render(color: :red, border: true) # => "inline-flex items-center rounded bg-red-600 border border-red-600" ``` -TODO: tailwind merge +## Override classes with `render` + +We can also override the builder classes in the `render` method. + +```ruby +button_classes = ClassVariants.build( + base: "inline-flex items-center rounded", + variants: { ... }, +) + +button_classes.render(color: :red, class: "block") +``` + +Now, the `block` class will be appended to the classes bus. + +If you're using the [`tailwind_merge`](#tailwind_merge) plugin it will override the `inline-flex` class. ## Block configurations @@ -290,7 +303,7 @@ end <%= link_to :Avo, "https://avohq.io", class: button_classes.render(color: :red, size: :xl) %> ``` -## TailwindMerge +## `tailwind_merge` By default, the classes are merged using `concat`, but you can use the awesome [TailwindMerge](https://github.com/gjtorikian/tailwind_merge) gem. Install the gem using `bundle add tailwind_merge` and use this configuration to enable it. From bd528218a166a9e8dc5370d4b793875cd6abac6e Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Fri, 1 Nov 2024 11:58:35 +0200 Subject: [PATCH 3/4] helper module --- readme.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/readme.md b/readme.md index 5fe01a9..b9682c7 100644 --- a/readme.md +++ b/readme.md @@ -303,6 +303,23 @@ end <%= link_to :Avo, "https://avohq.io", class: button_classes.render(color: :red, size: :xl) %> ``` +## Helper module + +If you're developing something more complex you might want to use composition more. You might want to use the helper module for that. + +```ruby +class MyClass + include ClassVariants::Helper + + class_variants { + base: {}, + variants: {} + } +end + +MyClass.new.class_variants(:container, color: :red, class: "shadow") +``` + ## `tailwind_merge` By default, the classes are merged using `concat`, but you can use the awesome [TailwindMerge](https://github.com/gjtorikian/tailwind_merge) gem. From 451b34dd7317c6720f832d9918adce60ec57622c Mon Sep 17 00:00:00 2001 From: Adrian Marin Date: Tue, 5 Nov 2024 11:37:37 +0200 Subject: [PATCH 4/4] Update TW merge config --- readme.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index b9682c7..d6c0722 100644 --- a/readme.md +++ b/readme.md @@ -327,8 +327,9 @@ Install the gem using `bundle add tailwind_merge` and use this configuration to ```ruby ClassVariants.configure do |config| - config.tw_merge = true # by default is false - config.tw_merge_config = {} # by default is nil + config.process_classes_with do |classes| + TailwindMerge::Merger.new.merge(classes) + end end ```