Skip to content

Pill

A lozenge that floats an in-progress status over the page. Use it for information that keeps updating: a recording timer, a build still running.

tsx
import { Pill } from 'neba';

<Pill startIcon={<DotIcon />} color="danger" title="Recording" />;

Props

PropTypeDefaultDescription
variantshared'solid' | 'outline' | 'text''solid'Weight of the surface, said the way a *control* says it: the surface takes the tint, as on Button and Chip
sizeshared'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Height and type scale
colorshared'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''secondary'Semantic colour role. `secondary` here rather than `primary`, because the object this shape is borrowed from is very nearly neutral black
densityshared'default' | 'compact''default'Padding only: never the height, never the type scale
elevationshared0 | 1 | 2 | 32Drop shadow depth. `2` against the `0` everything else defaults to, and not an inconsistency: a Pill is defined by not being part of the page, and a lozenge floating flat on the content it floats over reads as a mistake
startIconReactNodeThe leading slot: a glyph, an avatar, a status dot, a photo. It is given a square box of its own and clipped to a circle, so an `<img>` lands in it as readily as an icon does
titleReactNodeThe headline in the middle: what the pill is currently about. Centred, with generous room either side of it
descriptionReactNodeThe second line, under the title. One step down and one step lighter
endIconReactNodeThe trailing slot. Outside the pressable area, so it can be a control of its own
detailsReactNodeThe second half, revealed when `expanded`. The pill grows downward into it rather than swapping to a different shape: one object saying more, which is the whole idea being borrowed
expandedbooleanfalseWhether `details` is showing
positionshared'static' | 'sticky' | 'fixed''static'How it sits in the page’s scroll. `fixed` pins it against the viewport and centres it horizontally, which is the arrangement this shape exists for
sideshared'top' | 'bottom''top'Which edge it is held against when `position` is not `static`
onClickMouseEventHandlerPassing it makes the row a real button. `endIcon` stays outside it: a `<button>` inside a `<button>` is markup the browser rewrites on parse
childrenReactNodeThe middle: a line of text, a pair of small readouts

Every native <div> attribute passes through except title, which here is the pill's headline rather than the browser's tooltip.

The row has three parts: startIcon on the leading edge, endIcon on the trailing one, and the middle (title, description and anything in children) centred between them with generous padding either side.

color defaults to secondary and elevation to 2: it is meant to float, so the shadow is on by default.

Examples

title and description

title is the line the pill is about and description is the line under it. Both are optional: a title on its own keeps the row one line tall and the shape a true stadium, and adding a description grows it into a rounded rectangle with the same corner.

startIcon and endIcon

The leading slot is a square box clipped to a circle, so an <img> fills and crops it the way an avatar should. The trailing slot sits outside the pressable area, so it can hold a readout or a control of its own.

details and expanded

details grows a second area beneath the pill. expanded makes that controlled, and onClick attaches the toggle. It expands by animating its height, the same way an Accordion panel does.

The details area is inert while closed. Focus can still enter a zero-height element, so aria-hidden alone would leave a keyboard user tabbing into something invisible.

variant and size

As far as colour goes a Pill is a control rather than a container: like a Button or a Chip, the surface itself takes the colour.

position and side

The same vocabulary Toolbar uses. fixed pins it against the viewport and centres it horizontally with auto margins, so it stays centred under RTL.

tsx
<Pill
  position="fixed"
  side="top"
  startIcon={<BuildIcon />}
  color="info"
  title="Building — 2 of 7"
/>

When to use something else

  • A token inside a run of content (a tag, a filter, a status) is a Chip.
  • A bar of controls along the top of a page is a Toolbar.
  • Something the reader has to wait on and cannot dismiss is an Overlay; something they can dismiss is a Toast.

Released under the MIT License