fix(welcome): judge-panel fixes on the new launcher row

Design B ("one primary + chips") won a two-judge panel over a launcher grid
and a command panel. Their defect list, fixed here:

- The tunnel spinner's track was the shared translucent white and vanished on
  light skins; it now follows the link's own text colour.
- A running tunnel was only green text above its QR; it now shows as a quiet
  green pill, and the resting link uses --text-dim (contrast).
- A long custom CLI label could push a horizontal scrollbar into the welcome
  column: labels sit in a .welcome-label span that ellipsizes (still one text
  node, so i18n.js matches it), and both buttons cap at the column width.
- Chips are 40px tall on coarse pointers (tablets reach this view).
- The OG primary's colours now name the toolbar Run rule they mirror.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-10-08 23:07:55 +02:00
parent a1d07a56e5
commit 34cbd5015b
3 changed files with 60 additions and 9 deletions
+10 -3
View File
@@ -1693,8 +1693,12 @@ Object.assign(CodemanApp.prototype, {
disc.className = 'welcome-primary-logo';
disc.appendChild(logo(primary));
main.appendChild(disc);
// One raw string, kept whole: i18n.js matches the exact text node.
main.append(runLabel(primary));
// One raw string, kept whole: i18n.js matches the exact text node. The span
// only lets a long custom label ellipsize (styles.css .welcome-label).
const mainLabel = document.createElement('span');
mainLabel.className = 'welcome-label';
mainLabel.textContent = runLabel(primary);
main.appendChild(mainLabel);
main.onclick = launch(primary);
container.appendChild(main);
@@ -1715,7 +1719,10 @@ Object.assign(CodemanApp.prototype, {
chip.title = runLabel(cli);
chip.setAttribute('aria-label', runLabel(cli));
chip.appendChild(logo(cli));
chip.append(cli.kind === 'shell' ? 'Shell' : cli.label);
const chipLabel = document.createElement('span');
chipLabel.className = 'welcome-label';
chipLabel.textContent = cli.kind === 'shell' ? 'Shell' : cli.label;
chip.appendChild(chipLabel);
chip.onclick = launch(cli);
chips.appendChild(chip);
}
+34 -5
View File
@@ -4389,6 +4389,7 @@ body.touch-device .terminal-container .xterm .xterm-helper-textarea {
align-items: center;
gap: 0.65rem;
height: 46px;
max-width: 100%;
padding: 0 1.4rem 0 0.45rem;
box-sizing: border-box;
border: 1px solid var(--accent);
@@ -4416,7 +4417,8 @@ body.touch-device .terminal-container .xterm .xterm-helper-textarea {
/* OG has no designed --accent-ink (its Daylight extras are placeholders), and a
dark ink on its brighter blue reads poorly: it gets the deeper blue and light
text of its own toolbar Run button instead. */
text of its own toolbar Run button instead. These are that button's colours
(`.btn-toolbar.btn-run.mode-claude` and its :hover, below): keep the two in step. */
html[data-skin="og"] .welcome-primary {
background: linear-gradient(135deg, #1e4fb8 0%, #2563eb 100%);
border-color: rgba(96, 165, 250, 0.5);
@@ -4462,11 +4464,22 @@ html[data-skin="og"] .welcome-primary:hover {
max-width: 100%;
}
/* A long custom label (clis.json) ellipsizes inside its button (both carry
max-width: 100%) instead of pushing a horizontal scrollbar into
.welcome-content. The span holds the label as ONE text node, so i18n.js still
matches it whole. */
.welcome-label {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
}
.welcome-chip {
display: inline-flex;
align-items: center;
gap: 0.45rem;
height: 30px;
max-width: 100%;
padding: 0 0.85rem 0 0.7rem;
box-sizing: border-box;
border: 1px solid var(--control-border);
@@ -4497,17 +4510,17 @@ html[data-skin="og"] .welcome-primary:hover {
quiet text link under it. settings-ui.js owns its contents (it rewrites the
icon, label and spinner on every state change) and its inline display, so
everything here is styled from the outside: the 20px svg it writes is sized
down, and the states are text colour only. Ahead of #welcomeQr on purpose,
down, and the states are text colour (plus a pill while a tunnel runs). Ahead of #welcomeQr on purpose,
so the QR opens right under the control that toggled it. */
.welcome-tunnel-link {
align-items: center;
gap: 0.4rem;
margin-top: 1.4rem;
padding: 0.3rem 0.65rem;
border: none;
border-radius: 8px;
border: 1px solid transparent;
border-radius: 999px;
background: none;
color: var(--text-muted);
color: var(--text-dim);
font: inherit;
font-size: 0.75rem;
font-weight: 500;
@@ -4525,6 +4538,10 @@ html[data-skin="og"] .welcome-primary:hover {
width: 11px;
height: 11px;
border-width: 1.5px;
/* The shared spinner's track is translucent WHITE, which vanishes on the
light skins; draw it from the link's own text colour instead. */
border-color: color-mix(in srgb, currentColor 25%, transparent);
border-top-color: currentColor;
}
.welcome-tunnel-link:hover {
@@ -4538,10 +4555,22 @@ html[data-skin="og"] .welcome-primary:hover {
color: var(--text);
}
/* A running tunnel is a state, not a recoloured link: it gets a quiet green pill. */
.welcome-tunnel-link.active {
border-color: color-mix(in srgb, var(--green) 45%, transparent);
background: color-mix(in srgb, var(--green) 9%, transparent);
color: var(--green);
}
/* Touch screens wide enough for this view (tablets) get finger-sized chips. */
@media (pointer: coarse) {
.welcome-chip {
height: 40px;
border-radius: 20px;
padding: 0 1rem 0 0.85rem;
}
}
.welcome-tunnel-link.connecting,
.welcome-tunnel-link:disabled {
cursor: wait;