Usage
Changes in this example: 0
<script lang="ts">
const count = signal(0)
</script>
<template>
<UIButton on:click="() => count.value++">Save changes</UIButton>
<UIButton variant="outline">Cancel</UIButton>
<UIButton size="sm" disabled>Unavailable</UIButton>
<p role="status">Changes: {count.value}</p>
</template>Route, link or button
UIButton
renders the element that matches what it does, with the same look: with
to, a link to a route of the application that navigates without reloading; with
href, an
<a>
to any URL; with neither, a
<button type="button">.
<!-- A route of the application: navigates without reloading, with typed params and search -->
<UIButton to="/links">See links</UIButton>
<UIButton to="/users/[id]" bind:params="{ id: user.id }"
bind:search="{ tab: 'activity' }">Profile</UIButton>
<!-- Any URL: an <a>; with target="_blank" it adds rel="noopener noreferrer" -->
<UIButton href="https://github.com/meekojs/meeko" target="_blank"
variant="outline">GitHub</UIButton>
<UIButton href="/report.pdf" download="report.pdf">Download</UIButton>
<!-- Without to or href: a <button type="button"> -->
<UIButton type="submit" bind:disabled="saving.value">Save</UIButton>
<!-- id, title, aria-* and data-* reach the element -->
<UIButton aria-describedby="hint" data-testid="reset" on:click="reset">Reset</UIButton>
Combinations that make no sense are type errors in
meeko check
and in the editor:
to
with
href,
type
or
disabled
on a link,
target
on a button, a route that does not exist or a dynamic route without
params. A link cannot be disabled: it has no native state, and
aria-disabled
without removing
href
would still navigate. If the action is not available, do not render the link, or use a button with
disabled.
Sizes and states
Danger, loading and icon
tone="danger"
marks a destructive action.
loading
keeps the text, adds the spinner, announces
aria-busy
and blocks the action without taking its focus. With
iconOnly, the button is square: always name it with
ariaLabel.
<UIButton tone="danger">Delete</UIButton>
<UIButton tone="danger" variant="outline">Revoke</UIButton>
<UIButton bind:loading="saving.value">Save</UIButton>
<UIButton iconOnly ariaLabel="Delete" variant="outline">
<UIIcon name="lucide:trash-2" />
</UIButton>| Name | Type / default | Description |
|---|---|---|
to
|
RouteId
| A route of the application. Renders a link that navigates without reloading. Excludes href, type and disabled. |
params / search
|
route params / object
| With to: the params of a dynamic route (required there) and the query string. |
href
|
string
| Any URL. Renders an <a>. Excludes to, type and disabled. |
target / rel / download
|
string
| With to or href. For _blank, noopener noreferrer is added when rel is not set. |
type
|
button | submit | reset
button
| Without to or href. Native behavior in forms. |
disabled
|
boolean
false
| Without to or href. Disables the native button. |
variant
|
primary | secondary | outline | ghost
primary
| Visual hierarchy of the action. |
size
|
sm | md | lg
md
| Size of the control. |
shape
|
rounded | pill
rounded
| Shape of the outline. |
tone
|
danger
| Marks a destructive action, with any variant. |
loading
|
boolean
false
| Adds the spinner, announces aria-busy and blocks the action without taking its focus. |
iconOnly / ariaLabel
|
boolean / string
false
| A square button with an icon; ariaLabel gives its accessible name. |
name / value / form
|
string
| Without to or href. The native attributes of a submit button. |
class
|
string
| Additional classes. |
id / title / aria-* / data-*
|
HTML attributes
| Reach the element as they are. |
Events and content
on:click
receives the mouse event in all three forms; on a link,
event.preventDefault()
cancels the navigation. The
default
snippet is required. For an asynchronous action, bind
loading
to your signal.
For a link with its own visual hierarchy and the defaults of
ui.defaults.link, use
UILink.