Skip to content
Vanguard

Svelte 5 · Bits UI 2 · Tailwind 4 · dark only

Vanguard Design

The components behind Vanguard: Vanguard 1.0's charcoal, blue and monospace, rebuilt with GitHub Primer's functional color roles and Bits UI's accessible primitives. Every state of every component is on this page.

  • Roles, not hex

    Components reach for accent, danger, surface. Retune a role once; everything follows.

  • Quiet by default

    Secondary is the default button, badges are subtle, danger waits for hover. Emphasis is earned.

  • Keyboard first

    Bits UI handles focus, roving tabindex and ARIA. Every state has a visible focus ring.

Vanguard 1.0's charcoal and blue, organized into functional roles. Components use roles, never raw hex, so a role can be retuned in one place. Every text role clears WCAG AA on every background.

Backgrounds

Darkest to lightest. Elevation reads as lighter, not as heavier shadow.

inset
Inputs, wells
chrome
Header, sidebar, status bar
canvas
Page
surface
Cards, menus, dialogs
control
Secondary buttons
control-hover
Control hover
control-active
Pressed, selected segment

Text

Contrast measured against canvas.

  • Aa 1234 fg-strong Headings, selected
  • Aa 1234 fg Body
  • Aa 1234 fg-muted Secondary text
  • Aa 1234 fg-subtle Placeholders, hints
  • Aa 1234 fg-disabled Disabled (exempt)

Borders

  • border-muted Dividers within a surface
  • border Cards, tables, surfaces
  • border-emphasis Control edges
  • border-strong Hover; checkbox, radio, switch

Roles

Each hue ships four steps: text, solid fill, tint and border.

accent
emphasis
fg

Primary actions, links, selection, info

success
emphasis
fg

Wins, saved, healthy

attention
emphasis
fg

Ties, pending, warnings

danger
emphasis
fg

Losses, errors, destructive actions

Alliance

Separate from danger and accent so 'red alliance' never reads as 'error' in code.

alliance-red
alliance-blue

JetBrains Mono everywhere, as in Vanguard 1.0: team numbers, scores and timestamps align in columns without extra work. The scale is anchored at 13px for dense, data-heavy screens.

Scale

  • 3xl · 32/40 Qualification 12 · 184–97 Page title
  • 2xl · 24/32 Qualification 12 · 184–97 Section title
  • xl · 20/28 Qualification 12 · 184–97 Large stat
  • lg · 16/24 Qualification 12 · 184–97 Dialog, card title
  • md · 14/20 Qualification 12 · 184–97 Emphasized body, large controls
  • base · 13/20 Qualification 12 · 184–97 Body and default controls
  • sm · 12/18 Qualification 12 · 184–97 Secondary text, small controls
  • xs · 11/16 Qualification 12 · 184–97 Badges, table meta
  • 2xs · 10/14 Qualification 12 · 184–97 Dense badges only

Weights and emphasis

Regular 400 Medium 500 Semibold 600 Bold 700 Link text inline code

Four radii and three shadows. Controls are 6px, floating panels 8px. Shadows only appear on things that float; resting surfaces separate by border and tone.

Radius

sm · 4px Checkbox, kbd
md · 6px Controls
lg · 8px Cards, menus, dialogs
xl · 12px Hero panels

Elevation

control Buttons, inputs
overlay Menus, popovers
dialog Dialogs

Button

bits-ui · Button

One primary action per view. Secondary is the default. Danger stays quiet until hovered, so the destructive option never has the most visual weight. Loading keeps focus on the button and blocks repeat clicks.

Variants × states

Hover, active and focus are forced with data-force-state.

variantDefaultHoverActiveFocusDisabledLoading
primary
secondary
ghost
danger

Sizes

28 · 32 · 40px

With visuals

Try it

Loads for 1.5s.

As a link

Block

Fills its container, for narrow forms and mobile.

IconButton

bits-ui · Button

A square button with an icon and a required label. The label becomes the accessible name and appears as a tooltip on hover and keyboard focus.

Variants × states

variantDefaultHoverActiveFocusDisabledLoading
primary
secondary
ghost
danger

Sizes

Input

native

Single-line text. Inputs sit in an inset well so they read as fillable on any surface. Focus adds a blue edge and halo; errors swap both to red and never rely on color alone (see Field).

States

stateEmptyFilled
Default
Hover
Focus
Invalid
Disabled
Read-only

Sizes

Adornments

sec

Field

bits-ui · Label

Wraps a control with its label, help text and error, and wires up id, aria-describedby and aria-invalid for you. Errors pair color with an icon and a message that says how to fix it.

Live validation

Type letters to see the error.

Your FTC team, e.g. 6547.

No event found with code USCAFFL. Check the code on ftc-events.

In a form

Visible to your whole team.

Textarea

native

Multi-line text. Resizes vertically by default; `autosize` grows with the content instead.

States

stateFilled
Default
Hover
Focus
Invalid
Disabled

Checkbox

bits-ui · Checkbox

Independent on/off choices that take effect on submit. The label is part of the hit target. Indeterminate shows a parent whose children are partly selected.

States

valueDefaultHoverActiveFocusDisabled
Unchecked
Checked
Indeterminate

Try it

The parent reflects its children.

Includes surrogate matches.

Switch

bits-ui · Switch

A setting that applies immediately, like a light switch. If the change needs a Save button, use a Checkbox instead.

States

valueDefaultHoverActiveFocusDisabled
Off
On

Settings list

Pull new scores every 30 seconds.

Requires the mobile app.

Sizes

RadioGroup

bits-ui · RadioGroup

One choice from a short list, all options visible. Arrow keys move the selection. For more than about five options, use a Select.

States

valueDefaultHoverActiveFocusDisabled
Unchecked
Checked

Vertical

Selected: rank

Official ranking points.

Offensive power rating.

Not available for this season.

Horizontal

Select

bits-ui · Select

Pick one option from a list too long to show at once. Typeahead works while the trigger is focused, even closed. Options can carry a description and be disabled.

States

statePlaceholderSelected
Default
Hover
Focus
Invalid
Disabled

Try it

Open to see the list, descriptions and a disabled option.

Sizes

SegmentedControl

bits-ui · ToggleGroup

Switch between views of the same content. Always has exactly one selection; clicking the active segment does nothing. For separate content panels, use Tabs.

Text

Selected: all

Icons

Selected: list

Block

Disabled

Slider

bits-ui · Slider

Pick a value from a continuous range where the exact number matters less than the position. Pair with a visible value; arrow keys step, Page Up/Down jump.

States

DefaultHoverFocusDisabled
Value 40

With a value

Schedule offset +30 sec

Vertical

60%

Tabs

bits-ui · Tabs

Switch between related panels without leaving the page. The underline marks the active tab, as in Vanguard 1.0's admin nav; counts summarize what's inside. Arrow keys move between tabs.

Try it

Active: schedule

Qualification matches for today, in order.

Trigger states

Default · hover · focus · active · disabled

Accordion

bits-ui · Accordion

Stacked sections that expand in place, for secondary detail people only sometimes need. Don't hide anything required to finish a task.

Single

One section open at a time.

Scored 2 specimens and parked. Consistent across 5 matches.

Multiple, with meta and disabled

Two minor, one major (pinning) in match 14.

Dialog

bits-ui · Dialog

Focused tasks that need the page to wait. Focus moves in and is trapped; Escape, the ✕ and clicking outside close it. Keep the primary action last in the footer.

Try it

AlertDialog

bits-ui · AlertDialog

Interrupts to confirm a consequential action. Name the button after the action (“Delete note”, not “OK”). The confirm can be async: it shows progress and the dialog waits.

Try it

Last result: —

Popover

bits-ui · Popover

Non-modal floating content anchored to a trigger: quick settings, previews, small forms. Closes on Escape or outside click, and focus returns to the trigger.

Try it

Tooltip

bits-ui · Tooltip

A short text label for a control, shown on hover and keyboard focus. Never put essential information or interactive content in one. Once one tooltip opens, neighbors open instantly.

Try it

Hover or tab through.

Badge

native

Compact status and metadata, from Vanguard's W/L/T match pills. Subtle is the default; solid is for the one thing on screen that must pop. Red and blue are alliance colors, not status.

Tones × variants

variantneutralaccentsuccessattentiondangerredblue
subtle Draft Live Win Tie Loss Red Blue
solid Draft Live Win Tie Loss Red Blue

Sizes

Small Medium Large

Dots and icons

Queueing On field Idle Delayed 4m DQ

Alert

native

An inline message about the page or a section. Icon, color and text carry the tone together. Say what happened and what to do next.

Tones

Live scoring is on

Scores update as referees submit them.

Notes saved

Your changes are visible to your team.

Schedule is running late

Matches are about 12 minutes behind. Times below include the offset.

Couldn't reach FTC Events

Showing data from 4 minutes ago.

Without title, dismissible

New season data is available. Rankings reset at midnight.

Progress

bits-ui · Progress

Progress of a known amount of work, or an indeterminate bar when the length is unknown, like Vanguard's status bar loader. Label it, or give it an aria-label.

Values

Not started 0%
Syncing matches 35%
Complete 100%

Tones, sizes, indeterminate

Loading rankings

Spinner

native

For short waits in a small space. Prefer a Progress bar or a skeleton for anything that fills a region.

Sizes and color

Fetching scores…

Card

native

Groups related content on a surface. The optional stripe marks a category, such as the alliance a card belongs to, as in Vanguard's match details.

Red alliance

Qualification 12

Win
184 6547 · 16236

Blue alliance

Qualification 12

Loss
97 11115 · 7236

Rankings

SoCal League Meet 3

  • 1
    CC
    6547 Cobalt Colts 9-1-0
  • 2
    TT
    16236 Torque Theory 8-2-0
  • 3
    NP
    11115 Null Pointers 7-2-1

Plain card

A title, a body and a footer. Use `flush` for edge-to-edge lists and tables.

Avatar

bits-ui · Avatar

Circles for people, rounded squares for teams. Falls back to initials while the image loads or if it fails.

Sizes

20 · 24 · 32 · 40 · 64px

Fallbacks and shapes

AP
JS
CC

Separator

bits-ui · Separator

A 1px divider between groups. Decorative by default; set decorative=false when it separates meaningful sections.

Horizontal and vertical

Above

Schedule Rankings Notes

Kbd

native

Keyboard keys in hints and menus.

Examples

⌘K Search Esc Close ↑↓ Navigate