panel-redesign: the component kit - panel.css, partials, shell, kit page
Stage 0, steps 3-5, in one commit: the three were built together (the kit
page is what exercises the partials and the shell) and do not split into
states that build on their own. Written by Sonnet, reviewed by Opus.
- static/panel.css: shared/brand.css + panel/theme.css, rule for rule.
wordmark.svg and perf-edge.svg beside it; the stamp is logo.svg.
- templates/components.html: every partial of the plan's Three layers,
with its typed input in components.go. Wrappers are open/close pairs
(box_open/box_close, body_open/body_close, record_open/record_close).
Rich text is a Text value built from escaped runs - no field is
trusted HTML. status_tag and wbr_at are template functions; copy_field
is a partial whose button panel.js wires through data-copy.
- templates/layout.html: the shell as build.py draws it, the menu paths
written out literally, visibility from a typed Shell (role, feature
flags, the user's reach); the signed-out screen as a second define.
Not in the 2.0 menu: Inbound Log / Queue / Quarantine / Filter lists
and Preflight.
- GET /server/components (global role, 404 otherwise): the mockup
components page rebuilt from fixtures (kit.go) by the real templates.
- The old panel steps aside unchanged: panel.css -> legacy.css,
layout.html -> layout_legacy.html; a page uses the new layout iff it
is off legacy_pages.txt.
- legacy_pages.txt: @kit removed - the kit is under the guards for good.
Differences from the mockup components page, for the owner:
- the head button is Help, not "Cover sheet"; two "Example" links are
dropped (no fixed URL), two point at /outbound/domains and /login;
- the page sits in the Server group, so the sibling strip shows;
- Sign out is a POST form whose button carries navbar-item: same size
and type as the links, but without Bulma's hover tint;
- a head's actions are always wrapped in div.buttons.
Evidence
- docs/assets/panel-redesign/evidence/components.png: 1440 px wide, full
height, headless Edge. Taken from the real templates served locally,
NOT from the container (no Docker on this machine); the page reads
only its own fixtures and embedded assets.
- panel/audit.js on the kit page, 1440 and 1280:
{"pages":1,"widths":[1440,1280],"textsChecked":516,"problems":[]}
- go test ./internal/web/... (with @kit removed)
ok github.com/mixeme/selfpost/internal/web
ok github.com/mixeme/selfpost/internal/web/auth
ok github.com/mixeme/selfpost/internal/web/handlers
ok github.com/mixeme/selfpost/internal/web/validate
ok github.com/mixeme/selfpost/internal/web/view
TestRoutesFollowNavigation stays skipped behind @routes (stage 1).
Roadmap 10/27.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
{{/* The kit page (GET /server/components): every partial of components.html in
|
||||
every state, filled from kit.go — the mockup components page rebuilt with
|
||||
the real templates. Like any page it is thin: partial calls with structs,
|
||||
Bulma layout classes, and the page utilities; the markup of a component is
|
||||
written in components.html and nowhere else. */}}
|
||||
{{define "content"}}
|
||||
{{template "page_head" .Head}}
|
||||
|
||||
{{template "flash" .Flash}}
|
||||
{{template "flash" .FlashError}}
|
||||
|
||||
{{template "box_open" .Layouts}}
|
||||
{{template "body_open"}}
|
||||
{{template "facts" .LayoutFacts}}
|
||||
{{template "body_close"}}
|
||||
{{template "box_close"}}
|
||||
|
||||
<div class="columns">
|
||||
<div class="column is-6">
|
||||
{{template "box_open" .Postmark}}
|
||||
{{template "body_open"}}
|
||||
<div class="buttons">{{range .Postmarks}}
|
||||
{{template "postmark" .}}{{end}}
|
||||
</div>
|
||||
<p class="sp-muted">Only inside page_head, at most one per page, and only where the page has a verdict to give.</p>
|
||||
{{template "body_close"}}
|
||||
{{template "box_close"}}
|
||||
|
||||
{{template "box_open" .StatusTag}}
|
||||
<div class="table-container"><table class="table is-fullwidth">
|
||||
<thead><tr><th>Status</th><th>Tag</th><th>Bulma classes</th></tr></thead>
|
||||
<tbody>{{range .StatusRows}}
|
||||
<tr><td>{{.Words}}</td><td>{{template "tag" .Tag}}</td><td class="sp-mono sp-small">{{status_tag .Tag.Status}}</td></tr>{{end}}
|
||||
</tbody>
|
||||
</table></div>
|
||||
{{template "box_close"}}
|
||||
</div>
|
||||
|
||||
<div class="column is-6">
|
||||
{{template "box_open" .BoxHead}}
|
||||
{{template "body_open"}}
|
||||
<p class="mb-2">The <i class="ti ti-help-circle"></i> after the end slot is <code>sp-help</code>: an optional link to the section's topic on the Help page. It replaces today's help drawer.</p>
|
||||
<p>box_body — padded content. A <code>table</code> or a run of <code>sp-record</code> blocks sits directly in the box, without box_body.</p>
|
||||
{{template "body_close"}}
|
||||
{{template "box_foot" .BoxFoot}}
|
||||
{{template "box_close"}}
|
||||
|
||||
{{template "box_open" .DangerZone}}
|
||||
{{template "body_open"}}
|
||||
<p>For destructive confirmations and the "delete" entry of a settings page. The number may be an icon when the box is not part of a sequence.</p>
|
||||
{{template "body_close"}}
|
||||
{{template "box_close"}}
|
||||
|
||||
{{template "box_open" .Credential}}
|
||||
{{template "body_open"}}
|
||||
<p>Only for a secret the panel will never show again.</p>
|
||||
{{template "body_close"}}
|
||||
{{template "box_close"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "box_open" .HealthCard}}
|
||||
{{template "health_cards" .HealthCards}}
|
||||
{{template "box_close"}}
|
||||
|
||||
<div class="columns">
|
||||
<div class="column is-7">
|
||||
{{template "box_open" .DNSRecord}}
|
||||
{{range .Records}}{{template "dns_record" .}}
|
||||
{{end}}{{template "box_close"}}
|
||||
|
||||
{{template "box_open" .Tables}}
|
||||
<div class="table-container"><table class="table is-fullwidth is-hoverable">
|
||||
<thead><tr><th>Time, UTC</th><th>Name</th><th>sp-clip</th><th>Status</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td class="sp-mono sp-muted sp-nowrap sp-small">09-21 14:01:52</td><td><a href="#"><strong>the row's link</strong></a></td><td class="sp-clip">A long subject is clipped with an ellipsis instead of wrapping the row</td><td><span class="{{status_tag "sent"}}">sent</span></td><td class="sp-actions"><a href="#">Details</a><a class="has-text-danger" href="#">Delete</a></td></tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
{{template "box_foot" .TablesFoot}}
|
||||
{{template "box_close"}}
|
||||
|
||||
{{template "box_open" .LogPane}}
|
||||
{{template "log_pane" .LogLines}}
|
||||
{{template "box_close"}}
|
||||
</div>
|
||||
|
||||
<div class="column is-5">
|
||||
{{template "box_open" .Facts}}
|
||||
{{template "body_open"}}
|
||||
{{template "facts" .FactList}}
|
||||
{{template "body_close"}}
|
||||
{{template "box_close"}}
|
||||
|
||||
{{template "box_open" .Timeline}}
|
||||
{{template "body_open"}}
|
||||
{{template "timeline" .Steps}}
|
||||
{{template "body_close"}}
|
||||
{{template "box_close"}}
|
||||
|
||||
{{template "box_open" .EmptyState}}
|
||||
{{template "empty_state" .Empty}}
|
||||
{{template "box_close"}}
|
||||
|
||||
{{template "box_open" .ConfirmList}}
|
||||
{{template "body_open"}}
|
||||
{{template "confirm_list" .Confirm}}
|
||||
{{template "body_close"}}
|
||||
{{template "box_close"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="columns">
|
||||
<div class="column is-3">
|
||||
{{template "side_menu" .SideMenu}}
|
||||
</div>
|
||||
<div class="column is-9">
|
||||
{{template "box_open" .FormRows}}
|
||||
{{template "body_open"}}
|
||||
<div class="sp-form">
|
||||
<div class="sp-row">
|
||||
<div class="field"><label class="label">sp-row — a wide field</label><div class="control"><input class="input" value="host"></div></div>
|
||||
<div class="field"><label class="label">and a short one</label><div class="control"><input class="input" value="25"></div></div>
|
||||
</div>
|
||||
<div class="sp-pair">
|
||||
<div class="field"><label class="label">sp-pair — two equal fields</label><div class="control"><input class="input" type="password"></div></div>
|
||||
<div class="field"><label class="label">Repeat</label><div class="control"><input class="input" type="password"></div><p class="help">Help text lives in Bulma's <code>help</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "route" .Route}}
|
||||
{{template "body_close"}}
|
||||
{{template "help_topic" .HelpTopic}}
|
||||
{{template "box_close"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{template "box_open" .Shell}}
|
||||
{{template "body_open"}}
|
||||
{{template "facts" .ShellFacts}}
|
||||
{{template "body_close"}}
|
||||
{{template "box_close"}}
|
||||
|
||||
{{template "box_open" .TypeScale}}
|
||||
<div class="table-container"><table class="table is-fullwidth">
|
||||
<thead><tr><th>Size</th><th>Looks like</th><th>Used for</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td class="sp-mono sp-small">body · 16px</td><td>The quick brown fox, 203.0.113.25</td><td class="sp-muted">Text, table cells, inputs, selects, buttons, menus and their dropdowns</td></tr>
|
||||
<tr><td class="sp-mono sp-small">--sp-fs-s · 14px</td><td class="sp-small">The quick brown fox, <span class="sp-mono">203.0.113.25</span></td><td class="sp-muted">Supporting text: labels, <code>help</code>, notes in a box head or foot, mono values (<code>sp-small</code>), logs, the footer</td></tr>
|
||||
<tr><td class="sp-mono sp-small">--sp-fs-xs · 13px</td><td>{{template "kicker" .KickerSample}} <span class="tag is-light">tag</span></td><td class="sp-muted">Upper-case mono micro-labels (kicker, table head, <code>dt</code>, box title) and tags — nothing else</td></tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
{{template "box_foot" .TypeScaleFoot}}
|
||||
{{template "box_close"}}
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user