Button
Starts an action. One primary per view, in magenta; secondary and ghost for the rest.
Concept · live ReactSource file: tokens.jsonReact component: Button
Content
- Name what happens: Send, Join Jake, Add someone.
- Use the person’s name when there is one.
- Sentence case, no exclamation marks.
Switch
Turns a setting on or off at once, with a visible label and an optional line of detail.
Concept · live ReactSource file: tokens.jsonReact component: Switch
Try it
When to use
- A setting that takes effect the moment it changes: polite mode, sound.
Don’t use it
- A choice that needs saving. Use a button.
- More than two options. Use the corner picker’s segmented style.
States
Off has a 4.4:1 edge and a grey knob, so off reads as off without colour (1.4.11).
Accessibility
role=“switch” with aria-checked, and a visible label tied to it. The whole 44px row is the target.
| Key | What it does |
|---|
| Space / Enter | Toggles. |
Props
| Prop | Type | Default | Description |
|---|
| checked | boolean | — | On or off. |
| onChange | (checked: boolean) => void | — | Called with the new value. |
| label | string | — | Required; also the accessible name. |
| description | string | — | One line of what it does. |
| disabled | boolean | false | Not available right now. |
Tokens
| Token | Value | Where it lands |
|---|
| --cm-switch-on | #ca0e6f / #ff2d95 | Switch track, on |
| --cm-border-strong | #77777f | Input and control edges, 3:1 or better |
| --cm-bg-sunken | #ececee / #1f1f24 | Chips, keycaps, tracks |
| --cm-focus-ring | #ca0e6f / #ff56aa | The 2px focus ring |
Corner picker
Where the overlay sits: three corners, chosen without dragging.
Concept · live ReactSource file: tokens.jsonReact component: CornerPicker
Try it
Pick a corner, or Tab in and use the arrow keys.
When to use
- Choosing where the overlay sits, for all games or one.
- Beside a draggable preview, as the way to place it without a drag.
Don’t use it
- Offering the centre or the bottom left. The crosshair and chat live there.
Accessibility
The non-drag way to place the overlay (2.5.7). A radio group with one tab stop and arrow keys.
| Key | What it does |
|---|
| Tab | Moves into the group. |
| ← → | Moves between corners and chooses. |
Props
| Prop | Type | Default | Description |
|---|
| value | 'top-left' | 'top-right' | 'bottom-right' | — | The chosen corner. |
| onChange | (corner: Corner) => void | — | Called on choose. |
| label | string | 'Where messages appear' | The group’s accessible name. |
Tokens
| Token | Value | Where it lands |
|---|
| --cm-bg-sunken | #ececee / #1f1f24 | Chips, keycaps, tracks |
| --cm-bg-surface | #ffffff / #16161a | Cards and panels |
| --cm-text-secondary | #5a5a62 / #9a9aa2 | Supporting text, 6.9:1 on its ground |
| --cm-focus-ring | #ca0e6f / #ff56aa | The 2px focus ring |
Preset chips
Her usual messages as one-tap chips that fill the composer.
Concept · live ReactSource file: tokens.jsonReact component: PresetChips
Try it
When to use
- Above her composer: one tap fills it with a message she can still edit.
Don’t use it
- More than five. Her most-sent replace the defaults over time.
Content
- Two or three words, in her voice: Dinner’s ready, Call me.
- The chip is the label; the message it fills can be warmer and longer.
Accessibility
Toggle buttons with aria-pressed, in a labelled group. Her usual messages are one tap, never retyped (3.3.7).
Props
| Prop | Type | Default | Description |
|---|
| items | string[] | — | The chip labels. |
| value | string | null | — | The chip in use. |
| onPick | (text: string) => void | — | Called on tap. |
Tokens
| Token | Value | Where it lands |
|---|
| --cm-accent-fill | #ca0e6f / #ff2d95 | Primary buttons, selected controls |
| --cm-accent-subtle | #fff0f7 / #42062a | Selected backgrounds |
| --cm-border-subtle | #d9d9dd / #2a2a30 | Dividers and resting edges |
Composer
A labelled message field with a count and a send button, 140 characters at most.
Concept · live ReactSource file: tokens.jsonReact component: Composer
Try it
Type, then press Enter or Send.
When to use
- The last thing on her home screen and in the thread.
Don’t use it
- Longer than 140 characters. Two lines is what fits on his screen.
Accessibility
A visible label, not a placeholder (3.3.2). The count is announced at 20 left and at the limit, not on every key.
| Key | What it does |
|---|
| Enter | Sends. |
Props
| Prop | Type | Default | Description |
|---|
| to | Person | — | Names the label and the send button. |
| value | string | — | The message. |
| onChange | (v: string) => void | — | Called on input. |
| onSend | () => void | — | Called on Enter or Send. |
| maxLength | number | 140 | Hard limit. |
Tokens
| Token | Value | Where it lands |
|---|
| --cm-input-border | #77777f | Text field edge |
| --cm-focus-ring | #ca0e6f / #ff56aa | The 2px focus ring |
| --cm-button-primary-bg | #ca0e6f / #ff2d95 | Primary button fill |
| --cm-text-secondary | #5a5a62 / #9a9aa2 | Supporting text, 6.9:1 on its ground |
Keycap
A key or a chord, with what it does, on light surfaces or the overlay’s glass.
Concept · live ReactSource file: tokens.jsonReact component: Keycap
Try it
<Keycap keys={['F7']} label="…" tone="surface" />
When to use
- Teaching a key: under the notification in his first week, and in his settings.
Don’t use it
- As a button. To act, the key itself is pressed.
Tones
F7On my wayCtrlShiftCHeads down
F7On my wayF8After this match
Accessibility
Keys are real kbd elements. The keys they describe only listen while a notification is showing, and can be changed or turned off (2.1.4).
Props
| Prop | Type | Default | Description |
|---|
| keys | string[] | — | One key, or a chord. |
| label | string | — | What it does. |
| tone | 'surface' | 'overlay' | 'surface' | Overlay for the dark glass. |
Tokens
| Token | Value | Where it lands |
|---|
| --cm-keycap-bg | #ececee / #1f1f24 | Keycap face |
| --cm-border-subtle | #d9d9dd / #2a2a30 | Dividers and resting edges |
| --cm-text-primary | #0e0e10 / #f6f6f7 | Body and headings |