Button Component
A versatile button component built with TypeScript and styled with Tailwind CSS. Supports multiple variants, sizes, and states for comprehensive UI interactions.
Overview
The Button component provides a consistent interface element with multiple styling variants, sizes, and accessibility features built-in. It follows the shadcn/ui design system patterns.
Preview

Basic Usage
<template>
<div class="space-x-4">
<!-- Default button -->
<Button label="Click me" variant="default" size="medium" />
<!-- Success button with icon -->
<Button label="Success" variant="success" icon="heroicons:check" size="medium" />
<!-- Warning button -->
<Button label="Warning" variant="warning" size="medium" />
<!-- Glassmorphism button -->
<Button label="Glass Effect" variant="glassmorphism" size="medium" />
<!-- Disabled button -->
<Button label="Disabled" variant="default" size="medium" :disabled="true" />
</div>
</template>
<script setup lang="ts">
import Button from '@/components/Button.vue'
</script>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Component API
Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | Required | Button text content |
variant | 'success' | 'warning' | 'default' | 'glassmorphism' | 'default' | Button visual style variant |
size | 'small' | 'medium' | 'large' | 'medium' | Button size |
disabled | boolean | false | Disable button interaction |
className | string | '' | Additional CSS classes |
icon | string | undefined | Icon name from Iconify collection |
Events
The Button component supports all native button events through v-bind="$attrs":
@click- Click event handler@focus- Focus event handler@blur- Blur event handler@mouseenter- Mouse enter event@mouseleave- Mouse leave event
Slots
Ce composant n'utilise pas de slots. Le contenu est défini via la prop label et les icônes via la prop icon.
Variants
Default
Transparent button with border styling, perfect for secondary actions.
<Button label="Default Action" variant="default" size="medium" />Styles :
- Light:
bg-transparent hover:bg-gray-100avec bordures grises - Dark:
dark:bg-transparent dark:hover:bg-gray-800avec bordures sombres
Success
Green button for positive actions (save, confirm, etc.).
<Button label="Save Changes" variant="success" icon="heroicons:check" size="medium" />Styles :
- Light:
bg-green-500 hover:bg-green-600avec ombres - Dark:
dark:bg-green-600 dark:hover:bg-green-700
Warning
Red button for dangerous or warning actions (delete, remove, etc.).
<Button label="Delete Account" variant="warning" icon="heroicons:trash" size="medium" />Styles :
- Light:
bg-red-300 hover:bg-red-400avec ombres - Dark:
dark:bg-red-400 dark:hover:bg-red-500
Glassmorphism
Modern glass effect button with backdrop blur and transparency.
<Button label="Glass Effect" variant="glassmorphism" size="medium" />Styles :
- Light:
bg-white/20 backdrop-blur-mdavec bordures semi-transparentes - Dark:
dark:bg-gray-900/20avec effet de flou et transparence
Sizes
Small
Compact button for secondary actions or tight spaces.
<Button label="Small" variant="default" size="small" />Styles : px-3 py-1.5 text-sm
Medium
Standard button size for most use cases.
<Button label="Medium" variant="success" size="medium" />Styles : px-4 py-2 text-base
Large
Prominent button for primary actions.
<Button label="Large" variant="warning" size="large" />Styles : px-6 py-3 text-lg
Advanced Examples
With Icons
<template>
<div class="space-x-4">
<!-- Success with check icon -->
<Button label="Save" variant="success" icon="heroicons:check" size="medium" />
<!-- Warning with trash icon -->
<Button label="Delete" variant="warning" icon="heroicons:trash" size="medium" />
<!-- Default with plus icon -->
<Button label="Add Item" variant="default" icon="heroicons:plus" size="medium" />
<!-- Glassmorphism with star icon -->
<Button label="Favorite" variant="glassmorphism" icon="heroicons:star" size="medium" />
</div>
</template>2
3
4
5
6
7
8
9
10
11
12
13
14
15
Loading State
<template>
<Button
:label="isLoading ? 'Loading...' : 'Submit'"
:icon="isLoading ? 'heroicons:arrow-path' : 'heroicons:paper-airplane'"
variant="success"
size="medium"
:disabled="isLoading"
:className="isLoading ? 'animate-pulse' : ''"
/>
</template>
<script setup lang="ts">
const isLoading = ref(false)
const handleSubmit = async () => {
isLoading.value = true
try {
// Your async operation
await submitForm()
} finally {
isLoading.value = false
}
}
</script>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Form Integration
<template>
<form @submit.prevent="handleSubmit">
<input v-model="email" type="email" placeholder="Enter email" />
<div class="flex gap-4 mt-4">
<Button
label="Submit"
variant="success"
icon="heroicons:paper-airplane"
size="medium"
:disabled="!email"
/>
<Button
label="Reset"
variant="default"
icon="heroicons:arrow-path"
size="medium"
@click="reset"
/>
</div>
</form>
</template>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Styling Details
CSS Classes Structure
The button uses a combination of base classes and variant-specific classes:
// Base classes (always applied)
'transition-all duration-300 flex items-center justify-center rounded-md px-4 py-2 font-medium'
// Variant classes (applied based on variant prop)
variants = {
success: 'bg-green-500 hover:bg-green-600 text-white shadow-lg hover:shadow-xl dark:bg-green-600 dark:hover:bg-green-700',
warning: 'bg-red-300 hover:bg-red-400 text-white shadow-lg hover:shadow-xl dark:bg-red-400 dark:hover:bg-red-500',
default: 'bg-transparent hover:bg-gray-100 text-gray-700 border border-gray-300 hover:border-gray-400 dark:bg-transparent dark:hover:bg-gray-800 dark:text-gray-300 dark:border-gray-600 dark:hover:border-gray-500',
glassmorphism: 'bg-white/20 backdrop-blur-md border border-white/30 text-gray-800 hover:bg-white/30 hover:border-white/40 shadow-lg dark:bg-gray-900/20 dark:border-gray-700/30 dark:text-gray-200 dark:hover:bg-gray-900/30 dark:hover:border-gray-700/40'
}
// Size classes (applied based on size prop)
sizes = {
small: 'px-3 py-1.5 text-sm',
medium: 'px-4 py-2 text-base',
large: 'px-6 py-3 text-lg'
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Custom Styling
You can extend styling using the className prop:
<Button
label="Custom Styled Button"
variant="default"
size="medium"
className="border-2 border-dashed hover:border-solid shadow-xl"
/>2
3
4
5
6
Accessibility
The Button component includes built-in accessibility features:
- Keyboard Navigation - Full keyboard support with Enter and Space
- Focus Management - Visible focus rings with
focus-visible - Disabled State - Proper disabled handling with
pointer-events-none - ARIA Support - Inherits all native button ARIA attributes
Screen Reader Support
<!-- Button with screen reader label -->
<Button
label="Close"
variant="default"
icon="heroicons:x-mark"
size="medium"
aria-label="Close dialog"
/>
<!-- Button with description -->
<Button
label="Submit Form"
variant="success"
icon="heroicons:paper-airplane"
size="medium"
aria-describedby="button-help"
/>
<div id="button-help" class="sr-only">
This will submit your form data
</div>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Utility Function
The component uses a utility function for class merging:
import { cn } from '@/lib/utils'
// cn() combines classes intelligently, handling conflicts
const className = cn(
'base-classes',
variants[variant],
sizes[size],
props.className
)2
3
4
5
6
7
8
9
TypeScript Support
Full TypeScript integration with proper prop types:
interface Props {
label: string
variant: 'success' | 'warning' | 'default' | 'glassmorphism'
size: 'small' | 'medium' | 'large'
disabled?: boolean
className?: string
icon?: string
}2
3
4
5
6
7
8
Dependencies
- @nuxt/icon - Pour les icônes Iconify
- Tailwind CSS - Pour le styling
- Vue 3 - Composition API
- TypeScript - Support des types