Skip to content

Instantly share code, notes, and snippets.

@1gor
Forked from jgaskins/app.rb
Created September 12, 2018 13:04
Show Gist options
  • Save 1gor/c37b70ae9098bbdac61a4ad627b728dd to your computer and use it in GitHub Desktop.
Save 1gor/c37b70ae9098bbdac61a4ad627b728dd to your computer and use it in GitHub Desktop.
Ryan Florence's "Compound Components" in Clearwater
require 'opal'
require 'clearwater'
require 'clearwater/memoized_component'
class Layout
include Clearwater::Component
def render
div([
Tabs.memoize(
TabList.new([
Tab.new('Foo'),
Tab.new('Bar', disabled: true),
Tab.new('Baz'),
]),
TabPanels.new([
TabPanel.new(p('This is foo')),
TabPanel.new(p('Bar for days')),
TabPanel.new(p('lol omg baz')),
]),
),
])
end
end
class Tabs < Clearwater::MemoizedComponent
def initialize(tabs, panels)
@active_index = 0
@tabs = tabs
@panels = panels
end
def render
div([
@tabs
.on_activate { |index| @active_index = index; call }
.with_active_index(@active_index),
@panels
.with_active_index(@active_index),
])
end
end
class TabList
include Clearwater::Component
def initialize tabs
@tabs = tabs
end
def render
ul({ style: style }, @tabs.map.with_index { |tab, index|
tab
.on_click { @on_activate && @on_activate.call(index) }
.active(@active_index == index)
})
end
def with_active_index index
@active_index = index
self
end
def on_activate(&block)
@on_activate = block
self
end
private
def style
{
list_style: :none,
padding: 0,
}
end
end
class Tab
include Clearwater::Component
def initialize title, disabled: false
@title = title
@disabled = disabled
end
def render
li({ style: tab_style, onclick: @on_click }, [
@title
])
end
def active is_active
@active = is_active
self
end
def on_click &block
@on_click = block
self
end
private
def tab_style
{
display: 'inline-block',
vertical_align: :top,
width: '100px',
color: @active ? :black : :gray,
}
end
end
class TabPanels
include Clearwater::Component
def initialize panels
@panels = panels
end
def render
div(@panels[@active_index])
end
def with_active_index index
@active_index = index
self
end
end
class TabPanel
include Clearwater::Component
def initialize content
@content = content
end
def render
div(@content)
end
end
app = Clearwater::Application.new(
component: Layout.new,
element: Bowser.document['#app'],
)
app.call
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment