Skip to content

FlowPill is the composer’s tool token: while the host has Research or Web Search switched on, a pill says so — an icon and label on the faint fill, with an X that reports removal through onRemove. Presence is the state: render a pill while its tool is on, and actually turning the tool off is the host’s move. The package ships no strings, so label and both tooltips are host-localized.

A pill per enabled tool
FlowComposer(
onSend: send,
leadingActions: [
FlowMenu(...),
if (researchOn)
FlowPill(
icon: Icons.school_outlined,
label: 'Research',
removeTooltip: 'Turn off Research',
onRemove: () => setResearch(false),
),
],
)

Pass a removeTooltip whenever onRemove is set — it is the X’s tooltip and its accessible name, so without one assistive tech announces an unnamed button.

On iOS and Android the label drops away to the design’s compact form — icon and X alone. The check reads the theme’s platform rather than the real one, like the menus’ sheet resolution, so hosts and tests can steer it without a device. showLabel forces either form outright; a host forcing icon-only on a hovering device can pass tooltip so the tool’s name survives as a hover:

Forcing the compact form
FlowPill(
icon: Icons.language,
label: 'Web Search', // still the accessible name
showLabel: false,
tooltip: 'Web Search',
removeTooltip: 'Turn off Web Search',
onRemove: () => setWebSearch(false),
)

A pill without onRemove is a static status token in full ink — not a disabled control, which is a deliberate difference from the suggestion row, where a null tap reads disabled. Disabling here is explicit: enabled: false sets the ink to onSurfaceDisabled and inerts the targets, keeping the fill and hairline in place:

The pill is drawn 32 tall to sit flush in FlowComposer.leadingActions, next to the add menu that toggles it. The action row doesn’t scroll, so keep concurrent pills few:

FlowPillStyle overrides the pill’s colors without touching the global tokens: backgroundColor, hoverColor, borderColor, iconColor, labelStyle (merged over the default label), and removeColor. Install one on FlowTheme.pillStyle for every pill; the widget’s style wins field by field.

  • icon — always drawn; the pill’s whole identity in the icon-only form.
  • label — always the pill’s accessible name, painted only in the labeled form.
  • onRemove — removal intent from the X; null leaves the X off entirely.
  • onTap — optional tap on the pill’s body, e.g. reopening the tool’s options; null leaves the body inert.
  • removeTooltip, tooltip — host-localized; the X’s name, and the body’s hover.
  • showLabel — null resolves by platform; true/false forces.
  • enabled — explicit disabling; static and disabled are different states.
  • padding (the design’s 8 horizontally) and borderRadius (8) override the metrics.