fix
This commit is contained in:
1 parent
11ca2b7b79
commit
8f03c497af
1 file changed
+181
@@ -0,0 +1,181 @@
|
||||
# Agent instructions
|
||||
|
||||
Instructions for AI agents (and contributors) working in this repo. Currently
|
||||
covers the `otel-ui` frontend design system, since that's the active area of
|
||||
work; add sections here as other parts of the repo get their own conventions.
|
||||
|
||||
## otel-ui: design system
|
||||
|
||||
### The rule
|
||||
|
||||
**One theme, light and dark - that's it.** `otel-ui/src/index.css` defines a
|
||||
single set of `--ds-*` tokens with a dark variant (default) and a light
|
||||
variant (`:root[data-theme="light"]`). Never introduce a second palette, a
|
||||
third theme variant, or a new token namespace alongside `ds-*`. If a screen
|
||||
needs a color, it comes from this table or it doesn't exist yet - extend the
|
||||
table, don't invent a one-off.
|
||||
|
||||
The theme toggle lives in `TopBar.tsx`, persists to `localStorage`
|
||||
(`otel.ui.theme`), and is applied before first paint by an inline script in
|
||||
`index.html` so there's no flash of the wrong theme.
|
||||
|
||||
The repo still has a second, older color system - the MD3-style
|
||||
`--color-surface-container-*` / `--color-on-surface` / `--color-primary-container`
|
||||
tokens, also in `index.css` - left over from before this redesign. That system
|
||||
is **dead**, not a design choice: it exists only because not every screen has
|
||||
been migrated yet (see the checklist below). Never add new usages of it. Once
|
||||
the checklist is empty, delete that whole legacy `@theme` block plus the old
|
||||
Geist/Inter/JetBrains/Material-Symbols font `<link>` entries in `index.html`,
|
||||
so exactly one design system remains in the codebase.
|
||||
|
||||
### Token reference
|
||||
|
||||
Source of truth is `otel-ui/src/index.css` (`:root` and `:root[data-theme="light"]`).
|
||||
Tailwind utilities are generated as `bg-ds-*`, `text-ds-*`, `border-ds-*`.
|
||||
|
||||
| Token | Dark | Light | Used for |
|
||||
|---|---|---|---|
|
||||
| `ds-bg` | `#0D1014` | `#F4F2ED` | page ground |
|
||||
| `ds-chrome` | `#0B0E12` | `#FFFFFF` | icon rail, top bar |
|
||||
| `ds-surface` | `#14181E` | `#FFFFFF` | cards, panels |
|
||||
| `ds-surface-2` | `#191E26` | `#F7F5F0` | inputs, chips, selected row |
|
||||
| `ds-fill` | `#1D232B` | `#EDEAE3` | hairlines inside cards, chart bands, bar tracks |
|
||||
| `ds-line` | `#242B34` | `#E3E0D8` | card/control borders |
|
||||
| `ds-line-strong` | `#2A313B` | `#D6D2C8` | chip borders, neutral badges |
|
||||
| `ds-text` | `#E8ECF2` | `#161A1F` | primary text |
|
||||
| `ds-text-2` | `#98A3B2` | `#4F5964` | secondary text |
|
||||
| `ds-text-3` | `#8B96A6` | `#6B7480` | labels, metadata, muted text - this is the accessibility floor, don't go dimmer |
|
||||
| `ds-critical` / `ds-critical-bg` | `#FF6F5E` / `#2B1512` | `#C4402C` / `#FBE9E5` | breached threshold, open errors |
|
||||
| `ds-warn` / `ds-warn-bg` | `#F0B24A` / `#2A2011` | `#8A5D0E` / `#F9EFDA` | degraded but not (necessarily) user-visible |
|
||||
| `ds-ok` | `#4FCF9A` | `#1F7A56` | healthy, resolved, recovered |
|
||||
| `ds-accent` / `ds-accent-bg` | `#7B8CFF` / `#161B33` | `#3B4FC4` / `#E9ECFB` | the one interactive accent - primary buttons, selected segment, links, focus |
|
||||
| `ds-on-accent` | `ds-chrome` value | `#FFFFFF` | text on top of `ds-accent` |
|
||||
|
||||
**Colour is a signal, not decoration.** Chrome, borders and type are neutral.
|
||||
`ds-critical` / `ds-warn` / `ds-ok` only appear where a real measurement is
|
||||
out of its expected band or a real state changed (open vs resolved). A
|
||||
severity pill's color must correspond to an actual state, never picked for
|
||||
visual variety. Don't tint cards, headers or buttons "for interest."
|
||||
|
||||
### Fonts
|
||||
|
||||
Three families (`otel-ui/index.html` loads them; `index.css` exposes them as
|
||||
`--font-display` / `--font-ui` / `--font-data`, used via Tailwind's
|
||||
`font-[family-name:var(--font-display)]` arbitrary syntax):
|
||||
|
||||
- **Bricolage Grotesque** (`--font-display`) - page/card headings, big metric numbers.
|
||||
- **Instrument Sans** (`--font-ui`) - all other UI text and body copy. Also the
|
||||
new global default (`index.css`'s `@theme` overrides `--font-body`), so
|
||||
unmigrated screens already inherit this typeface even before their colors move.
|
||||
- **IBM Plex Mono** (`--font-data`) - anything a person would copy or grep:
|
||||
ids, `key=value` attribute pairs, timestamps, durations, service names.
|
||||
|
||||
Never Inter, Roboto, Arial, or a new font stack.
|
||||
|
||||
### Layout shell (already built - reuse, don't rebuild)
|
||||
|
||||
- `otel-ui/src/components/layout/IconRail.tsx` - 72px fixed icon rail, global nav, one `aria-label` per icon.
|
||||
- `otel-ui/src/components/layout/TopBar.tsx` - 58px fixed top bar: search, time range, theme toggle, auth.
|
||||
- `otel-ui/src/components/FilterBar.tsx` - generic filter bar (optional scope segmented control, removable chips, dashed add-filter, an always-visible match readout, clear-all). Reuse this on every screen that lists things instead of building a bespoke filter row.
|
||||
- `App.tsx` wires the shell globally and renders the single page-level `<main>`. Screens render inside it - see pitfall #2 below.
|
||||
|
||||
### Screen pattern
|
||||
|
||||
Established by `IssuesVisualizer.tsx` (the triage overview) and
|
||||
`RumSessionsVisualizer.tsx` (real-user sessions) - follow this shape for the
|
||||
remaining screens:
|
||||
|
||||
- `<FilterBar />` at the top of the screen's content.
|
||||
- A main content column (`flex-1`) plus an optional fixed-width aside
|
||||
(~340-420px) for supporting stats/panels.
|
||||
- Cards: `rounded-[14px] border border-ds-line bg-ds-surface`, **no shadows,
|
||||
no gradients** - depth comes from the border and ground color alone.
|
||||
- No per-service rainbow badges. `getServicePalette` in `otel-utils.ts` (the
|
||||
gradient hash-to-color picker) is legacy: per the original design spec, a
|
||||
muted per-service palette is reserved for trace-waterfall span coloring
|
||||
only, never for general UI chrome like service badges. Use a neutral
|
||||
`border-ds-line-strong text-ds-text-2` badge instead.
|
||||
- Real `<button>` / `<a href>` / `<input>` + `<label>` only. Never `onClick`
|
||||
on a `div` or `span[role=button]`. `aria-label` on every icon-only control;
|
||||
`aria-hidden="true"` on decorative SVG icons (use `lucide-react`, not the
|
||||
Material Symbols icon font - see pitfall below).
|
||||
|
||||
### Pitfalls hit migrating Issues and RUM sessions - avoid repeating these
|
||||
|
||||
1. **No nested `<button>` elements.** Browsers implicitly close the outer
|
||||
`<button>` the moment they hit an inner one, which silently breaks click
|
||||
handling on whatever's after it in the DOM (this shipped once, undetected
|
||||
until manual testing). If a row/card needs both "click to expand" and
|
||||
inner action buttons, make the expandable area its own `<button>` and put
|
||||
the action buttons as **siblings**, not children.
|
||||
2. **No nested `<main>` landmarks.** `App.tsx` already renders one `<main>`;
|
||||
a screen component must not render its own - use a `<div>`.
|
||||
3. **`whitespace-nowrap` + `shrink-0` on fixed-height pills/badges.** Without
|
||||
them, a longer label silently wraps onto two lines and blows out the
|
||||
pill's height inside its flex row - easy to miss until you test with real
|
||||
(longer) data or a narrower viewport.
|
||||
4. **Never fabricate data.** Before adding a metric, column, or button, check
|
||||
whether the field actually exists in the real data model - the backend API
|
||||
response, or for RUM specifically, what `static/otel-rum.js` actually
|
||||
sends (see the header comment in `otel-ui/src/lib/rum-utils.ts` for a
|
||||
worked example of what's real vs. invented). If a design reference shows
|
||||
something with no backing data - the RUM mockup invented rage clicks, geo
|
||||
location, a "frustration score", and session replay, none of which this
|
||||
pipeline captures - drop it or replace it with the closest real,
|
||||
honestly-labeled equivalent. Never wire up a control that looks
|
||||
functional but isn't backed by anything.
|
||||
5. **Screenshots of a hidden Browser preview pane are unreliable** for
|
||||
`position: fixed` elements (stale compositor frame, even after a full
|
||||
reload). If a screenshot shows something that contradicts
|
||||
`getComputedStyle`, trust the computed style, front the tab, and re-check
|
||||
before concluding there's a real bug.
|
||||
|
||||
## Migration checklist
|
||||
|
||||
Converted to `ds-*` already: `App.tsx` (shell), `IconRail.tsx`, `TopBar.tsx`,
|
||||
`FilterBar.tsx`, `IssuesVisualizer.tsx` (Issues / triage overview, tab0),
|
||||
`RumSessionsVisualizer.tsx` (RUM sessions, tab7).
|
||||
|
||||
Everything below still renders with the legacy MD3 dark-only palette
|
||||
(`text-on-surface`, `bg-surface-container-*`, `bg-primary-container`,
|
||||
gradient badges, the Material Symbols icon font) and needs the same
|
||||
treatment. Sizes are current line counts, biggest first:
|
||||
|
||||
| File | Lines | Tab / role | Notes |
|
||||
|---|---|---|---|
|
||||
| `TraceVisualization.tsx` | 1866 | Traces & Spans (tab1) | Waterfall + span detail; closest existing screen to the design spec's `trace-waterfall.html` reference |
|
||||
| `MetricsVisualizer.tsx` | 1107 | Metrics & APM (tab2) | Imports `GaugeMeter.tsx` |
|
||||
| `StructuredLogTerminal.tsx` | 582 | Live Log Stream (tab3) | Uses Material Symbols icons |
|
||||
| `Tabs.tsx` (shell) | 513 | horizontal tab strip rendered above every screen | Gradient active-tab underline, slate colors; decide whether this strip is still needed now that `IconRail` is the primary nav, or whether it should just lose the gradient/slate styling |
|
||||
| `SearchAndWatcher.tsx` | 504 | Archive & Trap (tab6) | |
|
||||
| `ServiceGraph.tsx` | 495 | used by `TraceVisualization.tsx` | migrate alongside its caller |
|
||||
| `WaveformHistogram.tsx` | 385 | shown above every non-Issues/RUM tab's content | Uses Material Symbols icons; see the shared-chrome note below |
|
||||
| `GaugeMeter.tsx` | 372 | used by `MetricsVisualizer.tsx` | migrate alongside its caller |
|
||||
| `TrendsVisualizer.tsx` | 323 | Historical Trends (tab5, only when ClickHouse stats are configured) | |
|
||||
| `CommandAndQueryBar.tsx` | 251 | shown above every non-Issues/RUM tab's content | see the shared-chrome note below |
|
||||
| `TelemetryFilters.tsx` | 124 | conditionally shown above `Tabs.tsx` content | service multiselect + attribute exclusions; candidate to rebuild on top of `FilterBar.tsx` instead of restyling in place |
|
||||
| `SetupPanel.tsx` | 112 | Setup & Agent API (tab4) | |
|
||||
| `PatternsVisualizer.tsx` | 76 | Similarity Patterns (tab8) | |
|
||||
| `ViewErrorBoundary.tsx` | 62 | error fallback UI, wraps every tab's content | small, easy pass |
|
||||
| `RolloutsVisualizer.tsx` | 48 | Cluster Rollouts (tab9) | |
|
||||
| `AuthCallbackView` (inside `App.tsx`) | ~40 | OIDC callback screen | still 100% old tokens even though the rest of `App.tsx` is migrated |
|
||||
|
||||
**Shared chrome note:** `CommandAndQueryBar.tsx` (anomaly banner, filter
|
||||
status strip, NDJSON export) and `WaveformHistogram.tsx` (volume/error
|
||||
waveform with click-to-focus) are currently skipped entirely on the Issues
|
||||
tab (`isTriageOverview` branch in `App.tsx`) because their old styling would
|
||||
clash with the new `FilterBar`. When migrating the remaining tabs, decide
|
||||
per screen whether that real functionality gets folded into the screen's own
|
||||
`FilterBar`/content area (as happened for Issues and RUM sessions), or stays
|
||||
as shared chrome above the remaining tabs, restyled to `ds-*` tokens.
|
||||
|
||||
### Finding old-pattern usages
|
||||
|
||||
```sh
|
||||
grep -rlE "surface-container|text-on-surface|primary-container|bg-error-container|material-symbols-outlined" otel-ui/src
|
||||
grep -rlE "from-[a-z]+-[0-9]+ via-[a-z]+-[0-9]+|getServicePalette" otel-ui/src
|
||||
```
|
||||
|
||||
A file with zero hits and zero `ds-*` usage either has no meaningful styling
|
||||
of its own (a pure hook/context) or hasn't been looked at yet - check the
|
||||
checklist above.
|
||||
Reference in new issue
Block a user