Beta, expect API change, and bugs. Hit one? Tell us.

Skip to content

Button

An action trigger.

<script setup lang="ts">
import { Button } from '@shardsui/vue/button'
</script>

<template>
  <Button
    class="font-inherit m-0 flex h-8 items-center justify-center gap-2 rounded-md border border-gray-200 bg-gray-50 px-3 text-sm/6 font-normal text-nowrap text-gray-900 outline-0 select-none hover:bg-gray-100 focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-gray-950 data-disabled:text-gray-500 hover:data-disabled:bg-gray-50"
  >
    Enroll
  </Button>
</template>

Anatomy

<script setup>
import { Button } from '@shardsui/vue/button'
</script>

<template>
  <Button />
</template>

Usage guidelines

  • Submit buttons: unlike the native button element, type="submit" must be specified on Button for it to act as a submit button.
  • Links: the Button component enforces button semantics (role="button", keyboard interaction, disabled state). It should not be used for links. See Rendering links as buttons.

Examples

Rendering as another tag

Non-button tags get role="button" and keyboard handlers automatically.

<script setup>
import { Button } from '@shardsui/vue/button'
</script>

<template>
  <Button as="div">Button that can contain complex children</Button>
</template>

Links (<a>) have their own semantics; don't render them as buttons through as. To make a link look like a button, style the <a> element directly with CSS.

Loading states

When a button becomes disabled after a click — while it loads — a native Button carries the native disabled attribute, so the browser drops it from the tab order and blurs it. With as set to any other tag it carries aria-disabled="true" and tabindex="-1" instead. Either way the click, keyboard and pointer handlers stop firing.

<script setup lang="ts">
import { Button } from '@shardsui/vue/button'
import { shallowRef } from 'vue'

const enrolling = shallowRef(false)

async function enroll() {
  enrolling.value = true
  await new Promise((resolve) => setTimeout(resolve, 3000))
  enrolling.value = false
}
</script>

<template>
  <Button
    class="font-inherit m-0 flex h-8 items-center justify-center gap-2 rounded-md border border-gray-200 bg-gray-50 px-3 text-sm/6 font-normal text-nowrap text-gray-900 outline-0 select-none hover:bg-gray-100 focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-gray-950 data-disabled:text-gray-500 hover:data-disabled:bg-gray-50"
    :disabled="enrolling"
    @click="enroll"
  >
    {{ enrolling ? 'Enrolling' : 'Enroll' }}
  </Button>
</template>

API reference

PropTypeDefault
AttributeDescription
data-disabledPresent when the button is disabled.