The kit's button, and — when asked — its link.
Import it from rei-kit:
import { BaseButton } from 'rei-kit'
Open BaseButton in the live documentation, where every prop below is a control you can change, in four materials and ten palettes.
<script setup lang="ts">
import { ref } from 'vue'
import { BaseButton } from 'rei-kit'
const deleting = ref(false)
function save() {
// …
}
</script>
<template>
<div class="flex flex-wrap gap-2">
<BaseButton @click="save">Save</BaseButton>
<BaseButton variant="secondary">Cancel</BaseButton>
<BaseButton variant="danger" :loading="deleting">Delete</BaseButton>
<BaseButton as="a" href="/docs" variant="ghost">Read the docs</BaseButton>
</div>
</template>
| Prop | Type | Required or default | What it is for |
|---|---|---|---|
as | 'button' | 'a' | 'router-link' | 'button' | What to render. `button` unless this navigates. |
variant | 'primary' | 'secondary' | 'ghost' | 'quiet' | 'destructive' | 'row' | 'danger' | 'positive' | 'warning' | 'accent' | 'link' | 'unstyled' | 'primary' | `link` is a real action that should read as text — "clear this note", "remove", "change category". It has no surface at all, so it also has no height and no padding: giving it either would make it a ghost button, which is a different thing and was already here. |
size | 'xs' | 'sm' | 'md' | 'lg' | 'md' | `xs` is the action inside a prompt or a nudge, not on a page. |
loading | boolean | false | |
disabled | boolean | false | |
type | 'button' | 'submit' | 'button' | Ignored unless `as` is `button`. |
icon | boolean | false | Square, sized to its icon, with no label beside it. **Pass `aria-label`.** An icon on its own has no accessible name, and a control a screen reader announces as "button" is not usable. Attributes fall through, so `aria-label` lands where it should — nothing here can check that you passed one, which is why it is said this loudly. |
block | boolean | false | Fills its container. The ordinary case under a form. |
to | string | Record<string, unknown> | undefined | For `as="router-link"`. |
href | string | undefined | For `as="a"`. |
pill | boolean | false | Fully rounded rather than card-cornered. Every install prompt, update prompt and nudge across the apps used the same pair — a filled pill to act and a quiet one to dismiss — and none of them could use this component, because it only knew one corner radius. |
pressed | boolean | undefined | That this button is a switch, and whether it is on. Omit it and the button is an action. Pass it and the button becomes a toggle: `aria-pressed` is written, and the variants that have an "off" look — ghost, quiet, secondary — take a filled one when on. There were 18 of these hand-written across the three apps, every one a picker cell or a filter chip, and almost none of them said `aria-pressed` at all. A screen reader met a row of identical buttons with no way to know which was chosen. |
rei-kit is an accessible Vue 3 and Tailwind CSS 4 component library: 106 components, themed by role rather than by colour on three independent axes — ten WCAG-checked palettes, four materials and light or dark, each switched with one attribute. Typed, tested, SSR-safe, no runtime dependencies, MIT.