Button
A versatile button component with multiple variants and sizes.
Import
import { Button, buttonVariants, type ButtonVariants } from '@gxp-dev/uikit'
Usage
Basic
<template>
<Button>Click me</Button>
</template>
With Click Handler
<script setup lang="ts">
import { Button } from '@gxp-dev/uikit'
const handleClick = () => {
console.log('Clicked!')
}
</script>
<template>
<Button @click="handleClick">Click me</Button>
</template>
Variants
The Button supports 6 visual variants:
<template>
<div class="flex flex-wrap gap-4">
<Button variant="default">Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
</div>
</template>
Variant Descriptions
| Variant | Use Case | Appearance |
|---|---|---|
default | Primary actions | Solid primary color background |
secondary | Secondary actions | Muted background |
destructive | Dangerous actions (delete, remove) | Red/danger color |
outline | Tertiary actions | Border only, transparent background |
ghost | Subtle actions | No border, transparent background |
link | Navigation-like actions | Underlined text |
Sizes
The Button supports 6 sizes:
<template>
<div class="flex items-center gap-4">
<Button size="sm">Small</Button>
<Button size="default">Default</Button>
<Button size="lg">Large</Button>
</div>
</template>
Icon Buttons
For icon-only buttons:
<script setup>
import { Button } from '@gxp-dev/uikit'
import { Plus, Settings, X } from 'lucide-vue-next'
</script>
<template>
<div class="flex items-center gap-4">
<Button size="icon-sm">
<X class="h-3 w-3" />
</Button>
<Button size="icon">
<Plus class="h-4 w-4" />
</Button>
<Button size="icon-lg">
<Settings class="h-5 w-5" />
</Button>
</div>
</template>
Size Dimensions
| Size | Height | Padding |
|---|---|---|
sm | 36px (h-9) | px-3 |
default | 40px (h-10) | px-4 py-2 |
lg | 44px (h-11) | px-8 |
icon | 40px (h-10 w-10) | - |
icon-sm | 36px (h-9 w-9) | - |
icon-lg | 44px (h-11 w-11) | - |
With Icons
Icon on Left
<script setup>
import { Button } from '@gxp-dev/uikit'
import { Mail } from 'lucide-vue-next'
</script>
<template>
<Button>
<Mail class="mr-2 h-4 w-4" />
Send Email
</Button>
</template>
Icon on Right
<template>
<Button>
Continue
<ArrowRight class="ml-2 h-4 w-4" />
</Button>
</template>
Loading State
<script setup>
import { ref } from 'vue'
import { Button } from '@gxp-dev/uikit'
import { Loader2 } from 'lucide-vue-next'
const isLoading = ref(false)
</script>
<template>
<Button :disabled="isLoading">
<Loader2 v-if="isLoading" class="mr-2 h-4 w-4 animate-spin" />
{{ isLoading ? 'Loading...' : 'Submit' }}
</Button>
</template>
Disabled State
<template>
<Button disabled>Disabled Button</Button>
</template>
Disabled buttons:
- Have reduced opacity (50%)
- Show
cursor-not-allowed - Don't respond to click events
As Different Element
As Anchor
<template>
<Button as="a" href="https://example.com">
Visit Site
</Button>
</template>
As Router Link
<script setup>
import { RouterLink } from 'vue-router'
import { Button } from '@gxp-dev/uikit'
</script>
<template>
<Button as-child>
<RouterLink to="/dashboard">
Go to Dashboard
</RouterLink>
</Button>
</template>
Custom Styling
Via Class Prop
<template>
<Button class="rounded-full w-full">
Full Width Rounded
</Button>
</template>
Using buttonVariants
For applying button styles to custom elements:
<script setup>
import { buttonVariants } from '@gxp-dev/uikit'
</script>
<template>
<a
href="/link"
:class="buttonVariants({ variant: 'outline', size: 'sm' })"
>
Styled Link
</a>
</template>
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'secondary' | 'destructive' | 'outline' | 'ghost' | 'link' | 'default' | Visual variant |
size | 'default' | 'sm' | 'lg' | 'icon' | 'icon-sm' | 'icon-lg' | 'default' | Button size |
as | string | Component | 'button' | Element to render as |
asChild | boolean | false | Merge props with child element |
disabled | boolean | false | Disable the button |
class | string | - | Additional CSS classes |
Events
| Event | Payload | Description |
|---|---|---|
click | MouseEvent | Emitted on click |
Slots
| Slot | Description |
|---|---|
default | Button content |
Exports
// Component
export { Button } from '@gxp-dev/uikit'
// Variant function
export { buttonVariants } from '@gxp-dev/uikit'
// Types
export type { ButtonVariants } from '@gxp-dev/uikit'
Accessibility
- Uses native
<button>element by default - Supports keyboard navigation (Enter/Space to activate)
- Properly disabled when
disabledprop is set - Focus visible ring for keyboard users
Examples
Form Submit Button
<template>
<form @submit.prevent="handleSubmit">
<!-- form fields -->
<Button type="submit">
Submit Form
</Button>
</form>
</template>
Button Group
<template>
<div class="flex">
<Button variant="outline" class="rounded-r-none">
Left
</Button>
<Button variant="outline" class="rounded-none border-x-0">
Center
</Button>
<Button variant="outline" class="rounded-l-none">
Right
</Button>
</div>
</template>
Confirmation Button
<script setup>
import { ref } from 'vue'
import { Button } from '@gxp-dev/uikit'
const confirmDelete = ref(false)
const handleDelete = () => {
if (confirmDelete.value) {
// Actually delete
console.log('Deleted!')
confirmDelete.value = false
} else {
confirmDelete.value = true
setTimeout(() => { confirmDelete.value = false }, 3000)
}
}
</script>
<template>
<Button
:variant="confirmDelete ? 'destructive' : 'outline'"
@click="handleDelete"
>
{{ confirmDelete ? 'Click again to confirm' : 'Delete' }}
</Button>
</template>