Swivel uses a single icon family — Material Symbols Outlined — at five fixed sizes, with one consistent default color. Fills, accents, and brand marks have narrow, specific jobs.
3.1
Library
One family, loaded with optical-size + weight + fill + grade axes so we can vary expression without changing source.
Used sparingly — KPI glyphs, in-product accents that tie to the switch brand.
check_circle
Success
var(--success)
Healthy state, deployed, verified. Filled.
warning
Warning
var(--warning)
Degraded, approaching limits. Filled.
error
Error
var(--error)
Failures, blocking states. Filled.
info
Info
var(--info)
Neutral notification, sync, progress. Filled.
3.4
Fill weight
Outline = chrome. Fill = state. Don't mix on the same surface unless the fill is carrying meaning.
check_circlecheck_circle
Status
Outlined for the affordance, filled when the row is in that state.
favoritefavorite
Toggle
Outlined off, filled on. Color follows the meaning of "on".
notificationsnotifications
Alert
Outline for the bell affordance; fill only when there's an unread.
verifiedverified
Trust mark
Filled with accent when the object is verified by Swivel.
3.5
Brand marks
Swivel's own symbols sit alongside Material icons — they aren't substitutes for them. Use only as object identifiers.
Symbol · slate
swivel-symbol-slate.svg
Symbol on dark
surface-canvas inverse
Smart QPS Automation
Agentic Buying Campaign
Magnite SSP Deal
GAM Ad Unit
Airtable Sync Base
Publica CTV Inventory
FreeWheel Forecast Sync
Inline usage · object identifiers
[mark · 16px] + object name · meta rows, headers
3.6
In context
How sizing + color resolve inside real controls. These are the patterns to copy.
Field with leading icon
searchSearch ad operations
18px / graphite-bg / 8px gap to text. Always inside the input box.
Button with leading icon
addNEW RULE
18px / inherits button color / 4px gap. Always before the label.
Chip with dismissal
tag · qps · smartcancel
14px / graphite-bg. Trailing only. No leading icon on chips.
Alert
warningSpend pacing 18% above plan — review caps before next refresh.
22px / severity color / FILL 1. Aligned to the title baseline.
Table cell / header icon
auto_modeterminalburst_modedescriptionperson
28×28 square chip · bg token as fill · base token as icon color. For object icons in table type cells and section headers — never for status (status uses the bare icon in its semantic color).
3.7
Swivel objects
Fixed glyph per object type. These appear in nav, breadcrumbs, type tables, and result rows.
auto_mode
Automation
auto_mode
terminal
Script
terminal
rocket_launch
Beacon
rocket_launch · FILL 1
description
Proposal
description
burst_mode
Creative
burst_mode
person
User
person
smart_toy
Agent
smart_toy
domain
Organization
domain
restore
User activity
restore
handshake
Buyer
handshake
storefront
Ad product
storefront
3.8
Swivel concepts
Verbs and states with a reserved glyph. Use these exact icons whenever the concept appears — don't substitute.
add
Create / Add
add
sensors
Agent activity
sensors
dashboard
Dashboard
dashboard
speed
Pacing
speed
insights
Analytics
insights
table_chart
Table
table_chart
insert_chart
Chart
insert_chart
bolt
Automation manager
bolt
insights
Datalake explorer
insights
shopping_cart
Media buyer
shopping_cart
tune
Operator
tune
terminal
Scripting agent
terminal
face_retouching_natural
Agentic buys
face_retouching_natural
cancel
Dismiss
cancel
delete
Delete
delete · FILL 0 · wght 500
save
Save
save
edit
Edit
edit · FILL 1
check_circle
Success
check_circle
done
Include
done
block
Exclude
block
public
Geo target
public
language
Public
language
hub
Explore
hub · FILL 1
backup
Update
backup
report_problem
Warning
report_problem
verified
Guaranteed
verified
settings_backup_restore
Revert
settings_backup_restore
videocam
Video
videocam · FILL 1
code
VAST
code
filter_list
Filter
filter_list
keyboard_arrow_down
Collapse / Expand
keyboard_arrow_down · _up
arrow_drop_down
Dropdown menu
arrow_drop_down
3.9
Status indicators
Fixed glyph + color per state. Render as the bare icon in its semantic color — never wrap in a chip. Never substitute another icon for one of these four meanings.
task_alt
Active / Approved
task_alt · var(--success) · FILL 1. Object is running, healthy, in-market.
task_alt
Pending approval
task_alt · var(--warning). Awaiting an internal sign-off before activation.
more_horiz
Pending partner action
more_horiz · var(--graphite-bg). Blocked on an external partner — not actionable by us.
remove_circle_outline
Rejected / inactive
remove_circle_outline · var(--error). Declined, paused, or otherwise off.
3.10
Accessibility
Icons aren't free — every one is either decoration to skip or meaning to announce.
Decorative — icon beside a label
<span class="material-symbols-outlined"
aria-hidden="true">add</span> New rule
Always aria-hidden="true" when the label is right there. AT should hear “New rule”, not “plus, New rule”.
Button carries the aria-label; glyph stays hidden so the name isn’t doubled.
Contrast
All semantic colors clear 4.5:1 against white and the matching *-bg token. Never place a colored icon directly on its own base color (e.g. --success on --success). Default --graphite-bg on --white = 5.4:1 — safe.
RTL / directionality
Directional glyphs (arrow_back, chevron_right, undo, send) flip in RTL via :dir(rtl). Non-directional glyphs (warning, delete, person) never flip.
3.11
Position
Side matters. Leading icons identify a noun; trailing icons signal an action on it.
Leading · noun
auto_modeSmart QPS AutomationsearchSearch ad operations
Expand, dismiss, external-link, more-menu. Smaller (14–18px) so it reads as control, not content.
3.12
Object chip color signals action
A neutral chip means the object is healthy and unattended. A semantic-colored chip means this object needs you. Match the fill to the action's urgency, never as decoration.
auto_mode
Neutral · no action
slate-bg fill, slate-100 icon. Default state. Object is running or simply present — the row doesn't ask for anything.
description
Proposal · pending approval
warning-bg fill, warning icon. User owes a decision — review, approve, sign off.
burst_mode
Creative · rejected
error-bg fill, error icon. Object failed or was declined — user must remediate or remove.
terminal
Script · update available
info-bg fill, info icon. Informational — a non-blocking action the user may want to take.
3.13
Source & variation axes
Where glyphs come from and which knobs we allow.
Material Symbols (Outlined)
Single source for every Material glyph. Browse at fonts.google.com/icons. If a glyph isn’t there, commission a Swivel mark instead — don’t reach for a second icon set.
Allowed variation axes
opsz · 24 (locked) wght · 400 default, 500 for heavy delete FILL · 0 chrome, 1 state/active GRAD · 0 (locked)
No other weights, no Rounded/Sharp families, no third-party packs.
Use the variable-font stylesheet — one network request covers every glyph. display=block hides the ligature text until the font lands.
3.14
Icon button sizing
Three button sizes, pinned to the control scale. The glyph inside is always one step smaller than the button — and the hit zone is always at least 40 × 40, no matter how small the button looks.
Scale · sm / md / lg
28 · 32 · 40
28 × 28 · sm
glyph 16 · radius-sm
Inline row controls, table-cell actions, chip dismiss. Visually compact — but the hit zone still extends to 40 (see below).
32 × 32 · md
glyph 18 · radius-sm
The default. Toolbars, card headers, sidebars, segmented groups. Reach for this first.
40 × 40 · lg
glyph 22 · radius-sm
Primary canvas actions, mobile-tappable surfaces, hero positions where the button anchors a region.
Hit target · ≥ 40 × 40
expanded via transparent ::before
sm — 28px button, 40px hit zone (dashed).
md — 32px button, 40px hit zone (dashed).
lg — 40px button is its own hit zone. No expansion needed.
Icon-only buttons need aria-label. Every one. Even close and more_horiz — the glyph alone is not a name.
Do · expand the hit zone
For sm and md, the transparent ::before pads tappable area out to 40 × 40. The visual button stays compact; the tap target meets WCAG.
Don't · invent in-between sizes
Three sizes: 28 / 32 / 40. Don't ship a 36 because it “looked right” in one mock — pick the nearest token.
Don't · oversize the glyph
Inner icon is always one step down from the button (16 / 18 / 22). A 22px glyph in a 28px button reads as broken, not bold.
3.15
Do & don't
A short list. The point is to never paste an icon in without thinking about what it says.
Do · use icons to clarify
Pair the icon with a text label whenever possible. Icon-only is for repeat affordances the user already knows (close, expand, sort).
Don't · decorate
No "spark", "pencil", or "checkmark" icons next to every bullet just because. Empty visual noise lowers scannability of the real signals.
Do · stay in family
Material Symbols Outlined only. If a glyph is missing, ask before mixing in another set or drawing custom.
Don't · resize mid-row
Don't drop a 14px icon next to an 18px one in the same row. Pick one size per surface and stick to it.
Do · fill for state
Outlined for affordances, filled for "this is true right now" — selected, verified, succeeded, failing.
Do · hide decoration from AT
Glyph next to a text label → aria-hidden="true". Icon-only control → aria-label on the button.
Do · lock reserved glyphs
If a glyph is reserved in §3.7–3.9 (objects, concepts, status), use that exact glyph for that exact meaning everywhere. Don't reinvent it locally.
Don't · swap a status glyph
"Active" is always task_alt in --success. Don't substitute check_circle, a green dot, or a colored chip — the four status forms in §3.9 are non-negotiable.
Don't · invent color
Stay on the eight tokens in §3.3. Icons are not a place to introduce new hues — that's what data-vis tokens are for.