Last active
June 7, 2020 01:21
-
-
Save bradparker/494a8d5c6f8f8e8f4098326ffc6b146a to your computer and use it in GitHub Desktop.
Sketch of ViewComponent::Styled API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ViewComponent | |
module Styled | |
def self.included(base) | |
base.extend ClassMethods | |
end | |
module ClassMethods | |
def styled(static = [], &block) | |
@static_styles = static | |
@dynamic_styles = block | |
end | |
def styled_like(components = [], static = [], &block) | |
@static_styles = components.flat_map(&:static_styles) + static | |
@dynamic_styles = Proc.new do | |
component_styles = components.flat_map do |component| | |
instance_eval(&component.dynamic_styles) | |
end | |
component_styles + instance_eval(&block) | |
end | |
end | |
def static_styles | |
@static_styles | |
end | |
def dynamic_styles | |
@dynamic_styles | |
end | |
end | |
def styles | |
self.class.static_styles + instance_eval(&self.class.dynamic_styles) | |
end | |
class Base | |
include ViewComponent::Styled | |
styled [] do | |
props.styles.to_a | |
end | |
def self.default_props | |
{ styles: [], element: :div } | |
end | |
attr_reader :props | |
def initialize(props = {}) | |
@props = Struct.new( | |
*props.keys, keyword_init: true | |
).new( | |
self.class.default_props.merge(props) | |
) | |
end | |
def element | |
props.element | |
end | |
def call | |
{ element: element, styles: styles } | |
end | |
end | |
end | |
end | |
# Not sure about this. Don't know if to override `styled` and `styled_like` in subclasses | |
puts ViewComponent::Styled::Base.new(styles: [:foo], element: :section).call.inspect | |
# {:element=>:section, :styles=>[:foo]} | |
class ExampleA | |
include ViewComponent::Styled | |
styled [:base] do | |
if active? | |
[:active] | |
else | |
[] | |
end | |
end | |
def initialize(active:) | |
@active = active | |
end | |
def active? | |
@active | |
end | |
end | |
puts ExampleA.new(active: true).styles.inspect | |
# [:base, :active] | |
puts ExampleA.new(active: false).styles.inspect | |
# [:base] | |
class ExampleB | |
include ViewComponent::Styled | |
styled [:a_different_base] do | |
if good? | |
[:good] | |
else | |
[] | |
end | |
end | |
def initialize(good:) | |
@good = good | |
end | |
def good? | |
@good | |
end | |
end | |
puts ExampleB.new(good: true).styles.inspect | |
# [:a_different_base, :good] | |
puts ExampleB.new(good: false).styles.inspect | |
# [:a_different_base] | |
class ExampleC | |
include ViewComponent::Styled | |
styled_like [ExampleA, ExampleB] do | |
if really_good? | |
[:really_good] | |
else | |
[] | |
end | |
end | |
def good? | |
true | |
end | |
def active? | |
true | |
end | |
def really_good? | |
true | |
end | |
end | |
puts ExampleC.new.styles.inspect | |
# [:base, :a_different_base, :active, :good, :really_good] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment