Files
hermes-ui/docs/chat-chain-changes/2026-10-19-chat-cyber-skeleton-pass.md
T
toor 5e1003ceb7
Build / build (push) Canceled after 0s
Playwright / e2e (push) Canceled after 0s
replace the monochrome theme with the CYBER neon-cyan skin
The project shipped a black-and-white theme that was only half converted:
the login page looked right, the message page was halfway, and the
settings page had not been started. This finishes the move to the CYBER
reference in prototype_reference/.

Colors now come from a single token source (styles/variables.scss), where
every semantic color is declared twice: once as OKLCH for the CSS, and
once as an RGB triple so translucent variants can be built as
rgba(var(--*-rgb), alpha). Cyan is the system itself, amber means the user
has to intervene, green means the machine is working, and red only ever
means something broke. The RGB triples are derived from the OKLCH values
so the two declarations cannot drift apart.

Pages adopt the .cy-* shell classes from the reference (view, panel,
kpis, tabs, grid, table, field) instead of ad-hoc markup, which is what
makes 19 of 26 views consistent. The remaining seven are deliberately
bespoke: chat streams, the kanban board, the workflow canvas, the
terminal, and the missing-agent screen.

The chart palette and the kanban column colors move into single-source
modules so they cannot drift either. A new guard test rejects raw hex
colors, named colors, and literal RGB triples anywhere in the client
source, with an explicit exemption list for the places that genuinely
cannot read a CSS variable. The existing chat semantics spec keeps the
chat chain honest.

No behavior changes: no logic, no i18n keys, no data structures, and the
/chat-run event contract is untouched.
2026-10-20 11:17:46 +08:00

90 lines
4.2 KiB
Markdown

---
date: 2026-10-19
pr: pending
feature: Chat view CYBER pass — single-colour live ring, send-key neon tube, status LED, responsive outline
impact: The chat chain's "machine is working" indicator is now a single lime pulse instead of a six-colour cycle, the send key renders as a neon tube with the standard sweep instead of a flat grey block, the header carries a connection LED and a cyan press-light, and the Outline panel becomes an overlay at ≤1180px. Rendering-layer only — no store logic, no `/chat-run` payload, no markup semantics beyond one decorative status span, no event wiring changed.
---
# Chat view CYBER pass
Follow-up to `2026-10-19-three-colour-semantics.md`. That change split the
palette by meaning but left several call sites hardcoded, and the chat view was
still missing the page-level treatment the rest of the app had.
## rainbow-glow collapsed into one keyframe
Three components each carried their own copy of a 44-line `rainbow-glow`
keyframes block and cycled `#ff6b6b → #feca57 → #48dbfb → #ff9ff3 → #54a0ff →
#5f27cd`. Four semantic hues flashing in one animation means the indicator
carries no meaning at all — which is exactly what the three-colour rule exists
to prevent.
`live-ring` is now defined once in `global.scss` and pulses `--success`
(lime) between a dim and a bright ring. All three call sites use it:
- `MessageItem.vue` — `.speech-playing` on the message bubble
- `SessionListItem.vue` — `.streaming` ring on the agent logo
- `GroupMessageItem.vue` — `.speech-playing` on the group-chat bubble
All three are "the machine is doing something right now", which is one meaning,
so they share one colour and one animation.
## Send key
`ChatInput.vue` had `border: 0 !important` and `box-shadow: none !important`
on `.send-button`, which erased the neon tube that `global.scss` gives every
`.arco-btn-primary`. The disabled state was also a solid `#9f9f9f` block —
a hardcoded grey outside the palette. Both are gone; the button now inherits
the global tube + `neon-sheen` sweep and uses the standard dimmed-tube disabled
treatment.
Added `.send-button--stop`: while a run is streaming, the same button becomes
the stop control, which is a "needs you" action rather than a "system" action,
so it turns amber — the same semantic the approval card uses.
## Status LED
New `.cy-led` in `global.scss`: a 7px dot, lime with a glow and a slow
breathe when connected, red and static when not. A dead connection should not
look like it is still doing work, so the breathe animation only runs in the
connected state. Bound to `appStore.connected` in the chat header, reusing the
existing `sidebar.connected` / `sidebar.disconnected` strings.
## Session list current item
`.session-item.active` already had the soft cyan fill; the prototype's defining
feature is the 2px glowing left bar. Added via `inset` box-shadow rather than
`border-left`, which would have shifted the row's content by 2px.
## Header press-light
`.chat-header` gets a `radial-gradient` cyan wash from the top edge. Radial,
not linear — a linear gradient lights the whole strip evenly and loses the
"pressed from above" quality.
## Responsive
Verified the real implementation had only the 768px tier. Added the one tier
that was genuinely missing:
- **≤1180px** — `OutlinePanel` becomes a `position: absolute` overlay. Below
this width the message stream, Outline and tool panel cannot coexist as three
columns; the header's Outline button already toggles it, so no extra close
control is needed. Below 768px it keeps its existing narrower width.
- **≤900px** — the workspace badge hides. The session sidebar deliberately does
**not** hide at this width: it is controlled by the header toggle, and
removing the column would leave no way to open it.
## Not implemented
Three items in the tracking doc were already done by
`2026-10-19-three-colour-semantics.md` and are recorded there, not repeated
here: bubble role colours (cyan right edge on user, lime left edge on
assistant), the approval card's amber zone, and the three-segment context meter.
## Verification
`npm run harness:check`, `npm run test` and `npm run build` pass. The LED,
the send key's enabled/disabled/stop states, the active session row, and both
new breakpoints were checked in a browser.