Skip to content

Instantly share code, notes, and snippets.

@pigoz
Created November 9, 2018 15:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pigoz/bef67f5a1d5c293e61a84f5a99b2d3d9 to your computer and use it in GitHub Desktop.
Save pigoz/bef67f5a1d5c293e61a84f5a99b2d3d9 to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
require 'ostruct'
class Component
attr_reader :props
def initialize(**props, &children)
@props = OpenStruct.new(default_props.merge(props))
@children = children
end
def default_props
{}
end
def button(**props, &children)
HtmlComponent.new(:button, **props, &children).render
end
def div(**props, &children)
HtmlComponent.new(:div, **props, &children).render
end
def children
@children.call
end
def render; end
end
class HtmlComponent < Component
def initialize(tag, **props, &children)
@tag = tag
super(**props, &children)
end
def render
html_attributes = props.to_h.map { |k, v| %("#{k}="#{v}") }.join(' ')
"<#{@tag} #{html_attributes}>#{@children ? @children.call : nil}</#{@tag}>"
end
end
class Button < Component
def default_props
{
type: 'primary'
}
end
def render
button class: "btn btn--#{props.type}" do
div class: 'btn__inner' do
children
end
end
end
end
def Button(**props, &children)
Button.new(**props, &children).render
end
class A < Component
def render
div class: "a a--color-#{props.color}" do
Button do
'click me!'
end
end
end
end
puts A.new(color: 'red').render # => <div "class="a a--color-red"><button "class="btn btn--primary"><div "class="btn__inner">click me!</div></button></div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment