Panel
A card with switcher buttons across its top bar and the open one's content below: a README beside the brief, a file's source beside its preview. Tabs switch in the page, or each is a page of its own.
Tabs switched in the page
The same tabs as tabs, in a bar: icon: leads each label, and the row scrolls sideways on a narrow screen with the open tab brought into view.
Kidbook
A picture book's worth of characters, rigged and ready to pose. Import a folder of drawings and every one becomes a resource with a preview, a poster and the metadata its format carries.
Start with bin/setup, then bin/dev.
Working here
- Plain Rails. Reach for a gem only when Rails can't say it.
- Rich models, thin controllers, no service layer.
- HTML over the wire: Turbo and a little Stimulus.
Style
Warm neutrals, one accent, and type that reads at a glance. Illustrations keep their linework; nothing is smoothed into a gradient.
<%= panel id: "notes" do |panel| %>
<% panel.tab "README", icon: :book_open %>
<% panel.tab "Agents", icon: :bot %>
<% panel.tab "Style guide", icon: :palette %>
<% panel.tab "Changelog", icon: :list_checks, disabled: "none yet" %>
<% panel.panel do %>
<div class="UnmagicProse">
<h2>Kidbook</h2>
<p>A picture book's worth of characters, rigged and ready to pose. Import a folder of drawings and every
one becomes a resource with a preview, a poster and the metadata its format carries.</p>
<p>Start with <code>bin/setup</code>, then <code>bin/dev</code>.</p>
</div>
<% end %>
<% panel.panel do %>
<div class="UnmagicProse">
<h2>Working here</h2>
<ul>
<li>Plain Rails. Reach for a gem only when Rails can't say it.</li>
<li>Rich models, thin controllers, no service layer.</li>
<li>HTML over the wire: Turbo and a little Stimulus.</li>
</ul>
</div>
<% end %>
<% panel.panel do %>
<div class="UnmagicProse">
<h2>Style</h2>
<p>Warm neutrals, one accent, and type that reads at a glance. Illustrations keep their linework; nothing
is smoothed into a gradient.</p>
</div>
<% end %>
<% end %>Tabs that are pages of their own
With href: the bar is links and the block is the body, drawn by the server for the open one. flush: true lets the content run to the edges, as a code view wants to.
{
"name": "kitchen.modelscene.json",
"viewports": [
{ "camera": "front", "width": 1920, "height": 1080 },
{ "camera": "top", "width": 1080, "height": 1080 }
],
"lighting": "studio"
}<%= panel flush: true do |panel| %>
<% panel.tab "Source", href: "#", active: true, icon: :code %>
<% panel.tab "Preview", href: "#", icon: :eye %>
<% panel.tab "Poster", href: "#", icon: :image %>
<% panel.tab "Metadata", href: "#", icon: :list_checks %>
<%= code_view language: :json, class: "rounded-none border-0" do %>
{
"name": "kitchen.modelscene.json",
"viewports": [
{ "camera": "front", "width": 1920, "height": 1080 },
{ "camera": "top", "width": 1080, "height": 1080 }
],
"lighting": "studio"
}
<% end %>
<% end %>