<script setup>
import Button from '~/components/ui/Button.vue'

const click = () => new Promise(resolve => setTimeout(resolve, 1000))
</script>

# Button

Buttons are UI elements that users can interact with to perform actions. Funkwhale uses buttons in many contexts.

| Prop         | Data type                                 | Required? | Default   | Description                                                        |
| ------------ | ----------------------------------------- | --------- | --------- | ------------------------------------------------------------------ |
| `variant`    | `solid` \| `outline` \| `ghost`           | No        | `solid`   | Whether to render the button as an solid, outline or ghost button. |
| `shadow`     | Boolean                                   | No        | `false`   | Whether to render the button with a shadow                         |
| `round`      | Boolean                                   | No        | `false`   | Whether to render the button as a round button                     |
| `icon`       | String                                    | No        |           | The icon attached to the button                                    |
| `is-active`  | Boolean                                   | No        | `false`   | Whether the button is in an active state                           |
| `is-loading` | Boolean                                   | No        | `false`   | Whether the button is in a loading state                           |
| `color`      | `primary` \| `secondary` \| `destructive` | No        | `primary` | Renders a colored button                                           |

## Button colors

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

### Primary

Primary buttons represent **positive** actions such as uploading, confirming, and accepting changes.

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

```vue-html
<Button>
  Primary button
</Button>
```

<Button>
  Primary button
</Button>

### Secondary

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

```vue-html
<Button color="secondary">
  Secondary button
</Button>
```

<Button color="secondary">
  Secondary button
</Button>

### Destructive

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

```vue-html
<Button color="destructive">
  Destructive button
</Button>
```

<Button color="destructive">
  Destructive button
</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.
:::

```vue-html
<Button>
  Filled button
</Button>
```

<Button>
  Filled button
</Button>

### Outline

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

```vue-html
<Button variant="outline" color="secondary">
  Outline button
</Button>
```

<Button variant="outline" color="secondary">
  Outline button
</Button>

### Ghost

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

```vue-html
<Button variant="ghost" color="secondary">
  Ghost button
</Button>
```

<Button variant="ghost" color="secondary">
  Ghost button
</Button>

## Button styles

### Shadow

You can give a button a shadow to add depth.

```vue-html
<Button shadow>
  Shadow button
</Button>
```

<Button shadow>
  Shadow button
</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.
:::

```vue-html
<Button>
  Normal button
</Button>
```

<Button>
  Normal button
</Button>

### Round

Round buttons have fully rounded edges.

```vue-html
<Button round>
  Round button
</Button>
```

<Button round>
  Round button
</Button>

## Button states

You can pass a state to indicate whether a user can interact with a button.

### Active

A button is active when clicked by a user. You can force an active state by passing an `is-active` prop.

```vue-html
<Button is-active>
  Active button
</Button>
```

<Button is-active>
  Active button
</Button>

### Disabled

Disabled buttons are non-interactive and inherit a less bold color than the one provided. You can apply a disabled state by passing a `disabled` prop.

```vue-html
<Button disabled>
  Disabled button
</Button>
```

<Button disabled>
  Disabled button
</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.

```vue-html
<Button is-loading>
  Loading button
</Button>
```

<Button is-loading>
  Loading button
</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.
:::

```vue
<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
</Button>

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

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

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

## Icons

You can use [Bootstrap Icons](https://icons.getbootstrap.com/) 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 `&nbsp;` into the slot.
:::

```vue-html
<Button color="secondary" icon="bi-three-dots-vertical" />

<Button color="secondary" is-round icon="bi-x" />

<Button icon="bi-save">&nbsp;</Button>

<Button color="destructive" icon="bi-trash">
  Delete
</Button>
```

<Button color="secondary" icon="bi-three-dots-vertical" />
<Button color="secondary" round icon="bi-x" />
<Button icon="bi-save">&nbsp;</Button>
<Button color="destructive" icon="bi-trash">
  Delete
</Button>
