Design tokens
The semantic tokens Vectis UI exposes as CSS custom properties, with what each one controls and its default value. These are the names to override when you adapt the library to your own design or brand.
When a value points at another token, the table shows it twice: the value it resolves to, then the reference as the stylesheet writes it, such as var(--vectis-color-gray-900). Overriding the role keeps every component that reads it consistent, whereas changing the primitive behind it also changes every other role pointing at that primitive.
The primitives (the five palettes and the spacing, type, radius, shadow and duration scales) are not listed on their own: they appear in those references. How to override a token for the whole page or for one part of it is covered on the Theming page.
This site repoints its own accent to violet, so the buttons and links around these tables do not match the indigo defaults listed in them.
Colors
Surfaces, text, borders and the four tones. Each tone is a family of six roles: the solid color, its hover and pressed steps, a tinted surface, the border that goes with that surface, and a text color that stays readable on it. The three calendar event colors carry a hue variable the calendar sets on each event, which is why their value includes one.
| Token | Description | Light | Dark |
|---|---|---|---|
| Surfaces | |||
--vectis-color-surface | The default page background | oklch(100% 0 0)var(--vectis-color-white) | oklch(13% 0.028 261.692)var(--vectis-color-gray-950) |
--vectis-color-surface-muted | A muted background (secondary areas) | oklch(96.7% 0.003 264.542)var(--vectis-color-gray-100) | oklch(27.8% 0.033 256.848)var(--vectis-color-gray-800) |
--vectis-color-surface-raised | Raised surfaces: cards | oklch(100% 0 0)var(--vectis-color-white) | oklch(21% 0.034 264.665)var(--vectis-color-gray-900) |
--vectis-color-surface-overlay | Floating surfaces: dialogs, popovers, menus | oklch(100% 0 0)var(--vectis-color-white) | oklch(21% 0.034 264.665)var(--vectis-color-gray-900) |
--vectis-color-surface-sunken | Sunken surfaces: wells, code areas | oklch(98.5% 0.002 247.839)var(--vectis-color-gray-50) | oklch(11% 0.006 260) |
--vectis-color-surface-inverse | Inverted-contrast surfaces: tooltips | oklch(21% 0.034 264.665)var(--vectis-color-gray-900) | oklch(27.8% 0.033 256.848)var(--vectis-color-gray-800) |
--vectis-color-surface-skeleton | The background of VSkeletonLoader's silhouettes, from which its highlight is derived | oklch(92.8% 0.006 264.531)var(--vectis-color-gray-200) | oklch(27.8% 0.033 256.848)var(--vectis-color-gray-800) |
| Text | |||
--vectis-color-text-on-inverse | Text set on an inverted surface | oklch(100% 0 0)var(--vectis-color-white) | oklch(98.5% 0.002 247.839)var(--vectis-color-gray-50) |
--vectis-color-text | The running text of the interface | oklch(21% 0.034 264.665)var(--vectis-color-gray-900) | oklch(98.5% 0.002 247.839)var(--vectis-color-gray-50) |
--vectis-color-text-muted | Secondary text: hints, captions, descriptions, start icons | oklch(44.6% 0.03 256.802)var(--vectis-color-gray-600) | oklch(87.2% 0.01 258.338)var(--vectis-color-gray-300) |
--vectis-color-text-subtle | Placeholders, disabled text | oklch(55.1% 0.027 264.364)var(--vectis-color-gray-500) | oklch(70.7% 0.022 261.325)var(--vectis-color-gray-400) |
--vectis-color-text-on-accent | Text set on an accent/danger/success background | oklch(100% 0 0)var(--vectis-color-white) | oklch(100% 0 0)var(--vectis-color-white) |
--vectis-color-text-on-warning | Text set on a solid warning background (amber too light for white) | oklch(13% 0.028 261.692)var(--vectis-color-gray-950) | Same as light |
| Borders | |||
--vectis-color-border | Dividers, and the frames of cards, tables and panels | oklch(92.8% 0.006 264.531)var(--vectis-color-gray-200) | oklch(27.8% 0.033 256.848)var(--vectis-color-gray-800) |
--vectis-color-border-strong | The borders of form controls | oklch(87.2% 0.01 258.338)var(--vectis-color-gray-300) | oklch(37.3% 0.034 259.733)var(--vectis-color-gray-700) |
| Accent | |||
--vectis-color-accent | The brand color: solid buttons, checked controls, the selected item | oklch(51.1% 0.262 276.966)var(--vectis-color-indigo-600) | oklch(58.5% 0.233 277.117)var(--vectis-color-indigo-500) |
--vectis-color-accent-hover | The accent color under the pointer | oklch(45.7% 0.24 277.023)var(--vectis-color-indigo-700) | oklch(67.3% 0.182 276.935)var(--vectis-color-indigo-400) |
--vectis-color-accent-active | The accent color while pressed | oklch(39.8% 0.195 277.366)var(--vectis-color-indigo-800) | oklch(78.5% 0.115 274.713)var(--vectis-color-indigo-300) |
--vectis-color-accent-surface | A tinted accent background (badges, selections) | oklch(96.2% 0.018 272.314)var(--vectis-color-indigo-50) | oklch(25.7% 0.09 281.288)var(--vectis-color-indigo-950) |
--vectis-color-accent-border | The border of a tinted accent element, matching the accent surface | oklch(87% 0.065 274.039)var(--vectis-color-indigo-200) | oklch(35.9% 0.144 278.697)var(--vectis-color-indigo-900) |
--vectis-color-accent-text | Accent text on a neutral or tinted background | oklch(45.7% 0.24 277.023)var(--vectis-color-indigo-700) | oklch(78.5% 0.115 274.713)var(--vectis-color-indigo-300) |
| Danger | |||
--vectis-color-danger | Destructive actions and errors: solid buttons, error states | oklch(57.7% 0.245 27.325)var(--vectis-color-red-600) | oklch(57.7% 0.245 27.325)var(--vectis-color-red-600) |
--vectis-color-danger-hover | The danger color under the pointer | oklch(50.5% 0.213 27.518)var(--vectis-color-red-700) | oklch(50.5% 0.213 27.518)var(--vectis-color-red-700) |
--vectis-color-danger-active | The danger color while pressed | oklch(44.4% 0.177 26.899)var(--vectis-color-red-800) | oklch(44.4% 0.177 26.899)var(--vectis-color-red-800) |
--vectis-color-danger-surface | A tinted danger background (soft buttons and chips, a destructive menu item) | oklch(97.1% 0.013 17.38)var(--vectis-color-red-50) | oklch(25.8% 0.092 26.042)var(--vectis-color-red-950) |
--vectis-color-danger-border | The border of a tinted danger element, matching the danger surface | oklch(88.5% 0.062 18.334)var(--vectis-color-red-200) | oklch(39.6% 0.141 25.723)var(--vectis-color-red-900) |
--vectis-color-danger-text | Danger text on a neutral or tinted background: error messages, a destructive menu item | oklch(50.5% 0.213 27.518)var(--vectis-color-red-700) | oklch(80.8% 0.114 19.571)var(--vectis-color-red-300) |
| Success | |||
--vectis-color-success | A positive outcome: solid chips, badges, notifications | oklch(52.7% 0.154 150.069)var(--vectis-color-green-700) | oklch(52.7% 0.154 150.069)var(--vectis-color-green-700) |
--vectis-color-success-hover | The success color under the pointer | oklch(44.8% 0.119 151.328)var(--vectis-color-green-800) | oklch(44.8% 0.119 151.328)var(--vectis-color-green-800) |
--vectis-color-success-active | The success color while pressed | oklch(39.3% 0.095 152.535)var(--vectis-color-green-900) | oklch(39.3% 0.095 152.535)var(--vectis-color-green-900) |
--vectis-color-success-surface | A tinted success background (soft chips, badges, notifications) | oklch(98.2% 0.018 155.826)var(--vectis-color-green-50) | oklch(26.6% 0.065 152.934)var(--vectis-color-green-950) |
--vectis-color-success-border | The border of a tinted success element, matching the success surface | oklch(92.5% 0.084 155.995)var(--vectis-color-green-200) | oklch(39.3% 0.095 152.535)var(--vectis-color-green-900) |
--vectis-color-success-text | Success text on a neutral or tinted background | oklch(44.8% 0.119 151.328)var(--vectis-color-green-800) | oklch(87.1% 0.15 154.449)var(--vectis-color-green-300) |
| Warning | |||
--vectis-color-warning | A situation that calls for attention: solid chips, badges, notifications | oklch(66.6% 0.179 58.318)var(--vectis-color-amber-600) | oklch(76.9% 0.188 70.08)var(--vectis-color-amber-500) |
--vectis-color-warning-hover | The warning color under the pointer | oklch(55.5% 0.163 48.998)var(--vectis-color-amber-700) | oklch(82.8% 0.189 84.429)var(--vectis-color-amber-400) |
--vectis-color-warning-active | The warning color while pressed | oklch(47.3% 0.137 46.201)var(--vectis-color-amber-800) | oklch(87.9% 0.169 91.605)var(--vectis-color-amber-300) |
--vectis-color-warning-surface | A tinted warning background (soft chips, badges, notifications) | oklch(98.7% 0.022 95.277)var(--vectis-color-amber-50) | oklch(27.9% 0.077 45.635)var(--vectis-color-amber-950) |
--vectis-color-warning-border | The border of a tinted warning element, matching the warning surface | oklch(92.4% 0.12 95.746)var(--vectis-color-amber-200) | oklch(41.4% 0.112 45.904)var(--vectis-color-amber-900) |
--vectis-color-warning-text | Warning text on a neutral or tinted background | oklch(41.4% 0.112 45.904)var(--vectis-color-amber-900) | oklch(87.9% 0.169 91.605)var(--vectis-color-amber-300) |
| Backdrop | |||
--vectis-color-backdrop | The veil behind modal dialogs | oklch(0% 0 0 / 0.45) | oklch(0% 0 0 / 0.6) |
| Calendar events | |||
--vectis-color-event-surface | The face of a calendar event that carries no color of its own | oklch(0.95 0.045 var(--vectis-calendar-event-hue, 265)) | oklch(0.3 0.05 var(--vectis-calendar-event-hue, 265)) |
--vectis-color-event-border | The edge of that calendar event, and the bar marking its leading side | oklch(0.85 0.08 var(--vectis-calendar-event-hue, 265)) | oklch(0.42 0.08 var(--vectis-calendar-event-hue, 265)) |
--vectis-color-event-text | The title of that calendar event | oklch(0.4 0.11 var(--vectis-calendar-event-hue, 265)) | oklch(0.9 0.06 var(--vectis-calendar-event-hue, 265)) |
Focus ring
The ring drawn around a control focused from the keyboard. Its color is a role of its own rather than the accent: the accent has to carry white text, the ring has to stand out against the page.
| Token | Description | Light | Dark |
|---|---|---|---|
--vectis-focus-ring-color | The keyboard focus ring, which has to stand out against the page | oklch(58.5% 0.233 277.117)var(--vectis-color-indigo-500) | oklch(67.3% 0.182 276.935)var(--vectis-color-indigo-400) |
--vectis-focus-ring-width | The thickness of the focus ring | 2px | Same as light |
--vectis-focus-ring-offset | The gap between a control and its focus ring | 2px | Same as light |
Typography
Three font families, then the text roles. A role is a complete recipe: its size, weight and leading, plus a tracking where it matters. Components ask for a role, so overriding one of its values changes every place that role is used.
Loading a web font and assigning it to the families is covered on the Font family page.
| Token | Description | Default value |
|---|---|---|
--vectis-text-family | The running font of every component | system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serifvar(--vectis-font-family-sans) |
--vectis-text-family-heading | The font of the display and heading roles, the running font until it is overridden | system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serifvar(--vectis-font-family-display) |
--vectis-text-family-code | The font of code content (the code role, VInputOTP) | ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, monospacevar(--vectis-font-family-mono) |
| Role | Size | Weight | Leading | Tracking |
|---|---|---|---|---|
--vectis-text-display-*The largest text, for a hero title | 3remvar(--vectis-font-size-5xl) | 700var(--vectis-font-weight-bold) | 1var(--vectis-font-leading-none) | -0.015emvar(--vectis-font-tracking-tight) |
--vectis-text-heading-1-*The title of a page | 2.25remvar(--vectis-font-size-4xl) | 700var(--vectis-font-weight-bold) | 1.25var(--vectis-font-leading-tight) | -0.015emvar(--vectis-font-tracking-tight) |
--vectis-text-heading-2-*A section heading | 1.5remvar(--vectis-font-size-2xl) | 600var(--vectis-font-weight-semibold) | 1.25var(--vectis-font-leading-tight) | -0.015emvar(--vectis-font-tracking-tight) |
--vectis-text-heading-3-*A subsection heading | 1.125remvar(--vectis-font-size-lg) | 600var(--vectis-font-weight-semibold) | 1.4var(--vectis-font-leading-snug) | none |
--vectis-text-heading-4-*The smallest heading: a group inside a section, a card title | 1remvar(--vectis-font-size-md) | 600var(--vectis-font-weight-semibold) | 1.4var(--vectis-font-leading-snug) | none |
--vectis-text-subtitle-*The line under a title, in a dialog or an accordion item | 0.875remvar(--vectis-font-size-sm) | 400var(--vectis-font-weight-regular) | 1.5var(--vectis-font-leading-normal) | none |
--vectis-text-body-xl-*The lead paragraph that opens a page or a section | 1.125remvar(--vectis-font-size-lg) | 400var(--vectis-font-weight-regular) | 1.65var(--vectis-font-leading-relaxed) | none |
--vectis-text-body-lg-*Running text given more room, for longer reading | 1remvar(--vectis-font-size-md) | 400var(--vectis-font-weight-regular) | 1.65var(--vectis-font-leading-relaxed) | none |
--vectis-text-body-md-*The default running text, also used by menu rows, notifications and fields | 0.875remvar(--vectis-font-size-sm) | 400var(--vectis-font-weight-regular) | 1.5var(--vectis-font-leading-normal) | none |
--vectis-text-body-sm-*Small running text: secondary details, notes | 0.75remvar(--vectis-font-size-xs) | 400var(--vectis-font-weight-regular) | 1.5var(--vectis-font-leading-normal) | none |
--vectis-text-label-*The label above a form field | 0.875remvar(--vectis-font-size-sm) | 500var(--vectis-font-weight-medium) | 1.4var(--vectis-font-leading-snug) | none |
--vectis-text-caption-*Short supporting text: a field hint, a counter | 0.75remvar(--vectis-font-size-xs) | 400var(--vectis-font-weight-regular) | 1.4var(--vectis-font-leading-snug) | none |
--vectis-text-overline-*The heading of a group of rows in a menu, a combobox list or a side navigation, with wider letter spacing | 0.75remvar(--vectis-font-size-xs) | 500var(--vectis-font-weight-medium) | 1.4var(--vectis-font-leading-snug) | 0.05emvar(--vectis-font-tracking-wide) |
--vectis-text-code-*Inline code and code content | 0.875remvar(--vectis-font-size-sm) | 400var(--vectis-font-weight-regular) | 1.5var(--vectis-font-leading-normal) | none |
--vectis-text-control-*The label of a control such as a button, a chip or a tab. It has no size of its own: the text follows the size the control was given | none | 500var(--vectis-font-weight-medium) | 1var(--vectis-font-leading-none) | none |
Radius
Corner radii by role. --vectis-radius-chip points at --vectis-radius-interactive, so chips follow the other controls until you give them a radius of their own. The reference is resolved where the tokens are declared, on the root: an override of the interactive radius on a narrower selector has to set the chip radius as well.
| Token | Description | Default value |
|---|---|---|
--vectis-radius-interactive | Buttons, inputs, controls | 0.375remvar(--vectis-radius-md) |
--vectis-radius-surface | Cards, alerts | 0.5remvar(--vectis-radius-lg) |
--vectis-radius-overlay | Dialogs, popovers, menus | 0.75remvar(--vectis-radius-xl) |
--vectis-radius-pill | Full rounding: switches, badges, pill-shaped chips | 9999pxvar(--vectis-radius-full) |
--vectis-radius-chip | Chips with shape="chip", which follow the interactive radius by default | 0.375remvar(--vectis-radius-interactive) |
Motion
The three durations a transition uses. They are the same in both themes. Looping animations such as the spinner use the duration scale directly and do not follow these roles.
| Token | Description | Default value |
|---|---|---|
--vectis-duration-fast | Color and border changes on hover, focus and press | 150msvar(--vectis-duration-150) |
--vectis-duration-base | The default: a panel opening, a value moving | 200msvar(--vectis-duration-200) |
--vectis-duration-slow | Movements large enough to be followed by the eye | 300msvar(--vectis-duration-300) |
Sizes
The height of each step of the control size scale, and the three icon sizes. A control set to compact is 4px shorter than its step.
| Token | Description | Default value |
|---|---|---|
| Control heights | ||
--vectis-control-height-xs | The height of every control at size="xs" (24px), 4px less when compact | 1.5rem |
--vectis-control-height-sm | The height of every control at size="sm" (32px), 4px less when compact | 2rem |
--vectis-control-height-md | The height of every control at size="md" (40px), 4px less when compact | 2.5rem |
--vectis-control-height-lg | The height of every control at size="lg" (48px), 4px less when compact | 3rem |
--vectis-control-height-xl | The height of every control at size="xl" (56px), 4px less when compact | 3.5rem |
| Icon sizes | ||
--vectis-icon-size-sm | The icon size of xs controls (16px) | 1rem |
--vectis-icon-size-md | The icon size of sm and md controls (20px) | 1.25rem |
--vectis-icon-size-lg | The icon size of lg and xl controls (24px) | 1.5rem |
Component dimensions
Dimensions that belong to a single component: a track, a thumb, the width of a panel. Each group links to the page of its component.
| Token | Description | Default value |
|---|---|---|
| Avatar group | ||
--vectis-control-size-avatar-ring | The ring separating stacked avatars (VAvatarGroup) | 2px |
| Badge | ||
--vectis-control-size-badge-h | The height of a VBadge pill | 1.25rem |
--vectis-control-size-badge-dot | The diameter of VBadge in dot mode | 0.625rem |
--vectis-control-size-badge-ring | The detaching ring of a bordered VBadge | 2px |
| Calendar | ||
--vectis-control-size-calendar-hour | The height of one hour in VCalendar's time grid | 4rem |
--vectis-control-size-calendar-gutter | The column of hour labels beside VCalendar's time grid, wide enough for a 12-hour clock's '12:00 AM' on one line | 4.5rem |
--vectis-control-size-calendar-tick | How far an hour's rule runs back into VCalendar's gutter, tying the label to its line | 0.375rem |
--vectis-control-size-calendar-edge | The strip at the side of VCalendar that pages the view when a dragged event rests on it | 3rem |
--vectis-control-size-calendar-day-min | The width a VCalendar day column may not go below, past which the grid scrolls | 5rem |
--vectis-control-size-calendar-handle | The strip along a VCalendar card's bottom edge that its end is dragged by | 0.5rem |
--vectis-control-size-calendar-allday-lane | One lane of VCalendar's all-day band | 1.5rem |
--vectis-control-size-calendar-allday-max | The height past which VCalendar's all-day band scrolls instead of growing | 7rem |
--vectis-control-size-calendar-now-dot | The dot on VCalendar's current-time line | 0.625rem |
--vectis-control-size-calendar-month-cell | The minimum height of a day in VCalendar's month view | 8.5rem |
--vectis-control-size-calendar-year-cell | The side of a day square in the mini-months of VCalendar's year view | 1.5rem |
| Carousel | ||
--vectis-control-size-carousel-block | The default block size of VCarousel's viewport, which a vertical carousel needs to lay its slides out | 24rem |
--vectis-control-size-carousel-indicator | The diameter of a VCarousel indicator dot (its hit area comes from --vectis-control-height-xs) | 0.625rem |
--vectis-control-size-carousel-indicator-active | The length of the active VCarousel indicator, which stretches from a dot into a pill | 1.25rem |
| Checkbox, Radio | ||
--vectis-control-border-width | The border of checkable controls (VCheckbox, VRadio) | 2px |
--vectis-control-size-check | The box of checkable controls (VCheckbox, VRadio) | 1.25rem |
--vectis-control-size-check-mark | The tick inside VCheckbox's box | 0.875rem |
--vectis-control-size-check-dot | The dot inside VRadio's circle | 0.5rem |
| Combobox | ||
--vectis-control-size-combobox-list-max-block | The maximum height of VCombobox's list panel (the scrolling area) | 18rem |
| Data table | ||
--vectis-control-size-table-search | The width of VDataTable's search field | 16rem |
| Date picker | ||
--vectis-control-size-date-picker-cell | The side of a VDatePicker day cell | 2.5rem |
--vectis-control-size-date-picker-day | The diameter of the disc a VDatePicker day is drawn on; the cell grows to hold it | 2.5remvar(--vectis-control-height-md) |
--vectis-control-size-date-picker-dot | The diameter of a VDatePicker event dot | 0.25rem |
--vectis-control-size-date-picker-nav-min | The minimum width of VDatePicker's month/year picker buttons (about 86px) | 5.375rem |
| Dialog | ||
--vectis-control-size-dialog-width | The default width of VDialog and VDialogAlert (400px), when no width is given | 25rem |
| File picker | ||
--vectis-control-size-file-picker-min-block | The minimum height of VFilePicker's drop zone: icon, two lines, separator and button | 10rem |
--vectis-control-size-file-picker-icon | The large icon at the top of VFilePicker's drop zone | 2.5rem |
--vectis-control-size-file-picker-thumb | The thumbnail square of a VFilePicker preview row (an image, or its type icon) | 2.5rem |
| Input | ||
--vectis-control-action-size-sm | The inner buttons of sm input fields (clear, a clickable icon) | 1.25rem |
--vectis-control-action-size-md | The inner buttons of md input fields (clear, a clickable icon) | 1.5rem |
--vectis-control-action-size-lg | The inner buttons of lg input fields (clear, a clickable icon) | 1.75rem |
| Menu | ||
--vectis-control-size-menu-min | The minimum width of VMenu's panel | 11rem |
--vectis-control-size-menu-max | The maximum width of VMenu's panel | 20rem |
| Progress circular | ||
--vectis-control-size-progress-circular-diameter | The default diameter of VProgressCircular | 3rem |
--vectis-control-size-progress-circular-thickness | The default stroke thickness of VProgressCircular (4px) | 0.25rem |
| Progress linear | ||
--vectis-control-size-progress-linear-thickness | The default thickness of VProgressLinear's bar (4px) | 0.25rem |
--vectis-control-size-progress-linear-length | The default length of a vertical VProgressLinear, which a height set on the bar replaces | 10rem |
| Skeleton loader | ||
--vectis-control-size-skeleton-surface | The default height of a surface-shaped VSkeletonLoader: a card, an image (96px) | 6rem |
| Slider | ||
--vectis-control-size-slider-track | The thickness of VSlider's track | 0.375rem |
--vectis-control-size-slider-thumb | The diameter of VSlider's thumb | 1.25rem |
--vectis-control-size-slider-length | The default length of a vertical VSlider | 10rem |
--vectis-control-size-slider-field | The width of VSlider's number fields | 5rem |
| Snackbar | ||
--vectis-control-size-snackbar-min | The minimum width of a snackbar (288px) | 18rem |
--vectis-control-size-snackbar-max | The maximum width of a snackbar (576px) | 36rem |
| Switch | ||
--vectis-control-size-switch-w | The width of VSwitch's track | 2.5rem |
--vectis-control-size-switch-h | The height of VSwitch's track | 1.25rem |
--vectis-control-size-switch-pad | The gap between VSwitch's thumb and the edge of its track | 0.125rem |
| Tabs | ||
--vectis-control-size-tab-indicator | The thickness of the active tab indicator (VTabs, flat/outlined) | 2px |
| Time picker | ||
--vectis-control-size-time-picker-dial | The diameter of VTimePicker's clock face | 16rem |
--vectis-control-size-time-picker-number | A numeral cell on VTimePicker's face, and the hand's dot on a marker | 3rem |
--vectis-control-size-time-picker-center | The center dot of VTimePicker's face | 0.5rem |
--vectis-control-size-time-picker-hand | The thickness of the hand on VTimePicker's face | 2px |
--vectis-control-size-time-picker-hand-minor | The dot of VTimePicker's hand on a minute off the 5-minute markers | 1rem |
| Toast | ||
--vectis-control-size-toast-width | The default width of a toast | 22rem |
| Tooltip | ||
--vectis-control-size-tooltip-max | The widest a tooltip grows before it wraps (288px) | 18rem |