Appearance
@vibe-labs/design-themes-default — Developer Reference
Default theme presets for the Vibe Design System. Provides scoped dark/light surface token overrides for elements with data-theme, plus three accent colour schemes and the Instrument Sans typeface.
Installation
ts
import { DefaultThemes, type DefaultTheme } from "@vibe-labs/design-themes-default";css
/* Pick a theme (includes common + fonts) */
@import "@vibe-labs/design-themes-default/cyan";
@import "@vibe-labs/design-themes-default/purple";
@import "@vibe-labs/design-themes-default/gold";Each theme CSS file imports common.css (base token overrides) and fonts.css (Instrument Sans) then adds its own accent colour block.
How It Works
This package applies overrides inside @layer vibe.theme, scoped to [data-theme] selectors. Any element with a data-theme attribute gets the scoped token values, overriding the base design system theme tokens only for that subtree.
html
<!-- Entire page -->
<html data-theme="cyan">
<!-- Scoped region -->
<section data-theme="purple" data-mode="light">
<!-- light-mode purple theme for this section only -->
</section>Because these rules live inside @layer vibe.theme, they sit below unlayered CSS — tenant overrides can still win.
Colour Themes
cyan
css
@import "@vibe-labs/design-themes-default/cyan";| Token | Value |
|---|---|
--color-accent | #53ddf5 |
--color-accent-dark | #16a9c3 |
--color-accent-light | #97edfd |
--color-accent-hover | #97edfd |
--color-accent-active | #16a9c3 |
--color-accent-contrast | #000 |
--color-secondary | #7e30ed |
--color-secondary-dark | #5411ab |
--color-secondary-light | #ba88ff |
--overlay-tint | rgba(83, 221, 245, 0.08) |
purple / gold
Follow the same pattern with their own accent values. Import ./purple or ./gold.
Common Token Overrides (common.css)
Applied to all elements matching [data-theme].
Dark (default)
| Category | Tokens |
|---|---|
| Surfaces | --surface-background: #0e0e0e · --surface-base: #161616 · --surface-subtle: #1e1e1e · --surface-elevated: #272727 · --surface-overlay: #313131 · --surface-modal: #383838 |
| Borders | --border-subtle: rgba(255,255,255,0.08) · --border-default: rgba(255,255,255,0.14) · --border-strong: rgba(255,255,255,0.22) |
| Text | --text-primary: #f0f0f0 · --text-secondary: #b0b0b0 · --text-muted: #777 · --text-disabled: #4a4a4a · --text-inverse: #0e0e0e |
| Status | --color-success/warning/danger/info → *-400 scale |
| Overlays | --overlay-scrim: rgba(0,0,0,0.5) · --overlay-heavy: rgba(0,0,0,0.7) |
| Interactions | --surface-hover-overlay: rgba(255,255,255,0.06) · --surface-active-overlay: rgba(255,255,255,0.1) |
| Focus | --ring-color: var(--color-accent) · --ring-offset-color: var(--surface-base) |
| Status surfaces | --surface-{success/warning/danger/info}-subtle (10% opacity rgba) |
Light ([data-theme][data-mode="light"])
Surfaces invert to neutral light scale. Text flips to neutral-900 scale. Status colours shift to *-500. Overlay opacities drop. Status surfaces use 8% opacity.
Fonts
Instrument Sans loaded via fonts.css (included automatically when importing a theme):
InstrumentSans-Latin.woff2+InstrumentSans-LatinExt.woff2InstrumentSans-Italic-Latin.woff2+InstrumentSans-Italic-LatinExt.woff2
Sets --font-sans to "Instrument Sans", sans-serif within [data-theme].
TypeScript
ts
import { DefaultThemes, type DefaultTheme } from "@vibe-labs/design-themes-default";
DefaultThemes // ["purple", "cyan", "gold"] as const
type DefaultTheme // "purple" | "cyan" | "gold"Use for type-safe theme switching in Vue or plain JS:
ts
function setTheme(el: HTMLElement, theme: DefaultTheme) {
el.dataset.theme = theme;
}Dist Structure
| File | Description |
|---|---|
common.css | Base dark/light token overrides for [data-theme] |
fonts.css | Instrument Sans @font-face declarations |
cyan.css | Cyan accent theme (imports common + fonts) |
purple.css | Purple accent theme |
gold.css | Gold accent theme |
index.js / index.d.ts | TypeScript constants and types |
Dependencies
Requires @vibe-labs/design for base token definitions. The [data-theme] overrides reference --color-neutral-* and --color-{status}-{stop} from the design package.
Build
bash
npm run buildBuild: rimraf dist && ncp src dist && tsc --rootDir types --outDir dist
Adding a New Theme
- Create
src/{name}.cssthat imports./common.cssand./fonts.css, then adds a[data-theme="{name}"]block with--color-accentand related tokens - Add
"types/index.ts"— extendDefaultThemesarray with the new name - Add the export to
package.json - Run
npm run build
Usage Guide
Scoped accent colour themes with dark/light mode support. Apply a data-theme attribute to any element to activate a theme for that subtree.
Import
css
/* Pick one (each includes common + fonts) */
@import "@vibe-labs/design-themes-default/cyan";
@import "@vibe-labs/design-themes-default/purple";
@import "@vibe-labs/design-themes-default/gold";ts
import { DefaultThemes, type DefaultTheme } from "@vibe-labs/design-themes-default";Apply a Theme
html
<!-- Full page: cyan dark (default) -->
<html data-theme="cyan">
<!-- Full page: purple light -->
<html data-theme="purple" data-mode="light">
<!-- Scoped: a panel with its own theme -->
<aside data-theme="gold">...</aside>
<!-- System mode within a theme -->
<html data-theme="cyan" data-mode="system">Theme Switching (Vue)
vue
<script setup lang="ts">
import { ref } from "vue";
import { DefaultThemes, type DefaultTheme } from "@vibe-labs/design-themes-default";
const theme = ref<DefaultTheme>("cyan");
function setTheme(t: DefaultTheme) {
theme.value = t;
document.documentElement.dataset.theme = t;
}
</script>
<template>
<div class="flex gap-2">
<button
v-for="t in DefaultThemes"
:key="t"
:data-variant="theme === t ? 'primary' : 'secondary'"
class="btn"
@click="setTheme(t)"
>
{{ t }}
</button>
</div>
</template>Overriding Accent Tokens
After loading a theme, override accent tokens with unlayered CSS (wins over @layer vibe.theme):
css
/* Custom tenant colour, not in the default themes */
:root {
--color-accent: #ff6b35;
--color-accent-dark: #cc4f1f;
--color-accent-light: #ff9a73;
--color-accent-hover: #ff9a73;
--color-accent-active: #cc4f1f;
--color-accent-contrast: #fff;
}Nested Theme Regions
html
<!-- Main interface in cyan -->
<div data-theme="cyan">
<nav class="bg-base">Main nav</nav>
<!-- Promotional sidebar in gold -->
<aside data-theme="gold" class="bg-base p-6">
<h2 class="text-primary">Upgrade</h2>
</aside>
</div>Light Mode with a Theme
html
<html data-theme="purple" data-mode="light">
<!-- Surfaces flip to light neutral scale, accent stays purple -->
</html>Type-Safe Theme Prop (Vue Component)
vue
<script setup lang="ts">
import type { DefaultTheme } from "@vibe-labs/design-themes-default";
const props = defineProps<{
theme?: DefaultTheme;
}>();
</script>
<template>
<div :data-theme="theme">
<slot />
</div>
</template>