Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements compound variants #8

Merged
merged 1 commit into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions lib/class_variants/instance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ class ClassVariants::Instance
attr_reader :variants
attr_reader :defaults

def initialize(classes = "", variants: {}, defaults: {})
def initialize(classes = "", variants: {}, compoundVariants: [], defaults: {})
@classes = classes
@variants = expand_boolean_variants(variants)
@compoundVariants = compoundVariants
@defaults = defaults
end

Expand All @@ -14,11 +15,18 @@ def render(**overrides)
result = [@classes]

# Then merge the passed in overrides on top of the defaults
@defaults.merge(overrides)
.each do |variant_type, variant|
# dig the classes out and add them to the result
result << @variants.dig(variant_type, variant)
selected = @defaults.merge(overrides)

selected.each do |variant_type, variant|
# dig the classes out and add them to the result
result << @variants.dig(variant_type, variant)
end

@compoundVariants.each do |compound_variant|
if (compound_variant.keys - [:class]).all? { |key| selected[key] == compound_variant[key] }
result << compound_variant[:class]
end
end

# Compact out any nil values we may have dug up
result.compact!
Expand Down
25 changes: 24 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ $ gem install class_variants

## Usage

We create an object from the class or helper where we define the configuration using three arguments:
We create an object from the class or helper where we define the configuration using four arguments:

1. The default classes that should be applied to each variant
1. The `variants` keyword argument where we declare the variants with their option and classes
1. The `compoundVariants` 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
Expand Down Expand Up @@ -77,6 +78,28 @@ button_classes.render
button_classes.render(color: :red, size: :xl, icon: true)
```

### Compound Variants

```ruby
button_classes = ClassVariants.build(
"inline-flex items-center rounded",
variants: {
color: {
red: "bg-red-600",
blue: "bg-blue-600",
},
border: "border"
},
compoundVariants: [
{ color: :red, border: true, class: "border-red-800" },
{ color: :blue, border: true, class: "border-blue-800" }
]
)

button_classes.render(color: :red) # => "inline-flex items-center rounded bg-red-600"
button_classes.render(color: :red, border: true) # => "inline-flex items-center rounded bg-red-600 border border-red-600"
```

## Use with Rails

```ruby
Expand Down
16 changes: 16 additions & 0 deletions test/class_variants_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ def setup
red: "text-red",
green: "text-green"
},
ring: "focus:ring-2",
visible: "inline-block",
"!visible": "hidden"
},
compoundVariants: [
{ ring: true, color: :red, class: "focus:ring-red-600" },
{ ring: true, color: :green, class: "focus:ring-green-600" }
],
defaults: {
size: :md
}
Expand All @@ -38,4 +43,15 @@ def test_boolean_variants
assert_equal "rounded border text-md inline-block", @cv.render(visible: true)
assert_equal "rounded border text-md hidden", @cv.render(visible: false)
end

def test_compound_variants
assert_equal(
"rounded border text-md focus:ring-2 text-red focus:ring-red-600",
@cv.render(ring: true, color: :red)
)
assert_equal(
"rounded border text-md focus:ring-2 text-green focus:ring-green-600",
@cv.render(ring: true, color: :green)
)
end
end