Lozenge
A status: where a record stands right now. Stages, Job status, Do not contact, meeting status. Soft fill with dark text of the same hue, so it reads at a glance without shouting.
Playground
Change the controls to try each prop. The code under the preview updates as you go and lists only the props you changed; copy it into your page.
import { Lozenge } from '@/ui/lozenge';<Lozenge> On hold</Lozenge>Stage
Pass the stage's phase and the lozenge picks the hue: Long list to Interview are grey, CV sent and the client rounds blue, Offer purple, Placed green. The same set appears on the list, the board, pills and column dots. The label names the stage.
import { Lozenge } from '@/ui/lozenge';
export default function LozengeStages() {
return (
<div className="flex flex-wrap items-center gap-075">
<Lozenge phase="working">Long list</Lozenge>
<Lozenge phase="working">Short list</Lozenge>
<Lozenge phase="working">Outreach</Lozenge>
<Lozenge phase="working">Interview</Lozenge>
<Lozenge phase="client">CV sent</Lozenge>
<Lozenge phase="client">1st</Lozenge>
<Lozenge phase="client">2nd</Lozenge>
<Lozenge phase="client">Final</Lozenge>
<Lozenge phase="offer">Offer</Lozenge>
<Lozenge phase="placed">Placed</Lozenge>
</div>
);
}Appearance
Neutral
The default, for most states, including early stages.
import { Lozenge } from '@/ui/lozenge';
export default function LozengeNeutral() {
return (
<div className="flex items-center gap-075">
<Lozenge>Briefing</Lozenge>
<Lozenge>On hold</Lozenge>
</div>
);
}Success
Live or done well: an Open Job, Placed, Won.
import { Lozenge } from '@/ui/lozenge';
export default function LozengeSuccess() {
return (
<div className="flex items-center gap-075">
<Lozenge appearance="success">Open</Lozenge>
<Lozenge appearance="success">Won</Lozenge>
</div>
);
}Information
With the client: CV sent and the client rounds.
import { Lozenge } from '@/ui/lozenge';
export default function LozengeInformation() {
return <Lozenge appearance="information">CV sent</Lozenge>;
}Discovery
An offer is out.
import { Lozenge } from '@/ui/lozenge';
export default function LozengeDiscovery() {
return <Lozenge appearance="discovery">Offer</Lozenge>;
}Warning
Waiting on someone, or due soon.
import { Lozenge } from '@/ui/lozenge';
export default function LozengeWarning() {
return <Lozenge appearance="warning">Contacting</Lozenge>;
}Danger
Lost, failed, or Do not contact.
import { Lozenge } from '@/ui/lozenge';
export default function LozengeDanger() {
return <Lozenge appearance="danger">Lost</Lozenge>;
}Meeting
Meeting status only.
import { Lozenge } from '@/ui/lozenge';
export default function LozengeMeeting() {
return <Lozenge appearance="meeting">Client meeting</Lozenge>;
}Leading icon
A 12px icon goes before the label, 4px from it, with 6px padding on its side. Add one only where it adds meaning.
import { ProhibitIcon } from '@phosphor-icons/react';
import { Lozenge } from '@/ui/lozenge';
export default function LozengeWithIcon() {
return (
<Lozenge appearance="danger">
<ProhibitIcon aria-hidden />
Do not contact
</Lozenge>
);
}Long label
A lozenge is at most 200px wide. A longer label ends in an ellipsis, and hovering shows the full label in a tooltip.
import { Lozenge } from '@/ui/lozenge';
export default function LozengeLongLabel() {
return <Lozenge>Kept for matching at Halcyon Bank after the final round</Lozenge>;
}In a table row
A 22px lozenge in a 36px row. It keeps its 6px radius in the grid.
import { Lozenge } from '@/ui/lozenge';
export default function LozengeInATableRow() {
return (
<div className="flex h-9 w-full max-w-120 items-center border-y border-border bg-surface text-body">
<span className="w-45 shrink-0 px-150 font-medium">Maya Chen</span>
<span className="flex h-9 w-30 shrink-0 items-center border-s border-border px-150">
<Lozenge phase="client">CV sent</Lozenge>
</span>
<span className="flex h-9 grow items-center border-s border-border px-150 text-text-subtle">2h ago</span>
</div>
);
}Item
A row in a list with no columns: Inbox threads, Needs you, tasks, connected accounts, search results. A leading slot, a title, an optional second line, and a trailing slot.
Metric tile
One number for the period, how it moved against the previous period, its target, and a small chart of the period. The Dashboard's headline grid is six of them.