Last active
September 12, 2018 13:04
-
-
Save jgaskins/47454f2b9f7030090dd701aa925c694e to your computer and use it in GitHub Desktop.
Ryan Florence's "Compound Components" in Clearwater
This file contains hidden or 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
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