-
-
Save 1gor/c37b70ae9098bbdac61a4ad627b728dd 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