@sabrenski/spire-ui-vue
Spire UI
A modern, themeable Vue 3 component library with 57+ components, built with TypeScript and Tailwind CSS v4.
Installation
npm install @sabrenski/spire-ui-vue
# or
pnpm add @sabrenski/spire-ui-vue
# or
yarn add @sabrenski/spire-ui-vue
Peer Dependencies
npm install vue@^3.0.0
RichTextEditor Setup (Optional)
If you use the RichTextEditor component, install the Tiptap dependencies:
npm install @tiptap/vue-3 @tiptap/starter-kit @tiptap/pm \
@tiptap/extension-link @tiptap/extension-image @tiptap/extension-placeholder \
@tiptap/extension-text-align @tiptap/extension-underline @tiptap/extension-color \
@tiptap/extension-text-style @tiptap/extension-highlight @tiptap/extension-typography \
@tiptap/extension-table @tiptap/extension-table-row @tiptap/extension-table-cell \
@tiptap/extension-table-header @tiptap/extension-task-list @tiptap/extension-task-item \
@tiptap/extension-character-count @tiptap/extension-bubble-menu @tiptap/extension-font-family
PhoneInput Setup (Optional)
If you use the PhoneInput component with country flags, install:
npm install flag-icons
Quick Start
1. CSS Setup (Required)
Spire UI uses Tailwind CSS v4's @theme directive for theming. Add these imports to your main CSS file:
/* app.css */
@import "@sabrenski/spire-ui-vue/theme.css";
@import "tailwindcss";
/* Required: Tell Tailwind to scan component files for utility classes */
@source "../node_modules/@sabrenski/spire-ui-vue/dist/**/*.js";
- theme.css - Must be imported before
tailwindcssso Tailwind processes the theme tokens - @source - Required for Tailwind to discover which utility classes the components use
2. Vue Plugin Setup
// main.ts
import { createApp } from 'vue'
import { SpireUI } from '@sabrenski/spire-ui-vue'
import App from './App.vue'
const app = createApp(App)
// Optional: Configure global defaults
app.use(SpireUI, {
defaults: {
form: { variant: 'outline', size: 'md' },
button: { variant: 'primary', size: 'md' },
}
})
app.mount('#app')
<script setup lang="ts">
import { Button, Badge, Input, Card } from '@sabrenski/spire-ui-vue'
import type { ButtonProps } from '@sabrenski/spire-ui-vue'
</script>
<template>
<Card>
<Input placeholder="Enter your email" />
<Button variant="primary">Subscribe</Button>
</Card>
</template>
Global Configuration
Spire UI supports global default configuration for components using the Vue plugin pattern. This allows you to set default prop values across your entire application.
Plugin Setup
import { createApp } from 'vue'
import { SpireUI } from '@sabrenski/spire-ui-vue'
import type { SpireUIOptions } from '@sabrenski/spire-ui-vue'
const app = createApp(App)
app.use(SpireUI, {
defaults: {
// Form components: Input, Textarea, Select, NumberInput, Autocomplete
form: {
variant: 'filled', // 'outline' | 'filled' | 'underline'
size: 'md', // 'sm' | 'md' | 'lg'
},
// Button component
button: {
variant: 'primary', // 'primary' | 'secondary' | 'danger' | 'ghost' | 'contrast' | 'outline'
size: 'md', // 'sm' | 'md' | 'lg'
radius: 'md', // 'none' | 'sm' | 'md' | 'lg' | 'full'
},
// Badge component
badge: {
variant: 'solid', // 'solid' | 'flat' | 'outline'
color: 'default', // 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'
size: 'md', // 'sm' | 'md' | 'lg'
},
// Avatar component
avatar: {
size: 'md', // 'xs' | 'sm' | 'md' | 'lg'
color: 'default', // 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger'
radius: 'full', // 'none' | 'sm' | 'md' | 'lg' | 'full'
},
// Alert component
alert: {
variant: 'flat', // 'flat' | 'solid'
color: 'default', // 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger'
radius: 'md', // 'none' | 'sm' | 'md' | 'lg' | 'full'
},
// Spinner component
spinner: {
size: 'md', // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
variant: 'ring', // 'ring' | 'dots'
},
// Tabs component
tabs: {
variant: 'solid', // 'solid' | 'underline' | 'bordered'
color: 'default', // 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger'
size: 'md', // 'sm' | 'md' | 'lg'
radius: 'md', // 'none' | 'sm' | 'md' | 'lg' | 'full'
},
// Progress component
progress: {
variant: 'linear', // 'linear' | 'circular'
color: 'primary', // 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger'
size: 'md', // 'sm' | 'md' | 'lg'
},
// Card component
card: {
shadow: 'md', // 'none' | 'sm' | 'md' | 'lg'
radius: 'lg', // 'none' | 'sm' | 'md' | 'lg'
},
// Icon component
icon: {
size: 'md', // 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'
stroke: 'regular', // 'thin' | 'light' | 'regular' | 'medium' | 'bold'
},
}
} as SpireUIOptions)
app.mount('#app')
Resolution Order
Props are resolved in the following order:
- Prop value - If a prop is explicitly passed to a component, it always takes precedence
- Global default - Value from the plugin configuration
- Hardcoded fallback - Built-in default value in the component
<!-- Uses global default variant, but overrides size -->
<Input size="lg" />
<!-- Uses both global defaults for variant and size -->
<Input />
<!-- Explicit props always win -->
<Input variant="underline" size="sm" />
Programmatic Configuration
You can also configure defaults programmatically:
import { configureDefaults, getDefaults, resetDefaults } from '@sabrenski/spire-ui-vue'
// Set defaults at runtime
configureDefaults({
form: { variant: 'filled' },
button: { variant: 'secondary' }
})
// Get current defaults
const currentDefaults = getDefaults()
// Reset to empty (use component fallbacks)
resetDefaults()
Components
Layout & Structure
- Card - Container with optional header, body, and footer
- Divider - Horizontal or vertical separator
- Group - Flex container for grouping elements
- Modal - Dialog overlay with customizable placement
- Popover - Floating content panel
- Sidebar - Collapsible navigation panel
- Navbar - Navigation bar with brand, items, and mobile menu
Forms & Inputs
- Input - Text input with validation states
- Textarea - Multi-line text input
- Select - Dropdown selection with search
- Autocomplete - Input with suggestions
- Checkbox - Single or group checkboxes
- Radio - Radio button groups
- Switch - Toggle switch
- Slider - Range slider
- NumberInput - Numeric input with increment/decrement
- DatePicker - Date selection with calendar
- TimePicker - Time selection
- ColorPicker - Color selection with presets
- FileInput - File upload input
- OTPInput - One-time password input
- PhoneInput - International phone input with country codes
- RichTextEditor - WYSIWYG editor powered by TipTap
- FormField - Form field wrapper with label and validation
Data Display
- Table - Data table with sorting and pagination
- DataList - Key-value list display
- Badge - Status indicators and labels
- Avatar - User profile images with fallback
- AvatarGroup - Stacked avatars
- Icon - Icon wrapper with size presets
- IconPicker - Icon selection from 9000+ icons
- Image - Responsive image with loading states
- Progress - Progress bar
- Spinner - Loading indicator
- User - User info display with avatar
- Tooltip - Hover tooltips
Navigation
- Tabs - Tab navigation
- Breadcrumbs - Breadcrumb navigation
- Pagination - Page navigation
- Link - Styled anchor links
Feedback
- Alert - Alert messages with variants
- Toast - Toast notifications
- EmptyState - Empty state placeholder
- Error - Error display
Typography
- Heading - Semantic headings (h1-h6)
- Text - Text with size and color variants
- Label - Form labels
- Hint - Helper text
Charts
- LineChart - Line/area charts
- BarChart - Bar charts
- PieChart - Pie/donut charts
- Sparkline - Compact inline charts
- StatsCard - Metric display with trend
Advanced
- Accordion - Collapsible content panels
- Calendar - Full calendar view
- Carousel - Responsive carousel/slider
- EventsCalendar - Events calendar with day/week/month views
- Dropdown - Dropdown menu with items and sections
- Rating - Star rating input
- Timer - Countdown/stopwatch timer
- Tree - Hierarchical tree view
Composables
import { useToast, useDarkMode, useTheme, useRovingFocus, useVirtualScroll, useComponentDefault } from '@sabrenski/spire-ui-vue'
- useToast - Toast notification management
- useDarkMode - Dark mode management with system preference detection
- useTheme - Color scheme theme management
- useRovingFocus - Keyboard navigation for lists
- useVirtualScroll - Virtualized scrolling for large lists
- useAnchor - CSS anchor positioning
- useTrigger - Trigger/popover positioning
- useScrollDirection - Scroll direction detection
- useChart - Chart utilities
- useComponentDefault - Resolve component defaults from global config
useDarkMode
Manage dark mode with system preference detection and localStorage persistence.
<script setup>
import { useDarkMode } from '@sabrenski/spire-ui-vue'
const { isDark, toggle, set, clearPreference } = useDarkMode()
</script>
<template>
<button @click="toggle">
{{ isDark ? 'Light Mode' : 'Dark Mode' }}
</button>
</template>
| Option | Type | Default | Description |
|---|---|---|---|
storageKey |
string |
'spire-dark-mode' |
localStorage key for persistence |
initialValue |
boolean |
System preference | Initial dark mode state |
selector |
string |
'html' |
Element to apply dark class |
darkClass |
string |
'dark' |
CSS class for dark mode |
listenToSystemChanges |
boolean |
true |
React to system preference changes |
| Return | Type | Description |
|---|---|---|
isDark |
Ref<boolean> |
Reactive dark mode state |
toggle |
() => void |
Toggle dark mode on/off |
set |
(value: boolean) => void |
Set dark mode explicitly |
clearPreference |
() => void |
Clear stored preference and follow system |
useTheme
Manage color scheme themes with localStorage persistence.
<script setup>
import { useTheme } from '@sabrenski/spire-ui-vue'
const { schemes, currentScheme, setScheme } = useTheme()
</script>
<template>
<select v-model="currentScheme">
<option v-for="scheme in schemes" :key="scheme" :value="scheme">
{{ scheme }}
</option>
</select>
</template>
| Option | Type | Default | Description |
|---|---|---|---|
storageKey |
string |
'spire-theme-scheme' |
localStorage key for persistence |
initialScheme |
ThemeScheme |
'default' |
Initial color scheme |
selector |
string |
'html' |
Element to apply theme class |
customSchemes |
string[] |
[] |
Additional custom schemes |
| Return | Type | Description |
|---|---|---|
schemes |
ComputedRef<ThemeScheme[]> |
All available scheme names |
currentScheme |
Ref<ThemeScheme> |
Current active scheme |
setScheme |
(scheme: ThemeScheme) => void |
Set the color scheme |
clearPreference |
() => void |
Clear stored preference and reset to default |
Available schemes: 'default', 'ocean', 'forest', 'sunset', 'rose', 'midnight'
Component Examples
Button
<Button variant="primary" size="md" :loading="isLoading">
Submit
</Button>
| Prop | Type | Default | Description |
|---|---|---|---|
variant |
'primary' | 'secondary' | 'danger' | 'ghost' | 'contrast' | 'outline' |
'primary' |
Visual style |
size |
'sm' | 'md' | 'lg' |
'md' |
Button size |
disabled |
boolean |
false |
Disable interactions |
loading |
boolean |
false |
Show loading spinner |
iconOnly |
boolean |
false |
Icon-only mode |
type |
'button' | 'submit' | 'reset' |
'button' |
HTML button type |
Badge
<Badge content="New" color="primary" />
<Badge content="3" color="danger" placement="top-right">
<Button>Notifications</Button>
</Badge>
| Prop | Type | Default | Description |
|---|---|---|---|
content |
string | number |
- | Badge content |
variant |
'solid' | 'flat' | 'outline' |
'solid' |
Visual style |
color |
'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' |
'default' |
Color |
size |
'sm' | 'md' | 'lg' |
'md' |
Size |
dot |
boolean |
false |
Show as dot |
Icon
<script setup>
import { Icon } from '@sabrenski/spire-ui-vue'
</script>
<template>
<Icon name="home-01" size="md" />
</template>
| Prop | Type | Default | Description |
|---|---|---|---|
name |
string |
required | Icon name from Hugeicons |
size |
'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' |
'md' |
Size (12-40px) |
stroke |
'thin' | 'light' | 'regular' | 'medium' | 'bold' |
'regular' |
Stroke width |
See Icon System Guide for advanced configuration including custom adapters and icon registries.
Toast
<script setup>
import { useToast, ToastContainer } from '@sabrenski/spire-ui-vue'
const toast = useToast()
function showToast() {
toast.success('Operation completed!')
}
</script>
<template>
<Button @click="showToast">Show Toast</Button>
<ToastContainer />
</template>
Theming
CSS Imports
Spire UI provides two CSS exports:
| Import | Purpose |
|---|---|
@sabrenski/spire-ui-vue/theme.css |
Raw @theme tokens for Tailwind v4 to process |
@sabrenski/spire-ui-vue/style.css |
Pre-built component styles (optional) |
For Tailwind v4 projects:
/* app.css */
@import "@sabrenski/spire-ui-vue/theme.css";
@import "tailwindcss";
/* Required: Scan component files for utility classes */
@source "../node_modules/@sabrenski/spire-ui-vue/dist/**/*.js";
You can also import individual theme files:
@import "@sabrenski/spire-ui-vue/theme/base.css"; /* Color palette */
@import "@sabrenski/spire-ui-vue/theme/semantic.css"; /* Semantic tokens + dark mode */
@import "@sabrenski/spire-ui-vue/theme/components.css"; /* Component-specific tokens */
Dark Mode
Add the dark class to <html> or any parent element:
<html class="dark">
Theme Variants
- Light (default)
- Dark (
class="dark") - Ocean (
class="ocean") - Forest (
class="forest") - Sunset (
class="sunset") - Rose (
class="rose") - Midnight (
class="midnight")
Customizing Colors
Override the base color variables to customize the entire palette:
:root {
--color-primary-base: oklch(55% 0.2 250); /* Blue primary */
--color-danger-base: oklch(55% 0.22 27);
}
Or override individual semantic tokens:
:root {
--color-primary: oklch(0.6 0.2 250);
--color-primary-hover: oklch(0.55 0.2 250);
}
TypeScript
Full TypeScript support with exported types:
import type {
ButtonProps,
BadgeProps,
AlertProps,
CardProps,
ModalProps,
ToastOptions,
SpinnerProps,
TooltipProps,
// Global configuration types
SpireUIOptions,
SpireUIDefaults,
} from '@sabrenski/spire-ui-vue'
Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
License
MIT
Related Packages
A clean, dark-mode-ready Vue 3 component library — 100+ token-driven, themeable,...
Vibe UI — a Vue 3 component library for vibe coders: 50+ components, dark/light...
Cocoar Design System — a touch-first Vue 3 component library with 30+ accessible...
The design system behind Hikarinagi: Vue 3 components built on Tailwind CSS v4.
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.3.39 | ^3.0.0 | MIT | |
| 0.3.38 | ^3.0.0 | MIT | |
| 0.3.37 | ^3.0.0 | MIT | |
| 0.3.36 | ^3.0.0 | MIT | |
| 0.3.35 | ^3.0.0 | MIT | |
| 0.3.34 | ^3.0.0 | MIT | |
| 0.3.33 | ^3.0.0 | MIT | |
| 0.3.32 | ^3.0.0 | MIT | |
| 0.3.31 | ^3.0.0 | MIT | |
| 0.3.30 | ^3.0.0 | MIT | |
| 0.3.29 | ^3.0.0 | MIT | |
| 0.3.28 | ^3.0.0 | MIT | |
| 0.3.27 | ^3.0.0 | MIT | |
| 0.3.26 | ^3.0.0 | MIT | |
| 0.3.25 | ^3.0.0 | MIT | |
| 0.3.24 | ^3.0.0 | MIT | |
| 0.3.23 | ^3.0.0 | MIT | |
| 0.3.22 | ^3.0.0 | MIT | |
| 0.3.21 | ^3.0.0 | MIT | |
| 0.3.20 | ^3.0.0 | MIT | |
| 0.3.19 | ^3.0.0 | MIT | |
| 0.3.18 | ^3.0.0 | MIT | |
| 0.3.17 | ^3.0.0 | MIT | |
| 0.3.16 | ^3.0.0 | MIT | |
| 0.3.15 | ^3.0.0 | MIT | |
| 0.3.14 | ^3.0.0 | MIT | |
| 0.3.13 | ^3.0.0 | MIT | |
| 0.3.12 | ^3.0.0 | MIT | |
| 0.3.11 | ^3.0.0 | MIT | |
| 0.3.10 | ^3.0.0 | MIT |
Showing the latest 30 of 55. See every release on npm