Skip to content
ArcadiaDesign
Describe a change, @ to add files

TSX

The text trigger every picker uses: workspace, branch, model, environment. No background, ever: the colour steps from text-2 to text-1 only after the pointer rests 80ms (hover intent) or while its popup is open, so sweeping across a toolbar doesn't flicker. The label is text, set on its capitals; past the trigger's maximum width it takes the longest of its forms that fits, then fades its end. What stands beside it goes in icon.

Examples

With its menu

Compose it as a MenuTrigger with render; the menu owns the choice, the trigger shows it.

A glyph of its own

icon takes an element as well as an icon's name: a ProviderMark, or a glyph the product draws as wide as an icon beside the label.

It sits where an icon does, centred on the label's capitals, in the glyph's colour.

In a toolbar

Beside standalone icon buttons, weight="medium" sets the label at 500 and its glyphs at the medium stem, 1.35px at 13px, so one toolbar strokes within 0.15px of the buttons' 1.5px.

Tones

neutral (text-2) for the value that matters most, such as the workspace or the model; muted (text-3) for context, such as the branch or the environment; emphasis rests at text-1.

Kind and state

rootStyle takes where the trigger sits (margins, self-alignment, flex and grid placement, size bounds) and the knobs below, each a token of its kind. A colour, a raw length or any other property is a type error: a look that comes up twice becomes a variant.

TSX
--pt-h
Ref<Control>Default var(--control-sm)
Height.
--pt-px
Ref<Space>Default var(--space-2)
The text side: padding before a label (8, 10 at md), and after it with no chevron.
--pt-ps
Ref<Space> | DerivedDefault var(--pt-px)
Padding before the icon or label: the text side, or (h − icon)/2 before an icon (R2).
--pt-pe
Ref<Space> | Derived
Padding after the chevron: (h − chevron)/2 (R2).
--pt-radius
Ref<Radius>Default var(--radius-md)
Corner radius (a pill is full).
--pt-max-w
Ref<Measure>Default 240px
Width past which the label shortens, then fades.
--pt-label-display
"block" | "none"Default block
none hides the label and leaves the icon (a squeezed toolbar); the accessible name still says the value.
--pt-fg
PaintDefault var(--text-2)
Label colour at rest.
--pt-fg-hover
PaintDefault var(--text-1)
Label colour, hover intent or popup open.
--pt-icon
PaintDefault var(--icon-3)
Leading glyph colour at rest.
--pt-icon-hover
PaintDefault var(--icon-1)
Leading glyph colour, hover intent or popup open.
--pt-sub
PaintDefault var(--text-3)
Secondary value colour at rest.
--pt-sub-hover
PaintDefault var(--text-2)
Secondary value colour, hover intent or popup open.
--pt-chevron
Paint | InkDefault currentColor
Chevron colour (the label's by default).
--pt-chevron-opacity
numberDefault 0.7
Chevron opacity at rest (1: never dimmed).

Each colour has a rest knob and a hover knob (--pt-fg, --pt-fg-hover), and disabled drops them to text-4 and icon-4. A glyph passed as icon takes the glyph's live colour as currentColor, and a provider mark as its ink.

A <button>. As a MenuTrigger it gets aria-haspopup and aria-expanded, and focus moves into the menu and back. The icon and the chevron are decorative, so the accessible name is the visible value alone.

A value without its context reads poorly ("main, button"), so name what is being picked: aria-label="Branch: main", as in the example above. Keep the visible label in that name, so voice control can still find it by what it shows.

EnterSpace
Open the picker's menu
Esc
Close it and return focus

PickerTrigger

labelrequired
string
The current value ("lumen"): text on its capitals (R7); a glyph beside it goes in icon.
forms
readonly string[]
Shorter ways to say label, longest first. Default: none up to three words with an icon (whole or the icon), else whole words or parts.
last
boolean
false: text follows, so a cut form ends undimmed.
tooltip
false
false: the product's own Tooltip says the whole value (onShortChange).
onShortChange
(short: boolean) => void
Told when it shows less than its whole value.
icon
IconName | ReactElement
Leading glyph at icon-3: an icon's name, or an element (a ProviderMark) at the label's icon size, in the glyph's colour, centred on the label's capitals.
sub
string
Secondary value after the label, a step quieter, the first to go. Text, as the label is.
emphasis
boolean
Rest at text-1 instead of text-2.
tone
"neutral" | "muted"
neutral rests at text-2 (workspace, model); muted at text-3 (branch, environment).
weight
"regular" | "medium"Default "regular"
size
"sm" | "md"Default "sm"
24 (toolbars) or 28.
shape
"rounded" | "pill"Default "pill"
chevron
IconName | falseDefault "chevron-down"
The trailing chevron. false hides it.
flush
boolean
Sides hang past its box (IconButton flush).
rootStyle
PickerTriggerStyle
Typed StyleX override: where the trigger sits and its --pt-* knobs.
render
RenderProp<{ disabled: boolean }>
Replace the rendered element, e.g. render={<a href="/settings" />}, or a function of props and state.
disabled
boolean
Native disabled: no pointer events, no tooltip, skipped by Tab.
focusableWhenDisabled
boolean
Keep a disabled control focusable and hoverable (aria-disabled), so a tooltip can say why.
nativeButton
boolean
Button semantics, inferred from what renders: a <button> is native, an <a> stays a link, anything else gets role="button" and key handling. false forces button semantics on whatever renders (a link acting as a button).
className
string
A product's hook class, retiring: new code uses rootStyle (ui.lint kit-classname counts the rest).

Rest props go to <button> props.