Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified apps/ui/e2e/__screens__/agent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/ui/e2e/__screens__/backlog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 47 additions & 1 deletion apps/ui/src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -1586,6 +1586,15 @@
font-family: var(--cx-font-ui);
}

/* Seat the inline branch glyph (state-dot.css §seating). */
.usage-git-glyph {
display: inline-flex;
}

.usage-git-glyph > svg {
display: block;
}

/* ── Shared helpers ─────────────────────────────────────────────────────── */

.muted {
Expand Down Expand Up @@ -1640,11 +1649,17 @@

.backlog-chevron {
color: var(--cx-text-faint);
font-size: 10px;
display: inline-flex;
/* stylelint-disable-next-line declaration-property-value-disallowed-list -- TODO(motion migration, D9/foundation-T8): raw 0.12s/ease grandfathered by the RIG-2034 cutover lane, which never scoped the motion axis */
transition: transform 0.12s ease;
}

/* Seat the inline glyph SVG (state-dot.css §seating): an inline replaced box
* otherwise rides the text baseline and overflows its box. */
.backlog-chevron > svg {
display: block;
}

.backlog-chevron.open {
transform: rotate(90deg);
}
Expand Down Expand Up @@ -3485,6 +3500,17 @@
cursor: default;
}

/* The Stop control's halt-mark glyph, seated inline beside the "stop" label. */
.obs-stop-glyph {
display: inline-flex;
vertical-align: middle;
color: currentColor;
}

.obs-stop-glyph > svg {
display: block;
}

/* A REFUSED stop, said beside the control rather than left in the console —
* same weight and colour as the ask block's refusal (.ask-error). */
.obs-error {
Expand All @@ -3507,6 +3533,26 @@
color: var(--cx-text);
}

/* The minimize/expand toggle's caret glyph. `disclosure` points right; the open
* panel keeps that (the old `⟩`), and the minimized rail rotates it 180° to
* point left (the old `⟨`, the expand affordance). Both states are one glyph so
* the pair can never misalign the way the old character pair could. */
.obs-min-glyph {
display: inline-flex;
color: currentColor;
transform: rotate(180deg);
/* stylelint-disable-next-line declaration-property-value-disallowed-list -- TODO(motion migration, D9/foundation-T8): raw 0.12s/ease grandfathered by the RIG-2034 cutover lane, which never scoped the motion axis */
transition: transform 0.12s ease;
}

.obs-min-glyph.open {
transform: rotate(0deg);
}

.obs-min-glyph > svg {
display: block;
}

.log-panel .obs-body {
flex: 1;
min-height: 0;
Expand Down
8 changes: 5 additions & 3 deletions apps/ui/src/comms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@ export function isDm(channel: Channel): boolean {
}

/** The glyph before a channel name, by kind (Discord-style: # for a channel,
* @ for a DM, a cluster glyph for a group DM). One home so the rail row and
* the channel header never drift. */
* @ for a DM, & for a group DM — the "cluster" marker). One home so the rail
* row and the channel header never drift. All three are ASCII, covered by the
* brand face; this stays DATA (a string in the marker column), not a `<Glyph>`
* — a bitmap for one kind only would mix glyph and character in one column. */
export function channelGlyph(kind: Channel["kind"]): string {
switch (kind) {
case "dm":
return "@";
case "group_dm":
return "";
return "&";
default:
return "#";
}
Expand Down
5 changes: 4 additions & 1 deletion apps/ui/src/components/BacklogView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { type Component, createSignal, For, Show } from "solid-js";
import { isMultiForge, issueKey } from "../board-render";
import { useStore } from "../context";
import type { Issue } from "../stub-data";
import { Glyph } from "./Glyph";

/** A single Linear-style issue row: id · title · priority · state · tracker.
* Clicking the row selects the issue (staying on the view). Not the board
Expand Down Expand Up @@ -63,7 +64,9 @@ const BacklogSection: Component<{
aria-controls={contentId}
onClick={() => setOpen(!open())}
>
<span class={["backlog-chevron", { open: open() }]}>▸</span>
<span class={["backlog-chevron", { open: open() }]} aria-hidden="true">
<Glyph name="disclosure" />
</span>
<span class="backlog-section-title">{props.title}</span>
<span class="backlog-count">{props.rows.length}</span>
</button>
Expand Down
57 changes: 56 additions & 1 deletion apps/ui/src/components/Glyph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ export type GlyphName =
| "gear"
| "logo"
| "panel-right"
| "panel-left";
| "panel-left"
| "stop";

/** [x, y] of each lit cell (11×11, one CSS px per cell), transcribed from the
* frozen ASCII grids in `design/components.md` §Glyphs (`#` = lit). Keying on
Expand Down Expand Up @@ -911,6 +912,60 @@ const GLYPH_CELLS: Record<
[8, 9],
[9, 9],
],
// A filled 7×7 square (rows/cols 2..8) — the halt mark on the log-panel Stop
// control, replacing the uncovered `■` U+25A0. One solid block, deliberately
// centered with a 2-cell margin so it reads square, not full-bleed.
stop: [
[2, 2],
[3, 2],
[4, 2],
[5, 2],
[6, 2],
[7, 2],
[8, 2],
[2, 3],
[3, 3],
[4, 3],
[5, 3],
[6, 3],
[7, 3],
[8, 3],
[2, 4],
[3, 4],
[4, 4],
[5, 4],
[6, 4],
[7, 4],
[8, 4],
[2, 5],
[3, 5],
[4, 5],
[5, 5],
[6, 5],
[7, 5],
[8, 5],
[2, 6],
[3, 6],
[4, 6],
[5, 6],
[6, 6],
[7, 6],
[8, 6],
[2, 7],
[3, 7],
[4, 7],
[5, 7],
[6, 7],
[7, 7],
[8, 7],
[2, 8],
[3, 8],
[4, 8],
[5, 8],
[6, 8],
[7, 8],
[8, 8],
],
};

/** Every glyph name, derived from the table itself so callers that enumerate
Expand Down
13 changes: 11 additions & 2 deletions apps/ui/src/components/LogPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { type Component, Show } from "solid-js";
import { useStore } from "../context";
import { foldSession } from "../session-events";
import type { Agent } from "../stub-data";
import { Glyph } from "./Glyph";
import { SessionTrace } from "./SessionTrace";

/** The trace observation pane: the selected agent's typed execution trace. The
Expand Down Expand Up @@ -82,7 +83,10 @@ export const LogPanel: Component<{ agent: Agent }> = (props) => {
}
onClick={() => void store.stopAgent()}
>
■ stop
<span class="obs-stop-glyph" aria-hidden="true">
<Glyph name="stop" />
</span>{" "}
stop
</button>
</Show>
{/* A refused stop (a server with no RunnerHub answers `Unavailable`,
Expand All @@ -104,7 +108,12 @@ export const LogPanel: Component<{ agent: Agent }> = (props) => {
title={store.logOpen() ? "Minimize log panel" : "Expand log panel"}
onClick={() => store.toggleLog()}
>
{store.logOpen() ? "⟩" : "⟨"}
<span
class={["obs-min-glyph", { open: store.logOpen() }]}
aria-hidden="true"
>
<Glyph name="disclosure" />
</span>
</button>
</div>
<Show when={store.logOpen()}>
Expand Down
6 changes: 5 additions & 1 deletion apps/ui/src/components/UsageBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { type Component, For } from "solid-js";
import { STUB_USAGE } from "../stub-data";
import { Glyph } from "./Glyph";

const fmtTokens = (n: number): string =>
n >= 1_000_000
Expand Down Expand Up @@ -41,7 +42,10 @@ export const UsageBar: Component = () => (
</For>
<span class="usage-spacer" />
<span class="usage-git">
<span aria-hidden="true">⎇</span> compass · main
<span class="usage-git-glyph" aria-hidden="true">
<Glyph name="vcs" />
</span>{" "}
compass · main
</span>
</footer>
);
50 changes: 50 additions & 0 deletions apps/ui/src/design/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,24 @@ toggle-right-sidebar control):
...........
```

### T5c glyph grid (LogPanel, 11×11)

`stop` — a filled square halt mark (replaces `■`, the log-panel Stop control):

```text
...........
...........
..#######..
..#######..
..#######..
..#######..
..#######..
..#######..
..#######..
...........
...........
```

### Chrome conversion audit (T5a + T5b)

Every chrome site converted from a character to a `<Glyph>`, with the
Expand Down Expand Up @@ -777,6 +795,38 @@ The two name-bearing rows are the hazard this table exists to catch: a bare
`✓`/`✗` verdict mark reads as nothing once the glyph is hidden, so those sites
carry the verdict word on the wrapper. `RightSidebar.prpane.test.tsx` pins that.

### Chrome conversion audit (T5c)

The final chrome-pictograph slice: the remaining characters no brand face
covers (`■ ⟩ ⟨ ⎇ ⌗ ▸`) and the `→` style calls. All converted sites below are
**decorative** — adjacent text or an `aria-label` on the control names them.

| Site | Was | Glyph |
| --- | --- | --- |
| `BacklogView` section caret | `▸` | `disclosure` |
| `LogPanel` Stop mark | `■` | `stop` |
| `LogPanel` minimize toggle | `⟩` `⟨` | `disclosure` (CSS rotates 180°) |
| `UsageBar` branch mark | `⎇` | `vcs` |

Only `stop` is a new bitmap; the rest reuse existing glyphs. The minimize
toggle is the two-state case (record T5c brief §2): both states are the one
`disclosure` glyph, rotated by CSS — `⟩` open, `⟨` (180°) minimized — so the
pair can never misalign the way two separate characters could.

`comms.channelGlyph` returns the group-DM marker as DATA (a string in the
marker column beside `@` and `#`), so a `<Glyph>` cannot go there. The old `⌗`
U+2317 was uncovered; it swaps to `&` U+0026, covered by the brand face — a
bitmap for one kind alone would mix glyph and character in one column.

Kept as text — the `→` U+2192 is in the cmap, so a bitmap is a style call, not
a coverage fix, and the typographic arrow reads at least as well:

| Site | Char | Why |
| --- | --- | --- |
| `Bridge` lane open cue (2) | `→` | reads no better as a bitmap at 11px |
| `SettingsView` map arrows (2) | `→` | chrome arrow; kept with the prose |
| `SettingsView` prose arrows (2) | `→` | mid-sentence — a bitmap breaks type |

## Tabs

- **Class:** `.cx-tabs` · `data-orientation="h | v"`, with `.cx-tab` items
Expand Down
Loading