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.
90 lines
4.2 KiB
Markdown
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.
|