Toggle
Save, follow topic, follow source. One control with three labels, replacing three separate implementations.
What it replaces
BookmarkButton, FollowButton and FollowSourceButton are the same control three times: a thing that is on or off, that shows which, and that a signed-out reader is allowed to press.
Off and on
HTML
<button class="p234-toggle" type="button" aria-pressed="false">
<span class="p234-toggle__off">Save</span>
<span class="p234-toggle__on">Saved</span>
</button>
<button class="p234-toggle" type="button" aria-pressed="true">
<span class="p234-toggle__off">Follow Canada</span>
<span class="p234-toggle__on">Following Canada</span>
</button>The state is announced, not just coloured
The control is a button with aria-pressed, which is what tells a screen reader it is on. The label changes with it, so the state survives for anyone who cannot see the tint. Colour is the third signal, not the only one.
- Change the label between off and on: Save becomes Saved, Follow becomes Following.
- Keep the control the same width in both states where you can, so the row does not jump under the reader's thumb.
- Switch the state immediately and reconcile with the server afterwards. If it fails, put it back and say so.
- Do not use a checkbox. This is an action with a state, not a form field.
- Do not block a signed-out reader at the press. Let them press it, then ask.
- Do not rely on a filled icon alone to show the state.
Signed out
Most readers arrive from search and are not signed in. Pressing Save should feel like it worked, then offer the account that keeps it. Putting the sign-in wall first turns the only retention control on the page into a dead end.
Size
The control is field.height tall, which is the 44px touch target. These sit under an article on a phone, often next to each other.
Tokens this component reads
--p234-color-ink--p234-color-brand--p234-color-brand-tint--p234-color-rule-strong--p234-color-paper-sunk--p234-type-ui-*--p234-field-height--p234-radius-md--p234-space-3--p234-space-5--p234-motion-duration-fast