Rost
← All components
component

Toggle

A 40×40 icon button that stays on or off, alone or as one choice in a group.

In codeContract: stableGuidance: agreedContract on GitHubFigma 168:1149
Default · selected
Default · not selected
Disabled · selected
Disabled · not selected
labelled · off
labelled · on
labelled · disabled

Hover, press or tab to one to see the other 6 states.

When to use

  • Switching a view or a filter on and off, when the change happens straight away.
  • Used to pick one option from a short set, as a group: a year switcher, a view switcher.

When not to use

  • Doing something. That's IconButton. A toggle remembers, a button doesn't.
  • A settings-style switch with a label. There isn't one in the kit yet, so ask for one rather than stretching Toggle.

Behaviour

It changes with selected and state. Off, it's a plate with 12px corners on the secondary surface, faded down. On, it becomes a fully round primary pill. The change of shape is part of the signal, not just the colour.

Accessibility

  • Alone: <button aria-pressed="true|false">.
  • Group: role="radio" with aria-checked, inside a role="radiogroup" that has a name. Arrow keys move between options, Tab gets you in and out.
  • Name: aria-label when it's icon only.
  • Focus: focus-ring (2px, actions/primary/focus/focus-ring when it's on), on :focus-visible.
  • Colour: on and off show in the shape (12px corners to fully round) as well as the colour.

Content

An icon, or a short text label: a year, a number, one word. The label makes the toggle grow wider than 40px, and it never wraps. Figma only draws the icon-only one.

Props

PropTypeValuesDefault
selectedbooleanfalse
labelslot
labelledbooleanfalse

States: Default, Hover, Pressed, Focus, Disabled.

Where it's used

Where code differs on purpose

Values

Straight from the contract. Each value sits next to its token, because six tokens here all come out as #3a3a3a and the colour alone can't tell you which one is right.

Never changes

PartPropertyValueToken
rootjustify-contentcenterlayout
rootalign-itemscenterlayout
rootdisplayinline-flexlayout
rootvertical-alignmiddlelayout
rootpositionrelativelayout
rootbackgroundnoneFigma frame size
rootbordernoneFigma frame size
rootcursorpointerFigma frame size
rootoutlinenoneFigma frame size
rootgap8pxspacing/gap/small
rootpadding-left20pxspacing/gap/medium-large
rootpadding-right20pxspacing/gap/medium-large
rootpadding-top0pxspacing/gap/none
rootpadding-bottom0pxspacing/gap/none
rootwidth40pxspacing/size/medium
rootheight40pxspacing/size/medium
backgroundpositionabsolutelayout
backgroundinset0layout
backgroundpointer-eventsnoneFigma frame size
icons-arrow-leftflex-shrink0layout
icons-arrow-leftpositionrelativelayout
icons-arrow-leftoverflowcliplayout
icons-arrow-leftwidth20pxspacing/size/xsmall
icons-arrow-leftheight20pxspacing/size/xsmall
labelpositionrelativelayout
labelwhite-spacenowraplayout
labelfont-family'General Sans Variable'font-family/base
labelfont-weight500typography/body/font-weight/medium
labelline-height22pxtypography/body/line-height
labelfont-size16pxtypography/body/font-size
labelletter-spacing0pxtypography/body/letter-spacing
labelfont-variant-numerictabular-numsFigma frame size
glyphdisplayblocklayout
glyphwidth100%layout
glyphheight100%layout
glyphbackgroundcurrentColorno token yet
glyphmaskurl(./icon-arrow-left.svg) center / contain no-repeaton purpose: The icon file itself, `assets/icons/arrow-left.svg`, the same shape as Figma's `Union` layer.
focus-ringdisplaynonelayout
focus-ringpositionabsolutelayout
focus-ringinsetcalc(-1 * var(--spacing-gap-2xsmall))layout
focus-ringborder-stylesolidno token yet
focus-ringborder-width2pxspacing/outline/medium
focus-ringpointer-eventsnoneFigma frame size

Changes by variant

background.background5
state=Default, selected=False#3a3a3aactions/secondary/regular/default/background
state=Hover, selected=False#747573actions/secondary/regular/hover/background
state=Pressed, selected=False#999actions/secondary/regular/pressed/background
state=Disabled, selected=False#3a3a3aactions/secondary/regular/disabled/background
state=Focus, selected=False#3a3a3aactions/secondary/regular/focus/background
background.border-color5
state=Default, selected=False#edededactions/secondary/regular/default/outline
state=Hover, selected=False#edededactions/secondary/regular/hover/outline
state=Pressed, selected=False#edededactions/secondary/regular/pressed/outline
state=Disabled, selected=False#edededactions/secondary/regular/disabled/outline
state=Focus, selected=False#edededactions/secondary/regular/focus/outline
background.border-radius5
state=Default, selected=False12pxspacing/radius/medium
state=Hover, selected=False12pxspacing/radius/medium
state=Pressed, selected=False12pxspacing/radius/medium
state=Disabled, selected=False12pxspacing/radius/medium
state=Focus, selected=False12pxspacing/radius/medium
background.border-sides5
state=Default, selected=Falseleft toplayout
state=Hover, selected=Falseleft toplayout
state=Pressed, selected=Falseleft toplayout
state=Disabled, selected=Falseleft toplayout
state=Focus, selected=Falseleft toplayout
background.opacity5
state=Default, selected=False0.24opacity/gentle
state=Hover, selected=False0.32opacity/mild
state=Pressed, selected=False0.32opacity/mild
state=Disabled, selected=False0.32opacity/mild
state=Focus, selected=False0.24opacity/gentle
focus-ring.border-color2
state=Focus, selected=True#b6ffdaactions/primary/focus/focus-ring
state=Focus, selected=False#999actions/secondary/regular/focus/focus-ring
focus-ring.border-radius2
state=Focus, selected=True10000pxspacing/radius/full
state=Focus, selected=False16pxspacing/radius/large
focus-ring.display2
state=Focus, selected=Trueblocklayout
state=Focus, selected=Falseblocklayout
icons-arrow-left.color10
state=Default, selected=True#3a3a3aactions/primary/default/icon
state=Default, selected=False#00d669actions/secondary/regular/default/icon
state=Hover, selected=True#3a3a3aactions/primary/hover/icon
state=Hover, selected=False#00b450actions/secondary/regular/hover/icon
state=Pressed, selected=True#3a3a3aactions/primary/pressed/icon
state=Pressed, selected=False#00d669actions/secondary/regular/pressed/icon
state=Disabled, selected=True#3a3a3aactions/primary/disabled/icon
state=Disabled, selected=False#00d669actions/secondary/regular/disabled/icon
state=Focus, selected=True#3a3a3aactions/primary/focus/icon
state=Focus, selected=False#00d669actions/secondary/regular/focus/icon
label.color10
state=Default, selected=True#060805actions/primary/default/label
state=Default, selected=False#d3d9d5actions/secondary/regular/default/label
state=Hover, selected=True#060805actions/primary/hover/label
state=Hover, selected=False#edededactions/secondary/regular/hover/label
state=Pressed, selected=True#060805actions/primary/pressed/label
state=Pressed, selected=False#d3d9d5actions/secondary/regular/pressed/label
state=Disabled, selected=True#060805actions/primary/disabled/label
state=Disabled, selected=False#d3d9d5actions/secondary/regular/disabled/label
state=Focus, selected=True#060805actions/primary/focus/label
state=Focus, selected=False#d3d9d5actions/secondary/regular/focus/label
root.background5
state=Default, selected=True#00d669actions/primary/default/background
state=Hover, selected=True#00b450actions/primary/hover/background
state=Pressed, selected=True#00913aactions/primary/pressed/background
state=Disabled, selected=True#00d669actions/primary/disabled/background
state=Focus, selected=True#00d669actions/primary/focus/background
root.border-radius10
state=Default, selected=True10000pxspacing/radius/full
state=Default, selected=False12pxspacing/radius/medium
state=Hover, selected=True10000pxspacing/radius/full
state=Hover, selected=False12pxspacing/radius/medium
state=Pressed, selected=True10000pxspacing/radius/full
state=Pressed, selected=False12pxspacing/radius/medium
state=Disabled, selected=True10000pxspacing/radius/full
state=Disabled, selected=False12pxspacing/radius/medium
state=Focus, selected=True10000pxspacing/radius/full
state=Focus, selected=False12pxspacing/radius/medium
root.box-shadow5
state=Default, selected=Trueinset var(--spacing-outline-small) var(--spacing-outline-small) 0 0 var(--actions-primary-default-outline)on purpose: Figma's 1px left and top stroke, drawn inside the shape as Figma draws it. The width and colour are tokens.
state=Hover, selected=Trueinset var(--spacing-outline-small) var(--spacing-outline-small) 0 0 var(--actions-primary-hover-outline)on purpose: Figma's 1px left and top stroke, drawn inside the shape as Figma draws it. The width and colour are tokens.
state=Pressed, selected=Trueinset var(--spacing-outline-small) var(--spacing-outline-small) 0 0 var(--actions-primary-pressed-outline)on purpose: Figma's 1px left and top stroke, drawn inside the shape as Figma draws it. The width and colour are tokens.
state=Disabled, selected=Trueinset var(--spacing-outline-small) var(--spacing-outline-small) 0 0 var(--actions-primary-disabled-outline)on purpose: Figma's 1px left and top stroke, drawn inside the shape as Figma draws it. The width and colour are tokens.
state=Focus, selected=Trueinset var(--spacing-outline-small) var(--spacing-outline-small) 0 0 var(--actions-primary-focus-outline)on purpose: Figma's 1px left and top stroke, drawn inside the shape as Figma draws it. The width and colour are tokens.
root.cursor2
state=Disabled, selected=TruedefaultFigma frame size
state=Disabled, selected=FalsedefaultFigma frame size
root.min-width1
labelled=True40pxspacing/size/medium
root.opacity2
state=Disabled, selected=True0.24opacity/gentle
state=Disabled, selected=False0.24opacity/gentle
root.width1
labelled=Trueautono token yet