A Vue 3 theming framework with shipped components.
Table of Contents
Vuecs is organized into five kinds of packages:
- Components (
@vuecs/button,@vuecs/forms,@vuecs/list,@vuecs/overlays, …) — render logic, props, slots, and structuralvc-*classes. Visually unstyled by default. - Themes (
@vuecs/theme-tailwind,@vuecs/theme-bootstrap,@vuecs/theme-bulma) — pure data objects mapping component slots (e.g.listItem.root,pagination.link) to CSS class strings. Swap, compose, or override themes without touching component code. - Icon presets (
@vuecs/icons-lucide,@vuecs/icons-font-awesome) — Iconify-name vocabularies that populate the semantic icon-prop slots on components likeVCPaginationandVCButton. Configured separately from themes viaicons: [...]. - Design tokens (
@vuecs/design) — CSS custom properties (--vc-color-*,--vc-radius-*, motion primitives) plus theme-agnosticuseColorMode/useColorPalettecomposables. Drives runtime palette switching across every theme. - Framework integrations (
@vuecs/nuxt) — SSR-safe color-mode + palette plugins, auto-imports, and module-level configuration for Nuxt apps.
Themes are resolved at runtime by @vuecs/core's theme manager through four layers: component defaults → themes (in array order) → global overrides → per-instance themeClass prop.
npm install @vuecs/core @vuecs/theme-bootstrap @vuecs/icon @vuecs/icons-lucideimport vuecs, { extend } from '@vuecs/core';
import bootstrap from '@vuecs/theme-bootstrap';
import lucide from '@vuecs/icons-lucide';
app.use(vuecs, {
themes: [bootstrap()],
icons: [lucide()],
overrides: {
elements: { listItem: { classes: { root: extend('border-bottom') } } },
},
});See @vuecs/core for the full theme API (installThemeManager, useComponentTheme, extend(), variant system).
Theme resolution engine and component infrastructure. Exports installThemeManager, useComponentTheme, extend(), resolveComponentTheme, and shared types. Required by every component and theme package.
CSS design tokens (--vc-color-*, --vc-radius-*), motion primitives (vanilla-CSS port of tw-animate-css), and theme-agnostic useColorMode / useColorPalette composables. Pair with @vuecs/design/standalone for Bootstrap or Bulma stacks that don't load Tailwind.
General-purpose <VCButton> with variant / color / size axes, loading state, and leading/trailing icon slots.
Atomic, presentation-only UI elements — VCSeparator, VCTag / VCTags, VCAvatar, VCAspectRatio, VCVisuallyHidden, VCBadge. Pure-CSS or thin Reka wrappers.
Compound overlays on Reka primitives — Modal (with useModal() view-stack composable), Popover, HoverCard, Tooltip, DropdownMenu, ContextMenu.
<VCIcon> — thin Iconify wrapper for vuecs's icon-string-prop slots and consumer slot content.
Compound list (VCList / VCListBody / VCListItem / VCListEmpty / VCListLoading) with the defineList() factory, useList() / useListItem() injectors, and built-in v-model:selection (single / multi, ARIA listbox). Header / footer / item-text / item-actions are consumer markup driven by slot-prop class strings.
<VCList :data="items" :busy="loading" v-model:selection="selected">
<template #default="{ classes }">
<header :class="classes.header">…</header>
<VCListBody>
<VCListItem v-for="item in items" :key="item.id" :value="item">
<template #default="{ classes }">
<span :class="classes.text">{{ item.name }}</span>
</template>
</VCListItem>
</VCListBody>
</template>
</VCList>Form inputs on Reka UI primitives, with validation support: Checkbox + CheckboxGroup, Switch, Radio + RadioGroup, Input, Number, Pin, Select + SelectSearch, Slider (single + range), Tags, Textarea.
<VCFormGroup label-content="Email" :validation-messages="errors">
<VCFormInput v-model="form.email" type="email" />
</VCFormGroup>Pagination component with page calculation utilities and Iconify-backed icon props.
<VCPagination :total="100" :limit="10" :offset="0" @load="onPageChange" />Multi-level navigation with NavigationManager, path-based active matching, and vue-router integration.
Countdown timer with auto-start, visibility handling, and a scoped slot for custom display.
Gravatar avatar component.
Router-aware link with automatic detection of vue-router or Nuxt.
Relative time display with locale support and auto-update.
Theme-agnostic Nuxt module — auto-imports @vuecs/design tokens, ships SSR-safe color-mode + palette plugins (useColorMode / useColorPalette auto-imports), and optionally auto-installs themes listed under vuecs: { themes: [...] }.
Themes are functions returning { elements, classesMergeFn? }. Multiple themes compose in array order. Themes resolve CSS class strings only — icon glyphs are provided separately by icon presets (@vuecs/icons-lucide, @vuecs/icons-font-awesome, …) configured under icons:. Themes only depend on @vuecs/core; the class strings they provide target whichever component packages the consumer has installed.
Bootstrap class defaults (form-control, btn btn-primary, d-flex, …) for every component. Currently targets Bootstrap 5; renamed from @vuecs/theme-bootstrap-v5 in 3.0 (clean break — no shim). The previous @vuecs/theme-bootstrap-v4 package was removed in the same release; Bootstrap 4's Sass-compiled stylesheet didn't benefit from the design-token bridge.
import bootstrap from '@vuecs/theme-bootstrap';
app.use(vuecs, { themes: [bootstrap()] });Tailwind CSS utility-class defaults for every component. Ships with tailwind-merge pre-wired as the theme's classesMergeFn so extend() calls in overrides merge cleanly, and exports a typed merge: ClassesMergeFn helper for reuse at the global overrides layer.
import tailwind, { merge } from '@vuecs/theme-tailwind';
app.use(vuecs, {
themes: [tailwind()],
overrides: { classesMergeFn: merge },
});Bulma 1.0+ theme — class strings (button is-primary, input, dropdown-content, …) for every component, plus an optional design-token bridge (@import "@vuecs/theme-bulma") that wires --bulma-* onto --vc-color-*.
import bulma from '@vuecs/theme-bulma';
app.use(vuecs, { themes: [bulma()] });Icon vocabularies are configured separately from themes. Pick an Iconify-backed preset (@vuecs/icons-lucide, @vuecs/icons-font-awesome) to populate the semantic icon-prop slots on VCPagination, VCButton, etc.
import vuecs from '@vuecs/core';
import bootstrap from '@vuecs/theme-bootstrap';
import lucide from '@vuecs/icons-lucide';
app.use(vuecs, {
themes: [bootstrap()],
icons: [lucide()],
});See @vuecs/icon for the runtime component (<VCIcon>) and the icon delivery options (Nuxt, Vite, SPA).
npm ci
npm run build
npm run test
npm run lintMade with 💚
Published under Apache 2.0 License.