Skip to content

Info sprinkle (inline help dot)

components specs/components/info-sprinkle.kmd

Lightweight inline help — small "i" icon next to a label that, on hover / focus / tap, surfaces a short tooltip. Mid-weight between no help and the larger guide-cue. Modeled after MongoDB LeafyGreen InfoSprinkle.

When this spec applies

Primary triggers

All triggers

Specification body

Component — Info sprinkle

Status: v0.1.0 — Draft.

R1 — Anatomy

  • Single "i" icon inscribed in a circle, 14×14px at default density.
  • Color: --kdr-text-muted by default; --kdr-accent on focus / hover.
  • Sits adjacent (right or left) to the label it annotates; 4px gap.

R2 — Trigger

SurfaceTrigger
Desktop / mouseHover (200ms delay)
KeyboardFocus (Tab to icon)
TouchTap (toggle)

Tooltip dismisses on:

  • Pointer leave (desktop)
  • Blur (keyboard)
  • Outside-tap (touch)
  • Esc (any input modality)

R3 — Tooltip content

  • 1–3 short lines max.
  • No actions (no buttons, no links) — pure informational.
  • If content needs actions or longer body, use specs/components/guide-cue.kmd instead.

R4 — Accessibility

  • Icon: <button> (not <span>) so it's focusable + keyboard-activatable.
  • Accessible name: derived from associated label + "more info" — e.g., "Project name — more info".
  • Tooltip: role="tooltip"; the icon button's aria-describedby points at the tooltip id.
  • Tooltip content remains in the DOM (just visually hidden) so screen-readers can read it without firing visual hover.

R5 — Internationalization

  • All tooltip body translatable per specs/i18n/contract.kmd.
  • Tooltip width: max 240px on desktop, full available width on mobile (minus 16px gutter).
  • Long strings wrap; no horizontal scroll.

R6 — Positioning

  • Uses Floating UI semantics; chooses side based on viewport.
  • 8px gap between icon edge and tooltip.

R7 — Multiple sprinkles per page

  • No upper limit, but author SHOULD reduce density to avoid noise; if more than half the form fields need a sprinkle, the form copy itself is unclear.

R8 — OUIA

Per specs/testing/ouia-test-hooks.kmd:

  • data-ouia-component-type="InfoSprinkle"
  • data-ouia-component-id="<sprinkle-id>" (auto-generated from associated label slug if not provided).
  • data-ouia-safe="true" always (icon is always ready; tooltip-open state is transient and not gated).

Não-escopo

  • Rich-content tooltips (use guide-cue or inline-definition).
  • Persistent visible tooltips (use callout-card instead).
  • Tooltip arrow customization (decorative; ships hard-coded).

Requirements (testable)

Requirement: Trigger surfaces the tooltip per input modality {#req-info-sprinkle-trigger}

The info sprinkle SHALL surface its tooltip on hover (with a 200ms delay) for pointer input, on focus for keyboard input, and on tap for touch input, and SHALL dismiss the tooltip on pointer-leave (desktop), blur (keyboard), outside-tap (touch), or Esc in any input modality.

Scenario: Hover reveals tooltip after delay

  • GIVEN an info sprinkle rendered next to a form label with its tooltip hidden
  • WHEN a mouse pointer hovers over the icon for 200ms
  • THEN the tooltip becomes visible

Scenario: Pointer leave dismisses tooltip

  • GIVEN an info sprinkle whose tooltip is visible from a hover
  • WHEN the pointer leaves the icon
  • THEN the tooltip is dismissed and no longer visible

Scenario: Esc dismisses regardless of modality

  • GIVEN an info sprinkle whose tooltip is currently open
  • WHEN the user presses the Esc key
  • THEN the tooltip is dismissed

Requirement: Keyboard focus toggles the tooltip {#req-info-sprinkle-keyboard}

The info sprinkle SHALL surface its tooltip when the icon receives keyboard focus via Tab and SHALL dismiss it on blur, so the help is reachable and readable without a pointer.

Scenario: Tab focus opens tooltip

  • GIVEN a page where the info sprinkle icon is in the tab order
  • WHEN the user tabs onto the icon
  • THEN the icon holds focus AND the tooltip becomes visible

Scenario: Blur closes tooltip

  • GIVEN an info sprinkle whose tooltip is visible from keyboard focus
  • WHEN focus moves away from the icon
  • THEN the tooltip is dismissed

Requirement: Tooltip content is purely informational {#req-info-sprinkle-content}

The info sprinkle tooltip SHALL contain only 1–3 short lines of informational text and SHALL NOT contain interactive actions such as buttons or links; content requiring actions or a longer body belongs to a different primitive.

Scenario: Tooltip renders text without interactive elements

  • GIVEN an info sprinkle configured with a short help string
  • WHEN the tooltip is rendered open
  • THEN the tooltip body shows at most 3 lines of text AND contains no button or link elements

Requirement: Accessible icon and described-by tooltip {#req-info-sprinkle-a11y}

The info sprinkle SHALL render the icon as a focusable, keyboard-activatable <button> with an accessible name derived from the associated label plus "more info", and its tooltip SHALL have role="tooltip" referenced by the button's aria-describedby, with the tooltip content remaining in the DOM (visually hidden) when closed so assistive technology can read it.

Scenario: Icon is a labelled button describing the tooltip

  • GIVEN an info sprinkle annotating a label with text "Project name"
  • WHEN the component is rendered
  • THEN the icon is a <button> element AND its accessible name is "Project name — more info" AND its aria-describedby references the tooltip element whose role is "tooltip"

Scenario: Tooltip content persists in the DOM when closed

  • GIVEN an info sprinkle whose tooltip is in the closed (visually hidden) state
  • WHEN the DOM is inspected
  • THEN the tooltip element with its content is present in the DOM AND is only visually hidden, not removed

Requirement: Positioning keeps a fixed gap and stays in viewport {#req-info-sprinkle-positioning}

The info sprinkle tooltip SHALL be positioned with an 8px gap between the icon edge and the tooltip and SHALL choose its side based on available viewport space so it does not overflow off-screen.

Scenario: Tooltip renders with the required gap

  • GIVEN an info sprinkle with ample space on all sides
  • WHEN the tooltip opens
  • THEN the measured distance between the icon edge and the nearest tooltip edge is 8px

Scenario: Side flips to stay within viewport

  • GIVEN an info sprinkle whose preferred side lacks room before the viewport boundary
  • WHEN the tooltip opens
  • THEN the tooltip is placed on an alternative side AND its bounding box stays fully within the viewport

Requirement: OUIA test hooks are present and stable {#req-info-sprinkle-ouia}

The info sprinkle SHALL expose OUIA hooks with data-ouia-component-type="InfoSprinkle", a data-ouia-component-id (auto-generated from the associated label slug when not provided), and data-ouia-safe="true" at all times since the icon is always ready.

Scenario: Component exposes OUIA attributes with auto-generated id

  • GIVEN an info sprinkle annotating a label with slug "project-name" and no explicit id provided
  • WHEN the component is rendered
  • THEN the root carries data-ouia-component-type="InfoSprinkle" AND data-ouia-component-id is derived from "project-name" AND data-ouia-safe equals "true"

Scenario: Safe stays true while tooltip is open

  • GIVEN an info sprinkle whose tooltip has just been opened
  • WHEN the OUIA attributes are read
  • THEN data-ouia-safe still equals "true"

References