UIPackage
Menu

Framework

Change language

Boilerplate repo

Button

buttonui

Interactive button component with variants (default, destructive, outline, secondary, ghost, link), sizes, and composite ButtonGroup container for segmented toolbars and split buttons.

Also available for React ->

Installation

$npx shadcn-vue@latest add https://uipkge.dev/r/vue/button.json
Named registry:npx shadcn-vue@latest add @uipkge/buttonInstalls to:app/components/ui/button/

Examples

Loading interactive previews…

Props

NameType / ValuesDefaultRequired
asstring'button'optional
asChildbooleanoptional
variant
'default''destructive''outline''secondary''ghost''link'
'default'optional
size
'default''sm''lg''xs''icon''icon-sm''icon-lg''icon-xs''icon-2xs'
optional
type

Native button type. Defaults to `button` so forms are not submitted accidentally.

'button''submit''reset'
'button'optional
classHTMLAttributes['class']optional

Used by

Files installed (4)

  • app/components/ui/button/Button.vue1.7 kB
    <script setup lang="ts">
    import type { HTMLAttributes } from 'vue'
    import { Primitive } from 'reka-ui'
    import { cn } from '@/lib/utils'
    import { buttonVariants } from './button.variants'
    
    // Why inline these unions instead of `ButtonVariants['variant']` /
    // `ButtonVariants['size']`:
    //
    // `ButtonVariants` is `VariantProps<typeof buttonVariants>`. cva's
    // type machinery wraps the variant keys in a conditional + indexed
    // access (`{ [K in keyof Variants]?: ... }`), which Vue 3.5+'s SFC
    // compiler can't resolve. Result: defineProps<> silently drops
    // `variant`/`size` from the runtime declarations, every <Button
    // variant="ghost"> falls back to `default`, and SidebarTrigger
    // renders as a filled primary block.
    //
    // Inline the unions and Vue extracts them cleanly. The cva runtime
    // still validates against the same option set at runtime; we just
    // give the SFC compiler a type it can handle.
    type Variant = 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'
    type Size = 'default' | 'sm' | 'lg' | 'xs' | 'icon' | 'icon-sm' | 'icon-lg' | 'icon-xs' | 'icon-2xs'
    
    interface Props {
      as?: string
      asChild?: boolean
      variant?: Variant
      size?: Size
      /** Native button type. Defaults to `button` so forms are not submitted accidentally. */
      type?: 'button' | 'submit' | 'reset'
      class?: HTMLAttributes['class']
    }
    
    const props = withDefaults(defineProps<Props>(), {
      as: 'button',
      type: 'button',
      variant: 'default',
    })
    </script>
    
    <template>
      <Primitive
        data-uipkge
        data-slot="button"
        :data-variant="variant"
        :data-size="size"
        :as="as"
        :as-child="asChild"
        :type="as === 'button' && !asChild ? type : undefined"
        :class="cn(buttonVariants({ variant, size }), props.class)"
      >
        <slot />
      </Primitive>
    </template>
    
  • app/components/ui/button/ButtonGroup.vue3.4 kB
  • app/components/ui/button/button.variants.ts2.7 kB
  • app/components/ui/button/index.ts0.2 kB

Raw manifest:https://uipkge.dev/r/vue/button.json