Skip to content

Commit

Permalink
Merge pull request #22 from avo-hq/chore/update-readme
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianthedev authored Nov 13, 2024
2 parents f04e762 + 451b34d commit dc090ca
Showing 1 changed file with 209 additions and 11 deletions.
220 changes: 209 additions & 11 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,32 +38,34 @@ 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 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,
Expand All @@ -78,7 +80,7 @@ button_classes.render
button_classes.render(color: :red, size: :xl, icon: true)
```

### Compound Variants
## Compound Variants

```ruby
button_classes = ClassVariants.build(
Expand All @@ -100,6 +102,172 @@ 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"
```

## 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

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
<div>
<div class="<%= alert_classes.render(:head) %>">
Head of alert
</div>
<div class="<%= alert_classes.render(:body) %>">
Body of alert
</div>
</div>
```

## 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
Expand Down Expand Up @@ -135,6 +303,36 @@ 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.
Install the gem using `bundle add tailwind_merge` and use this configuration to enable it.

```ruby
ClassVariants.configure do |config|
config.process_classes_with do |classes|
TailwindMerge::Merger.new.merge(classes)
end
end
```

### Output

![](sample.jpg)
Expand Down

0 comments on commit dc090ca

Please sign in to comment.