Skip to content

UI Library Overview

The packages/ui directory contains a collection of reusable Vue components styled with TailwindCSS 4. These components follow a similar pattern to shadcn/ui - providing primitives that you can copy, customize, and own.


Button

Multi-variant button with loading states and icon support.

Input

Text input with validation and label support.

Select

Dropdown select with search and multi-select options.

Dialog

Modal dialog with header, body, and footer slots.

Drawer

Slide-out panel for side content.

Tabs

Tab navigation component.

Steps

Multi-step wizard component.

Card

Content container with header and sections.


ComponentDescription
AccordionExpandable/collapsible content sections
BadgeSmall status indicators and labels
ButtonInteractive buttons with variants
CardContent container with header, body, footer
CheckboxBoolean input control
DialogModal popup windows
DrawerSlide-out side panels
InputText input fields
JsonViewerJSON data display component
LabelForm field labels
MenuDropdown menu lists
SelectDropdown selection
SkeletonLoading placeholder
StepsMulti-step wizard
SwitchToggle switch control
TableData table display
TabsTab navigation
TextareaMulti-line text input

These components are used internally within ion-components. Import them directly:

// In ion-components source files
import { Button } from '@/packages/ui';
import { Steps } from '@/packages/ui';
import Tabs from '@/packages/ui/Tabs/Tabs.vue';
import { SelectForm, type Item } from '@/packages/ui/Select';

  1. TailwindCSS Native: All styling uses Tailwind utility classes
  2. OKLCH Colors: Modern color system with semantic tokens
  3. Dark Mode Ready: All components support light/dark themes
  4. Composable: Small, focused components that compose together
  5. TypeScript First: Full type definitions for props and events

<script setup>
import { Button } from '@/packages/ui';
</script>
<template>
<!-- Primary button -->
<Button variant="primary">Submit</Button>
<!-- Secondary button -->
<Button variant="secondary">Cancel</Button>
<!-- Danger button -->
<Button variant="danger">Delete</Button>
<!-- Loading state -->
<Button :loading="true">Processing...</Button>
<!-- Outlined style -->
<Button variant="primary" outlined>Outline</Button>
<!-- Icon button -->
<Button as="icon">
<PlusIcon />
</Button>
</template>
<script setup>
import { SelectForm, type Item } from '@/packages/ui/Select';
import { ref } from 'vue';
const selected = ref('');
const options: Item[] = [
{ label: 'Option 1', value: 'opt1' },
{ label: 'Option 2', value: 'opt2' },
{ label: 'Option 3', value: 'opt3', description: 'With description' },
];
</script>
<template>
<SelectForm
v-model="selected"
:options="options"
placeholder="Select an option..."
/>
</template>
<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: 'Add profile details' },
{ title: 'Review', description: 'Confirm information' },
];
</script>
<template>
<Steps
:steps="steps"
:current="currentStep"
@change="currentStep = $event"
/>
<!-- Step content -->
<div v-if="currentStep === 0">Step 1 content</div>
<div v-if="currentStep === 1">Step 2 content</div>
<div v-if="currentStep === 2">Step 3 content</div>
</template>
<script setup>
import Tabs from '@/packages/ui/Tabs/Tabs.vue';
import { ref } from 'vue';
const activeTab = ref('general');
const tabs = [
{ id: 'general', label: 'General' },
{ id: 'advanced', label: 'Advanced' },
{ id: 'security', label: 'Security' },
];
</script>
<template>
<Tabs
v-model="activeTab"
:tabs="tabs"
/>
<div v-if="activeTab === 'general'">General settings</div>
<div v-if="activeTab === 'advanced'">Advanced settings</div>
<div v-if="activeTab === 'security'">Security settings</div>
</template>

packages/ui/
├── index.ts # Main exports
├── theme.css # Theme variables (OKLCH)
├── ui.css # Global UI styles
├── types.ts # Shared TypeScript types
├── webcomponent.css # Styles for CE context
├── Accordion/
│ └── Accordion.vue
├── Badge/
│ └── Badge.vue
├── Button/
│ ├── index.ts
│ ├── Button.vue
│ └── variants.ts
├── Card/
│ ├── Card.vue
│ ├── CardHeader.vue
│ ├── CardContent.vue
│ └── ...
├── Dialog/
│ └── Dialog.vue
├── Drawer/
│ └── Drawer.vue
├── Input/
│ ├── Input.vue
│ └── ...
├── Select/
│ ├── index.ts
│ ├── Select.vue
│ ├── SelectForm.vue
│ └── ...
├── Steps/
│ ├── index.ts
│ └── Steps.vue
├── Switch/
│ └── Switch.vue
├── Tabs/
│ ├── Tabs.vue
│ └── Tab.vue
└── ...