funkwhale/front/ui-docs/components/ui/button.md

10 KiB

import Button from "~/components/ui/Button.vue"

Button

Buttons are UI elements that users can interact with to perform actions and manipulate objects. They are distinct from Links and will not change the user's position.

{
  thinFont?: true
  lowHeight?: true

  isActive?: boolean
  isLoading?: boolean

  shadow?: boolean
  round?: boolean
  icon?: string

  onClick?: (...args: any[]) => void | Promise<void>

  autofocus?: boolean
  ariaPressed?: true
} & (ColorProps | DefaultProps)
  & VariantProps
  & RaisedProps
  & WidthProps
  & AlignmentProps

Action

The default action of buttons is submit [mdn]. Specify an onClick or @click function to change the behavior of a button.

<form>
  <Button>Without `onClick`</Button>
  <Button :onClick="() => {}">With `onClick`</Button>
</form>
Without `onClick` With `onClick`

Short-form @click

For convenience, you can use the Vue-specific @click syntax to add the onClick prop. The following two buttons are effectively equal:

  <Button :onClick="() => { console.log('Hi!') }"> Long form </Button>
  <Button @click="console.log('Hi!')"> Short form </Button>

Long form <Button @click="console.log('Hi!')"> Short form

Button colors

Buttons come in different types depending on the type of action they represent.

Find a complete overview of recommended styles on the color page.

Default

Default buttons represent neutral actions such as cancelling a change or dismissing a notification.

<Button>
  Default button
</Button>
Default button

Primary

The primary button represents the single positive action on a page or modal, such as uploading, confirming, and accepting changes.

<Button primary>
  Primary button
</Button>
Primary button

Secondary

Secondary buttons represent neutral actions such as cancelling a change or dismissing a notification.

<Button secondary raised>
  Secondary button
</Button>
Secondary button

Note that on a secondary background, the button needs to be raised to make it stand out.

Destructive

Desctrutive buttons represent dangerous actions including deleting items or purging domain information.

<Button destructive>
  Destructive button
</Button>
Destructive button

Button variants

Buttons come in different styles that you can use depending on the location of the button.

Solid

Solid buttons have a filled background. Use these to emphasize the action the button performs.

::: info This is the default style. If you don't specify a style, a solid button is rendered. :::

<Button>
  Filled button
</Button>

<Button solid>
  Also filled button
</Button>
Filled button Also filled button

Outline

Outline buttons have a transparent background. Use these to deemphasize the action the button performs.

<Button outline secondary>
  Outline button
</Button>
Outline button

Ghost

Ghost buttons have a transparent background and border. Use these to deemphasize the action the button performs.

<Button ghost secondary>
  Ghost button
</Button>
Ghost button

Button styles

Shadow

You can give a button a shadow to add depth.

<Button shadow>
  Shadow button
</Button>
Shadow button

Button shapes

You can choose different shapes for buttons depending on their location and use.

Normal

Normal buttons are slightly rounded rectangles.

::: info This is the default shape. If you don't specify a type, a normal button is rendered. :::

<Button>
  Normal button
</Button>
Normal button

Round

Round buttons have fully rounded edges.

<Button round>
  Round button
</Button>
Round button

Split button

I am split I am not split I am not split and I am disabled I am split and disabled

Button states

On/Off

You can force an active state by passing an aria-pressed prop.

::: tip When do I use a Toggle vs. a Button?

Use a Button with an aria-pressed prop

  • if the semantics of the option change depending whether it's on or off
  • to perform asynchronous, stateful and fallible actions

Examples:

  • Toggle a remote property
  • Open/close a section in the UI
  • Toolbar buttons that toggle through many options such as "Paragraph/Heading/List"

Use the Toggle component (a.k.a. switch)

  • for options that don't cause side-effects and never change the Toggle label content based on the Toggle state (think of the traditional checkbox).
  • for options that don't have any intermediary state besides "on" and "off"

Examples:

  • A checkbox in the User settings
  • A checkbox in a form that the user submits later

:::

<Button>
  Off
</Button>

<Button aria-pressed>
  On
</Button>

Default:

Off On

Secondary:

Off On

Primary:

Off On

Disabled

Disabled buttons are non-interactive and inherit a less bold color than the one provided.

::: tip When do I use disabled?

Use the disabled property for buttons that the user expects at a certain position, for example in a toolbar or in a row of action buttons.

If there is just one button in a form and its action is disabled, you may instead just remove it.

:::

<Button disabled>
  Disabled button
</Button>
Disabled button

Loading

If a user can't interact with a button until something has finished loading, you can add a spinner by passing the is-loading prop.

<Button is-loading>
  Loading button
</Button>
Loading button

Promise handling in @click

When a function passed to @click returns a promise, the button automatically toggles a loading state on click. When the promise resolves or is rejected, the loading state turns off.

::: danger There is no promise rejection mechanism implemented in the <Button> component. Make sure the @click handler never rejects. :::

<script setup lang="ts">
const click = () => new Promise((resolve) => setTimeout(resolve, 1000));
</script>

<template>
  <Button @click="click"> Click me </Button>
</template>

<Button @click="click"> Click me

You can override the promise state by passing a false is-loading prop.

<Button :is-loading="false">
  Click me
</Button>
Click me

Add an icon

You can use Bootstrap Icons in your button component.

::: info

  • Icon buttons shrink down to the icon size if you don't pass any content. If you want to keep the button at full width with just an icon, add button-width as a prop.
  • When combining icons with other content, prefix the icon prop with right to place it after the content.
  • To make icons large, add large to the icon prop.

:::

<Button icon="bi-three-dots-vertical" />
<Button round icon="bi-x large" />
<Button primary icon="bi-save" button-width/>
<Button destructive icon="bi-trash">
  Delete
</Button>
<Button low-height icon="right bi-chevron-right">
  Next
</Button>
Delete Next

Set width and alignment

See Using width and Using alignment

    <Button min-content>🐌</Button>
    <Button tiny>🐌</Button>
    <Button buttonWidth>🐌</Button>
    <Button small>🐌</Button>
    <Button auto>🐌</Button>
    <hr />
    <Button alignSelf="start">🐌</Button>
    <Button alignSelf="center">🐌</Button>
    <Button alignSelf="end">🐌</Button>
    <hr />
    <Button alignText="left">🐌</Button>
    <Button alignText="center">🐌</Button>
    <Button alignText="right">🐌</Button>
🐌 🐌 🐌 🐌 🐌
🐌 🐌 🐌
🐌 🐌 🐌