Skip to main content
Version: v1 (Current)

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

VariantUse CaseAppearance
defaultPrimary actionsSolid primary color background
secondarySecondary actionsMuted background
destructiveDangerous actions (delete, remove)Red/danger color
outlineTertiary actionsBorder only, transparent background
ghostSubtle actionsNo border, transparent background
linkNavigation-like actionsUnderlined 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

SizeHeightPadding
sm36px (h-9)px-3
default40px (h-10)px-4 py-2
lg44px (h-11)px-8
icon40px (h-10 w-10)-
icon-sm36px (h-9 w-9)-
icon-lg44px (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>
<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

PropTypeDefaultDescription
variant'default' | 'secondary' | 'destructive' | 'outline' | 'ghost' | 'link''default'Visual variant
size'default' | 'sm' | 'lg' | 'icon' | 'icon-sm' | 'icon-lg''default'Button size
asstring | Component'button'Element to render as
asChildbooleanfalseMerge props with child element
disabledbooleanfalseDisable the button
classstring-Additional CSS classes

Events

EventPayloadDescription
clickMouseEventEmitted on click

Slots

SlotDescription
defaultButton 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 disabled prop 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>