Skip to main content

EditorialMarks

Chart Partschart

SVG text that punches a plot-ground halo out from behind itself, so a label stays readable directly ON a mark instead of beside it.

import { HaloText } from "@elabs-ai/components-charts";
Install
npm install @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-charts

Skipping the @source line is the most common first failure: Tailwind does not scan node_modules, so every component renders unstyled. The one-time wiring

Prompt for your coding agent

Paste it into Claude Code, Cursor, Codex or any other coding agent. Text in [brackets] is yours to fill in.

Add the brand-ui HaloText chart (from @elabs-ai/components-charts) to this project.

1. Read https://elabs-ai.com/llms.txt first: it maps every package and the rules. If you can use MCP servers, connect https://elabs-ai.com/mcp and use its search, docs and tokens tools. If not, run the same lookups in the terminal: `npx -y @elabs-ai/components-cli search "<what you need>"` and `npx -y @elabs-ai/components-cli docs <Component>`.
2. Look HaloText up before writing code: `npx -y @elabs-ai/components-cli docs HaloText` prints its real props, variants, what it pairs with and what to avoid.
3. If @elabs-ai/components-charts is not installed yet: `pnpm add @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-charts` (or `npm install @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-charts`). If this is the first brand-ui package in the project, wire it once: import `@elabs-ai/components-tokens/styles.css` plus the `themes/light.css` and `themes/dark.css` stylesheets in the CSS entry, add one Tailwind `@source` line per installed @elabs-ai package (Tailwind does not scan node_modules, so without it everything renders unstyled), and wrap the app root in `ThemeProvider` from `@elabs-ai/components-tokens`.
4. Use it here: [the screen or file, and what it should show]
5. Rules: use only @elabs-ai/components-* components and the semantic tokens — no raw colours, no raw font sizes, no arbitrary Tailwind values. Look up each component's real props with the docs tool before you use it; never guess a prop.
6. Done means: the typecheck passes, `npx -y @elabs-ai/components-cli audit src --strict` reports nothing, and you have opened the app and looked at every screen you touched in the light and the dark theme.

Avoid

  • Hard-coding a paper colour for the halo — the halo IS the plot ground, so a literal white one becomes a white smear the moment the theme goes dark. It defaults to var(--chart-background) for that reason; an override names another token, never a colour.
  • Reaching for it to rescue low-contrast text — the halo separates a label from BUSYNESS, not from its ground. The ink still has to clear 4.5:1 against the card; a halo over a 3:1 label is still a 1.4.3 failure.
  • Widening the halo until labels stop colliding — the visible outline is half the width, so a wide one starts eating glyph counters and neighbouring letters. Move the label or drop one; 3px is the calibrated value.
  • Letting it carry the only copy of a number — the chart body is aria-hidden, so a halo label reaches no screen reader. Repeat the figure in the caption, the summary or the flip-to-table view.

Editorial marks — the vocabulary sheet. A SPECIMEN SHEET: one labelled cell per mark on a single SVG, so the layer reads as a vocabulary of ten distinct marks rather than as one chart with debris on it. Each specimen is isolated in its cell by a hairline divider; nothing overlaps a neighbour. The sheet is the surface the acceptance criteria are checked on: - Vocabulary renders in whatever theme the toolbar (or STORYBOOK_THEME) is set to, so the same story proves light and dark — HaloText's halo follows --chart-background, so on a dark card it is a DARK halo, with no dark: override anywhere. - VocabularyDecorated and VocabularyPlain put the sheet on an opt-in drafting ground (data-decoration-fade) at decoration 10 and 0. The marks are ink and do not change; what the dial does is paint the ground BEHIND them — visible at 10, transparent at 0 — and the halo cuts that ground away around every label, which is the halo doing its job on a busy surface.

Works with

Pairs with

  • Leader
  • PeakRing
  • Marginalia
  • HairlineFloor

Examples

3 live examples

Vocabulary Decorated

The sheet on a drafting ground at decoration 10. The marks are unchanged — they are ink — but the ground behind them is now drawn, and every halo cuts it away around its label. Compare `VocabularyPlain`, where the same ground is transparent. For decoration reaching a chart's FILLS, see `Charts/ChartFrame › With Source` at decoration 10.

Vocabulary Plain

The same ground at decoration 0 — the plain end of the dial, where the drafting layer is transparent: the proof that the marks owe nothing to decoration.

API

HaloText

PropTypeDescription
halostringThe halo colour. Defaults to `var(--chart-background)` — the plot ground — which is what makes the mark THEME-SAFE: on a light card the halo is light, on a dark card it is dark, with no `dark:` override and no literal anywhere. Override it only when the text sits on something other than the plot ground (a tooltip plate, a filled zone) — and then with another semantic token. The halo tracks the PLOT ground, not the card. The shipped themes declare that mirror in the token layer (`--chart-background: var(--card)` in `themes.css`), so the two agree by contract, not by coincidence. A theme that paints the plot on something other than `--card` must set `--chart-background` to that ground, or every halo punches a card-coloured hole in it.
haloWidthnumberHalo width in px (default 3). The visible halo is half of it — a stroke is centred.

Also accepts: SVGProps<SVGTextElement>

Theming

The tokens each state resolves to. Change the token and every theme follows.

StateToken
halostroke paints var(--chart-background) beneath the glyphs, under paint-order stroke
inkfill defaults to var(--chart-foreground)