Info tip

An (i) next to a section heading or a field label that opens a short explanation on click or tap. React <InfoTip> (packages/ui/src/components/InfoTip.tsx) renders the button .acrm-infotip-btn and a portalled panel .acrm-infotip-panel (apps/web/src/ds/info-tip.css). Owner decision 3 Oct 2026: no long descriptive text in the base UI — explanations live behind (i).

When to use

  • An explanation that changes a decision: a consequence ("a disabled type is no longer offered"), irreversibility ("the log cannot be edited or deleted"), or where data comes from ("counted only for calls placed through the CRM").
  • Next to a section heading — <SectionBlock info="…"> places the (i) after the title, outside the collapse toggle.
  • Next to a field label — <span className="flabel">Label <InfoTip>…</InfoTip></span> or Field labelExtra.
  • At most two sentences; the panel is capped at 280px.

When not to use

  • State, errors, data and warnings — they stay visible in the base UI ("Connected to the provider.", "Default 5 $ applies now.").
  • The only instruction needed to complete an action — keep it visible as a hint under the field.
  • An example of the expected value — use the field placeholder.
  • The name of an icon action or the reason it is disabled — use Tooltip (hover/focus, no click).
  • Text that only repeats the heading — delete it.
  • Never leave a section as a bare heading with everything hidden: if nothing on the screen makes sense without the explanation, the screen needs redesign, not an (i).

Anatomy

  • Button: 24px (--control-h-sm), radius --radius-sm, glyph info-circle at --ico-sm, colour --fg-secondary (a control, ≥ 3:1); hover and open state --fg on --hover-surface.
  • Touch target: on pointer: coarse an invisible ::before extends the hit area to --tap-min (44px); the glyph and highlight stay 24px so they do not cover the heading next to it.
  • Inside a label (.flabel, Field label): margin-inline-start: var(--sp-1) and negative block margin, so the 24px button does not make the label row taller.
  • Panel: popover surface — --surface-100, 1px --border-strong, --radius-md, --shadow-pop, padding --sp-3, text var(--small) 400 --fg; max-width: 280px, layer 101 (above dialogs, below Tooltip 120).
  • Position: below the (i), aligned to its start; kept 16px inside the viewport and flipped above when there is no room below.

Behaviour

  • Opens on click or tap, closes on a second click, a tap or click outside the button and panel, Esc, window resize or scroll.
  • Esc closes only the panel (caught in capture phase), so an InfoTip inside a Dialog does not close the dialog; focus returns to the (i).
  • Portalled into the current portal root, so it works inside modal dialogs (not inert).

Hosts

  • Section heading — <SectionBlock info="…">.
  • Field label — Field labelExtra; the (i) stands next to the <label> in .acrm-field-head, never inside it (a <label> passes clicks to its control — inside it a click on the label text would open the panel; fixed in acrm !4522).
  • Form-less row label .flabel, dialog label .dlg-label, table column header SegCol.info (the click does not sort or open the column menu).
  • Never inside a button. A toggle or checkbox explanation goes into the (i) of its field.
  • No host (empty state): one sentence stays visible instead.
  • Use the default accessible label; never hard-code Czech text into label.

Best practices

Do

  • Write the consequence, not the mechanics: "Existing products are kept." rather than "This toggle updates the product type flag."
  • Keep the visible state next to the (i) — the (i) explains, the base UI informs.
  • One (i) per heading or label.

Don't

  • Don't put links, buttons or form controls inside the panel — it is a note, not a popover menu.
  • Don't use (i) as a warning icon; warnings stay visible with their own tone.
  • Don't stack (i) on every field of a form — if each field needs one, the labels need rewriting.

Source: docs/popover/info-tip.usage.md · GitLab