Skip to content

UI Components Reference

Detailed documentation for each component in the UI library with props, events, and usage examples.


A versatile button component with multiple variants, loading states, and icon support.

PropTypeDefaultDescription
variant'primary' | 'secondary' | 'danger' | 'success' | 'warning' | 'info''primary'Button style variant
outlinedbooleanfalseUse outline style
loadingbooleanfalseShow loading spinner
disabledbooleanfalseDisable the button
labelstringButton text (alternative to slot)
iconstringIcon identifier
as'icon'Render as icon button (circular)
<script setup>
import { Button } from '@/packages/ui';
import { PlusIcon, TrashIcon, DownloadIcon } from 'lucide-vue-next';
</script>
<template>
<!-- Variants -->
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="danger">Delete</Button>
<Button variant="success">Confirm</Button>
<Button variant="warning">Warning</Button>
<Button variant="info">Info</Button>
<!-- Outlined -->
<Button variant="primary" outlined>Outline Primary</Button>
<Button variant="danger" outlined>Outline Danger</Button>
<!-- States -->
<Button :loading="isLoading">{{ isLoading ? 'Saving...' : 'Save' }}</Button>
<Button disabled>Disabled</Button>
<!-- With Icons -->
<Button>
<template #icon><PlusIcon /></template>
Add Item
</Button>
<!-- Icon-only button -->
<Button as="icon" variant="danger">
<TrashIcon />
</Button>
</template>

Dropdown select component with search, icons, and multi-select support.

interface Item {
label: string;
value: string | number;
icon?: string;
description?: string;
nested?: Array<Field>; // For dynamic nested forms
}
PropTypeDefaultDescription
modelValuestring | number | ArraySelected value(s)
optionsItem[][]Available options
placeholderstringPlaceholder text
multiplebooleanfalseAllow multiple selection
searchablebooleanfalseEnable search filter
disabledbooleanfalseDisable the select
<script setup>
import { SelectForm, type Item } from '@/packages/ui/Select';
import { ref } from 'vue';
const selected = ref<string>('');
const multiSelected = ref<string[]>([]);
const countries: Item[] = [
{ label: 'United States', value: 'us', icon: '🇺🇸' },
{ label: 'Canada', value: 'ca', icon: '🇨🇦' },
{ label: 'Mexico', value: 'mx', icon: '🇲🇽' },
{ label: 'United Kingdom', value: 'uk', icon: '🇬🇧' },
];
const categories: Item[] = [
{ label: 'Electronics', value: 'electronics', description: 'Phones, laptops, tablets' },
{ label: 'Clothing', value: 'clothing', description: 'Shirts, pants, shoes' },
{ label: 'Books', value: 'books', description: 'Fiction, non-fiction, textbooks' },
];
</script>
<template>
<!-- Basic select -->
<SelectForm
v-model="selected"
:options="countries"
placeholder="Select a country"
/>
<!-- With descriptions -->
<SelectForm
v-model="selected"
:options="categories"
placeholder="Choose a category"
/>
<!-- Multi-select -->
<SelectForm
v-model="multiSelected"
:options="countries"
:multiple="true"
placeholder="Select countries"
/>
<!-- Searchable -->
<SelectForm
v-model="selected"
:options="countries"
:searchable="true"
placeholder="Search countries..."
/>
</template>

Multi-step wizard component for guided user flows.

PropTypeDefaultDescription
stepsStep[][]Step definitions
currentnumber0Active step index
clickablebooleanfalseAllow clicking to navigate
interface Step {
title: string;
description?: string;
icon?: string;
}
<script setup>
import { Steps } from '@/packages/ui';
import { ref } from 'vue';
const currentStep = ref(0);
const steps = [
{ title: 'Account', description: 'Create your account' },
{ title: 'Profile', description: 'Personal information' },
{ title: 'Preferences', description: 'Notification settings' },
{ title: 'Complete', description: 'Review and finish' },
];
function nextStep() {
if (currentStep.value < steps.length - 1) {
currentStep.value++;
}
}
function prevStep() {
if (currentStep.value > 0) {
currentStep.value--;
}
}
</script>
<template>
<Steps
:steps="steps"
:current="currentStep"
/>
<!-- Step Content -->
<div class="step-content">
<div v-if="currentStep === 0">
<h2>Create Account</h2>
<input placeholder="Email" />
<input type="password" placeholder="Password" />
</div>
<div v-if="currentStep === 1">
<h2>Your Profile</h2>
<input placeholder="Full Name" />
<input placeholder="Phone" />
</div>
<div v-if="currentStep === 2">
<h2>Preferences</h2>
<label><input type="checkbox" /> Email notifications</label>
<label><input type="checkbox" /> SMS notifications</label>
</div>
<div v-if="currentStep === 3">
<h2>All Done!</h2>
<p>Review your information and submit.</p>
</div>
</div>
<!-- Navigation -->
<div class="step-nav">
<Button
v-if="currentStep > 0"
variant="secondary"
@click="prevStep"
>
Previous
</Button>
<Button
v-if="currentStep < steps.length - 1"
@click="nextStep"
>
Next
</Button>
<Button
v-if="currentStep === steps.length - 1"
variant="success"
>
Submit
</Button>
</div>
</template>

Tab navigation for switching between content panels.

PropTypeDefaultDescription
modelValuestringActive tab ID
tabsTab[][]Tab definitions
interface Tab {
id: string;
label: string;
icon?: string;
disabled?: boolean;
}
<script setup>
import Tabs from '@/packages/ui/Tabs/Tabs.vue';
import { ref } from 'vue';
const activeTab = ref('overview');
const tabs = [
{ id: 'overview', label: 'Overview' },
{ id: 'analytics', label: 'Analytics' },
{ id: 'settings', label: 'Settings' },
{ id: 'logs', label: 'Logs', disabled: true },
];
</script>
<template>
<Tabs v-model="activeTab" :tabs="tabs" />
<div v-if="activeTab === 'overview'">
<h2>Overview</h2>
<p>Dashboard overview content...</p>
</div>
<div v-if="activeTab === 'analytics'">
<h2>Analytics</h2>
<p>Charts and metrics...</p>
</div>
<div v-if="activeTab === 'settings'">
<h2>Settings</h2>
<p>Configuration options...</p>
</div>
</template>

Toggle switch for boolean values.

PropTypeDefaultDescription
modelValuebooleanfalseCurrent state
labelstringLabel text
disabledbooleanfalseDisable the switch
<script setup>
import Switch from '@/packages/ui/Switch/Switch.vue';
import { ref } from 'vue';
const notifications = ref(true);
const darkMode = ref(false);
const maintenance = ref(false);
</script>
<template>
<Switch v-model="notifications" label="Email Notifications" />
<Switch v-model="darkMode" label="Dark Mode" />
<Switch v-model="maintenance" label="Maintenance Mode" disabled />
</template>

Text input field with validation support.

PropTypeDefaultDescription
modelValuestringInput value
type'text' | 'password' | 'email' | 'number' | 'url''text'Input type
placeholderstringPlaceholder text
labelstringLabel text
errorstringError message
disabledbooleanfalseDisable the input
<script setup>
import Input from '@/packages/ui/Input/Input.vue';
import { ref } from 'vue';
const email = ref('');
const password = ref('');
const emailError = ref('');
function validateEmail() {
if (!email.value.includes('@')) {
emailError.value = 'Please enter a valid email';
} else {
emailError.value = '';
}
}
</script>
<template>
<Input
v-model="email"
type="email"
label="Email"
placeholder="[email protected]"
:error="emailError"
@blur="validateEmail"
/>
<Input
v-model="password"
type="password"
label="Password"
placeholder="Enter password"
/>
</template>

Small status indicator for labels and counts.

PropTypeDefaultDescription
variant'primary' | 'secondary' | 'danger' | 'success' | 'warning''primary'Color variant
size'sm' | 'md' | 'lg''md'Badge size
<script setup>
import Badge from '@/packages/ui/Badge/Badge.vue';
</script>
<template>
<Badge variant="primary">New</Badge>
<Badge variant="success">Active</Badge>
<Badge variant="warning">Pending</Badge>
<Badge variant="danger">Error</Badge>
<!-- Sizes -->
<Badge size="sm">Small</Badge>
<Badge size="md">Medium</Badge>
<Badge size="lg">Large</Badge>
</template>

Loading placeholder for content.

PropTypeDefaultDescription
widthstring'100%'Width
heightstring'1rem'Height
roundedbooleanfalseUse rounded corners
circlebooleanfalseRender as circle
<script setup>
import Skeleton from '@/packages/ui/Skeleton/Skeleton.vue';
</script>
<template>
<!-- Text placeholder -->
<Skeleton height="1rem" width="80%" />
<Skeleton height="1rem" width="60%" />
<!-- Card placeholder -->
<div class="card">
<Skeleton height="200px" />
<Skeleton height="1.5rem" width="70%" />
<Skeleton height="1rem" width="100%" />
<Skeleton height="1rem" width="90%" />
</div>
<!-- Avatar placeholder -->
<Skeleton circle width="48px" height="48px" />
</template>