diff --git a/README.md b/README.md index b89eb90..54c0db5 100644 --- a/README.md +++ b/README.md @@ -282,6 +282,32 @@ class ButtonComponent < ViewComponent::Base end ``` +### Dependent (or compound) styles + +Sometimes it might be necessary to define complex styling rules, e.g., when a combination of variants requires adding additional styles. That's where usage of Ruby blocks for configuration becomes useful. For example: + +```ruby +style do + variants { + size { + sm { "text-sm" } + md { "text-base" } + lg { "px-4 py-3 text-lg" } + } + theme { + primary do |size:, **| + %w[bg-blue-500 text-white].tap do + _1 << "uppercase" if size == :lg + end + end + secondary { %w[bg-purple-500 text-white] } + } + } +end +``` + +The specified variants are passed as block arguments, so you can implement dynamic styling. + ### Using with TailwindCSS LSP To make completions (and other LSP features) work with our DSL, try the following configuration: diff --git a/lib/view_component_contrib/style_variants.rb b/lib/view_component_contrib/style_variants.rb index 839511d..e559b1c 100644 --- a/lib/view_component_contrib/style_variants.rb +++ b/lib/view_component_contrib/style_variants.rb @@ -96,7 +96,7 @@ def compile(**variants) @defaults.merge(variants.compact).each do |variant, value| variant = @variants.dig(variant, value) || next - styles = variant.is_a?(::Proc) ? variant.call : variant + styles = variant.is_a?(::Proc) ? variant.call(**variants) : variant acc.concat(Array(styles)) end diff --git a/test/cases/style_variants_test.rb b/test/cases/style_variants_test.rb index 162f2a2..c97340a 100644 --- a/test/cases/style_variants_test.rb +++ b/test/cases/style_variants_test.rb @@ -94,6 +94,27 @@ class DiffStyleSubcomponent < Component end end + class CompoundComponent < Component + style do + variants { + size { + sm { %w[text-sm] } + md { %w[text-md] } + lg { %w[text-lg] } + } + theme { + primary do |size:, **| + %w[primary-color primary-bg].tap do + _1 << "uppercase" if size == :lg + end + end + + secondary { %w[secondary-color secondary-bg] } + } + } + end + end + def test_render_variants component = Component.new @@ -153,4 +174,18 @@ def test_style_config_inheritance assert_css "div.text-white.font-md" end + + def test_dynamic_variants + component = CompoundComponent.new + + render_inline(component) + + assert_css "div.primary-color.primary-bg.text-md" + + component = CompoundComponent.new(theme: :primary, size: :lg) + + render_inline(component) + + assert_css "div.primary-color.primary-bg.text-lg.uppercase" + end end