carlos / platform Public

console: the switcher's caret and marks become icons — a glyph is whatever the reader's font says it is

"▾" and "✓" were standing in for controls. What they actually render as is
the reader's font's business: a black triangle here, a coloured emoji there,
a notdef box somewhere else, and in none of those cases does the page get to
say how big it is or what colour it takes. The vendored Lucide chevron and
check do both — they size from the text beside them and inherit its colour,
in light mode and dark.

The tick column becomes the mark column while it is open: a check on the
account you are in, hidden on the ones you are not (it still reserves its
width, so the names stay in one column), and a plus on "New account", which
was previously an invisible tick used as a spacer.

Every icon is aria-hidden: each sits beside its own text label, and the
current account is announced by aria-current, not by the mark. The footer's
robot stays exactly where it is — that is the factor-X disclosure, which is
content, and emoji are content.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell 5f619fe835e15ca4857af38509d1f621b6cebdb8 parent fed767d
1 file changed, +22 −9
  • internal/console/templates/layout.html +22 −9
diff --git a/internal/console/templates/layout.html b/internal/console/templates/layout.html
index 7d2975305..eb87bd008 100644
--- a/internal/console/templates/layout.html
+++ b/internal/console/templates/layout.html
@@ -40,6 +40,11 @@
border: 1px solid var(--rule); border-radius: 0.5rem; padding: 0.3rem 0.5rem;
}
td form { display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; margin: 0; }
+ /* Interface icons: inline SVG from internal/console/icons.go — Lucide,
+ vendored, because this page fetches nothing from anywhere. They carry no
+ width/height of their own, so they size to the text beside them and
+ inherit its colour. */
+ .icon { width: 1em; height: 1em; flex: none; vertical-align: -0.125em; }
header {
max-width: 56rem; margin: 0 auto; padding: 1.4rem 0;
display: flex; align-items: baseline; gap: 1rem;
@@ -72,8 +77,10 @@
font-weight: 700; min-width: 0; max-width: 14rem;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
- header .switcher .caret { font-size: 0.7rem; color: var(--muted); }
- header .switcher[open] > summary .caret { transform: rotate(180deg); display: inline-block; }
+ /* The caret is an icon, not a text character: centred against a
+ baseline-aligned row, muted, and flipped while the menu is open. */
+ header .switcher > summary > .icon { color: var(--muted); align-self: center; width: 0.9em; }
+ header .switcher[open] > summary > .icon { transform: rotate(180deg); }
header .switcher-menu {
position: absolute; z-index: 20; top: calc(100% + 0.6rem); left: -0.5rem;
min-width: 13rem; max-width: 20rem;
@@ -89,9 +96,15 @@
}
header .switcher-menu a:hover, header .switcher-menu a:focus { background: var(--accent-soft); }
header .switcher-menu .current { font-weight: 600; background: var(--accent-soft); }
- /* The tick reserves its width on every row so the names stay in one column. */
- header .switcher-menu .tick { color: var(--accent); width: 0.9rem; flex: none; }
- header .switcher-menu a .tick { visibility: hidden; }
+ /* The mark column reserves its width on every row so the names stay in one
+ column: a check on the account you are in, hidden on the ones you are
+ not, a plus on "New account". */
+ header .switcher-menu .mark {
+ color: var(--accent); width: 0.9rem; flex: none;
+ display: flex; align-self: center;
+ }
+ header .switcher-menu a .mark { visibility: hidden; }
+ header .switcher-menu .new a .mark { visibility: visible; }
header .switcher-menu hr { border: 0; border-top: 1px solid var(--rule); margin: 0.35rem 0.2rem; }
header .switcher-menu .new a { color: var(--accent); }
main { max-width: 56rem; margin: 0 auto; padding: 2.5rem 0 3rem; min-height: 55vh; }
@@ -165,19 +178,19 @@
<summary>
<span class="small">Account</span>
<span class="current-name">{{.Account.Name}}</span>
- <span class="caret" aria-hidden="true">▾</span>
+ {{icon "chevron-down"}}
</summary>
<div class="switcher-menu">
<ul>
{{range .Accounts}}<li>{{if eq .Sqid $.Account.Sqid}}
- <span class="current" aria-current="true"><span class="tick" aria-hidden="true">✓</span>{{.Name}}</span>
+ <span class="current" aria-current="true"><span class="mark">{{icon "check"}}</span>{{.Name}}</span>
{{else}}
- <a href="/a/{{.Sqid}}/"><span class="tick" aria-hidden="true">✓</span>{{.Name}}</a>
+ <a href="/a/{{.Sqid}}/"><span class="mark">{{icon "check"}}</span>{{.Name}}</a>
{{end}}</li>
{{end}}
</ul>
<hr>
- <div class="new"><a href="/accounts/new"><span class="tick" aria-hidden="true">✓</span>New account</a></div>
+ <div class="new"><a href="/accounts/new"><span class="mark">{{icon "plus"}}</span>New account</a></div>
</div>
</details>
{{else}}