primevue-theme-builder
v0.1.1
Published
A Vue 3 + PrimeVue theme builder package. Install it, drop in two components, and your users can pick built-in themes or build their own — with live preview, palette generation, font switching, and localStorage persistence.
Readme
PrimeVue Theme Builder
A Vue 3 + PrimeVue theme builder package. Install it, drop in two components, and your users can pick built-in themes or build their own — with live preview, palette generation, font switching, and localStorage persistence.
Requirements
- Vue 3.4+
- PrimeVue 4+ (with Aura base theme)
- PrimeIcons (for button icons)
- TailwindCSS (utility classes used in component templates)
Quick start
npm install primevue-theme-builderimport { createApp } from "vue";
import PrimeVue from "primevue/config";
import { NordicTheme, useTheme } from "primevue-theme-builder";
const app = createApp(App);
app.use(PrimeVue, {
theme: {
preset: NordicTheme,
options: { darkModeSelector: ".my-app-dark" },
},
});
app.mount("#app");
// Apply the persisted theme from localStorage
const { initTheme } = useTheme();
initTheme();Components
<ThemeChooser />
A popover button that lists all registered themes (built-in + custom). The user clicks a theme to switch instantly.
<script setup>
import { ThemeChooser } from "primevue-theme-builder";
</script>
<template>
<ThemeChooser>
<!-- Optional: inject extra content below the theme list -->
<template #footer="{ hide }">
<button @click="hide()">Open full editor…</button>
</template>
</ThemeChooser>
</template><ThemeBuilder />
A drawer (side panel) with the full theme editor: saved themes list, color sliders, typography, shape controls, and palette previews.
<script setup>
import { ref } from "vue";
import { ThemeBuilder } from "primevue-theme-builder";
const visible = ref(false);
</script>
<template>
<button @click="visible = true">Customize theme</button>
<ThemeBuilder v-model:visible="visible" position="right" />
</template>Props:
visible(boolean, v-model) — controls drawer visibilityposition("left" | "right", default"right") — drawer side
Exposed (via template ref):
primarySwatches—{ shade, hex }[]surfaceSwatches—{ shade, hex }[]state— reactiveThemeBuilderState
Built-in themes
| Theme | Export | Style |
|-------|--------|-------|
| Nordic | NordicTheme | Muted steel-blue, warm grey surfaces |
| Terracotta | TerracottaTheme | Dusty clay primary, warm parchment |
| Noir | NoirTheme | Near-black, cool zinc, editorial |
import { NordicTheme, TerracottaTheme, NoirTheme } from "primevue-theme-builder";Composables
useTheme()
Manages the active theme, switching, and custom theme registration.
const {
activeTheme, // Ref<string>
themeNames, // ComputedRef<string[]>
themeLabels, // Record<string, string>
themeAccents, // Record<string, string>
setTheme, // (name: string) => void
registerCustomTheme, // (name, label, accent, preset) => void
initTheme, // () => void — apply persisted theme on startup
} = useTheme();useThemeBuilder()
Full theme-building state machine with persistence.
const {
state, // reactive ThemeBuilderState
preset, // computed PrimeVue preset
primarySwatches, // computed { shade, hex }[]
surfaceSwatches, // computed { shade, hex }[]
savedThemes, // reactive SavedTheme[]
activeThemeId, // Ref<string | null>
saveCurrentTheme,
createTheme,
loadTheme,
deleteTheme,
resetCurrentTheme,
} = useThemeBuilder();Generator functions
For programmatic use without the UI:
import { generatePreset, defaults } from "primevue-theme-builder";
const preset = generatePreset({ ...defaults, primaryHue: 220 });generatePreset(state)— full PrimeVue Aura preset fromThemeBuilderStategeneratePrimaryPalette(hue, sat, lightness)— 11-shade color palettegenerateAlertPalette(hue)— 11-shade alert palettegenerateSurfacePalette(hue, sat)— surface/neutral palettegenerateShadow(intensity, hue)— CSS box-shadow stringhslToHex(h, s, l)/hexToRgb(hex)— color conversion utilities
ThemeBuilderState
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| name | string | "Custom" | Theme display name |
| primaryHue | number | 210 | Primary color hue (0–360) |
| primarySaturation | number | 30 | Primary saturation (0–100) |
| primaryLightness | number | 50 | Primary lightness (0–100) |
| accentHue | number | 35 | Accent hue |
| accentSaturation | number | 70 | Accent saturation |
| accentLightness | number | 50 | Accent lightness |
| surfaceHue | number | 35 | Surface hue |
| surfaceSaturation | number | 8 | Surface saturation |
| borderRadius | number | 10 | Component border radius (px) |
| cardBorderRadius | number | 16 | Card border radius (px) |
| paddingScale | number | 100 | Padding scale (%) |
| fontWeight | number | 500 | Base font weight |
| shadowIntensity | number | 50 | Shadow intensity (0–100) |
| focusRingStyle | FocusRingStyle | "dashed" | Focus ring style |
| titleFont | GoogleFont | "Playfair Display" | Title font |
| bodyFont | GoogleFont | "Inter" | Body font |
| buttonPaddingX | number | 1.25 | Button padding X (rem) |
| buttonPaddingY | number | 0.625 | Button padding Y (rem) |
| alertSuccessHue | number | 142 | Success alert hue |
| alertWarnHue | number | 45 | Warning alert hue |
| alertErrorHue | number | 0 | Error alert hue |
| alertInfoHue | number | 210 | Info alert hue |
