Skip to content
Snippets Groups Projects
Commit e350b89e authored by Ciarán Ainsworth's avatar Ciarán Ainsworth
Browse files

Merge branch 'document-all-components' into 'main'

Add documentation for all components

Closes #3

See merge request funkwhale/vui!3
parents 3b29686f 76a5ac9a
Branches
Tags
1 merge request!3Add documentation for all components
Pipeline #23794 passed
Showing
with 923 additions and 139 deletions
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
......@@ -17,16 +17,45 @@ const user = {
</script>
# Activity
```html
Activities display history entries for a Funkwhale pod. Each item contains the following information:
- An image
- A track title
- An artist name
- A username
- A [popover](./../popover/index.md)
| Prop | Data type | Required? | Description |
|---------|--------------|-----------|----------------------------------------------|
| `track` | Track object | Yes | The track to render in the activity entry. |
| `user` | User object | Yes | The user associated with the activity entry. |
## Single items
You can render a single activity item by passing the track and user information to the `<fw-activity>` component.
```vue-html
<fw-activity :track="track" :user="user" />
```
<fw-activity :track="track" :user="user" />
## Activity lists
You can display a list of activity items by passing a `v-for` directive and adding a `key` to the item. The `key` must be unique to the list.
::: info
Whenever there is more than 1 activity entry in a row, there would be a 1px border to separate the entries
Items in a list are visually separated by a 1px border.
:::
```html
<fw-activity :track="track" :user="user" v-for="i in 3" :key="i" />
```vue-html{4-5}
<fw-activity
:track="track"
:user="user"
v-for="i in 3"
:key="i"
/>
```
<fw-activity :track="track" :user="user" v-for="i in 3" :key="i" />
......@@ -3,117 +3,208 @@ const click = () => new Promise(resolve => setTimeout(resolve, 1000))
</script>
# Button
## Button colors
### Primary button
```html
Buttons are UI elements that users can interact with to perform actions. Funkwhale uses buttons in many contexts.
| Prop | Data type | Required? | Description |
| ----- | ---------- | ---------- | ----------- |
| `outline` | Boolean | No | Whether to render the button as an outline button. |
| `shadow` | Boolean | No | Whether to render the button with a shadow |
| `round` | Boolean | No | Whether to render the button as a round button |
| `icon` | String | No | The icon attached to the button |
| `is-active` | Boolean | No | Whether the button is in an active state |
| `is-loading` | Boolean | No | Whether the button is in a loading state |
| `primary` | Boolean | No | Renders a primary button |
| `secondary` | Boolean | No | Renders a secondary button |
| `destructive` | Boolean | No | Renders a destructive button |
## Button types
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
<fw-button>
Primary button
</fw-button>
```
<fw-button>
Primary button
</fw-button>
### Secondary button
```html
### Secondary
Secondary buttons represent **neutral** actions such as cancelling a change or dismissing a notification.
```vue-html
<fw-button secondary>
Secondary button
</fw-button>
```
<fw-button secondary>
Secondary button
</fw-button>
### Destructive button
```html
### Destructive
Desctrutive buttons represent **dangerous** actions including deleting items or purging domain information.
```vue-html
<fw-button destructive>
Destructive button
</fw-button>
```
<fw-button destructive>
Destructive button
</fw-button>
## Button types
## Button styles
Buttons come in different styles that you can use depending on the location of the button.
### Filled
```html
Filled buttons have a solid background. Use these to emphasize the action the button performs.
::: info
This is the default style. If you don't specify a style, a filled button is rendered.
:::
```vue-html
<fw-button>
Filled button
</fw-button>
```
<fw-button>
Filled button
</fw-button>
### Outline
```html
Outline buttons have a transparent background. Use these to deemphasize the action the button performs.
```vue-html
<fw-button outline>
Outline button
</fw-button>
```
<fw-button outline>
Outline button
</fw-button>
### Shadow
You can give a button a shadow to add depth.
```vue-html
<fw-button shadow>
Shadow button
</fw-button>
```
<fw-button shadow>
Shadow button
</fw-button>
## Button shapes
You can choose different shapes for buttons depending on their location and use.
### Normal
```html
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
<fw-button>
Normal button
</fw-button>
```
<fw-button>
Normal button
</fw-button>
### Round
```html
Round buttons have fully rounded edges.
```vue-html
<fw-button round>
Round button
</fw-button>
```
<fw-button round>
Round button
</fw-button>
## Button states
### Disabled
```html
<fw-button disabled>
Disabled button
</fw-button>
```
<fw-button disabled>
Disabled button
</fw-button>
You can pass a state to indicate whether a user can interact with a button.
### Active
```html
A button is active when clicked by a user. You can force an active state by passing an `is-active` prop.
```vue-html
<fw-button is-active>
Active button
</fw-button>
```
<fw-button is-active>
Active button
</fw-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
<fw-button disabled>
Disabled button
</fw-button>
```
<fw-button disabled>
Disabled button
</fw-button>
### Loading
```html
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
<fw-button is-loading>
Loading button
</fw-button>
```
<fw-button is-loading>
Loading button
</fw-button>
&nbsp;
### Promise handling in `@click`
#### Promise handling in @click
When a function passed to `@click` returns a promise, the button will automatically toggle it's loading state on click, and when promise resolves/rejects, it will toggle it off.
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
The `<fw-button>` component does not have any promise rejection mechanism implemented. Make sure, that the `@click` handler never rejects.
There is no promise rejection mechanism implemented in the `<fw-button>` component. Make sure the `@click` handler never rejects.
:::
```vue
......@@ -127,18 +218,32 @@ const click = () => new Promise(resolve => setTimeout(resolve, 1000))
</fw-button>
</template>
```
<fw-button @click="click">
Click me
</fw-button>
You can override the promise state by passing a false `is-loading` prop.
```vue-html
<fw-button :is-loading="false">
Click me
</fw-button>
```
<fw-button :is-loading="false">
Click me
</fw-button>
## Icons
You can use [Bootstrap Icons](https://icons.getbootstrap.com/) in your button component
::: info
When the button doesn't have any contents or it's contents are empty, it will shrink down to the icon size.
To avoid this, you can add `&nbsp;`.
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.
:::
```html
```vue-html
<fw-button secondary icon="bi-three-dots-vertical" />
<fw-button secondary is-round icon="bi-x" />
......@@ -149,6 +254,7 @@ To avoid this, you can add `&nbsp;`.
Delete
</fw-button>
```
<fw-button secondary icon="bi-three-dots-vertical" />
<fw-button secondary round icon="bi-x" />
<fw-button icon="bi-save">&nbsp;</fw-button>
......
# Play Button
```html
The play button is a specialized button used in many places across the Funkwhale app. Map a function to the `@play` event handler to toggle it on click.
```vue-html
<fw-play-button @play="play" />
```
<fw-play-button />
......@@ -14,8 +14,22 @@ const album = {
</script>
# Album card
## Normal card
```html
Album cards are specialized cards that represent an album in Funkwhale's interface. Pass an album object to the `album` prop to generate a card with the following:
- The album's cover image
- The album's title
- The artist's name
- The number of tracks in the album
| Prop | Data type | Required? | Description |
| ---- | ---------- | ---------- | ------------ |
| `album` | Album object | Yes | The album represented by the card. |
The card includes a [play button](../button/play.md) that plays the whole album and a [popover](../popover/index.md) containing other actions the user can perform.
```vue-html
<fw-album-card :album="album" />
```
<fw-album-card :album="album" />
......@@ -12,8 +12,22 @@ const artist = {
</script>
# Artist card
## Normal card
```html
Artist cards are specialized cards that represent an artist in Funkwhale's interface. Pass an artist object to the `artist` prop to generate a card with the following:
- The artist's image
- The artist's name
- The artist's genre tags in [pills](../pill/index.md)
- The number of albums associated with the artist
| Prop | Data type | Required? | Description |
| ---- | ---------- | ---------- | ------------ |
| `artist` | Artist object | Yes | The artist represented by the card. |
The card includes a [play button](../button/play.md) that plays all of the artist's content and a [popover](../popover/index.md) containing other actions the user can perform.
```vue-html
<fw-artist-card :artist="artist" />
```
<fw-artist-card :artist="artist" />
......@@ -3,78 +3,131 @@ const alert = (message: string) => window.alert(message)
</script>
# Card
Funkwhale cards are used to contain textual information, links, and interactive buttons. You can use these to create visually pleasing links to content or to present information.
| Prop | Data type | Required? | Description |
|---------|--------------|-----------|----------------------------------------------|
| `title` | String | No | The title of the card. |
| `image` | String | No | The URL of an image to display on the card. |
| `button-title` | String | No | The text that appears on the button. |
| `category` | Boolean | No | Whether the card is a category card or not. |
| `tags` | Array\<String\> | No | An array of tags. These are rendered as [pills](../pill/index.md). |
## Basic card
```html
Basic cards only contain textual information. You can set a title for the card by passing a `title` prop.
```vue-html
<fw-card title="For music lovers">
Access your personnal music collection from anywhere. Beeing focused on the promotion of Free licensed content, Funkwhale sports advanced sharing features.
Access your personal music collection from anywhere. Funkwhale gives you access to publication and sharing tools that you can use to promote your content across the web.
</fw-card>
```
<fw-card title="For music lovers">
Access your personnal music collection from anywhere. Beeing focused on the promotion of Free licensed content, Funkwhale sports advanced sharing features.
Access your personal music collection from anywhere. Funkwhale gives you access to publication and sharing tools that you can use to promote your content across the web.
</fw-card>
## Interactive card
```html
You can make a card interactive by passing an event to the `@click` handler. When a user clicks on the card, the event fires. Use this to add links or events to your cards.
```vue-html{3}
<fw-card
title="Frequently Asked Questions"
@click="alert('hello')"
@click="alert('A quick answer!')"
>
You have a question about Funkwhale? Get a quick answer!
Got a question about Funkwhale? Get a quick answer!
</fw-card>
```
<fw-card
title="Frequently Asked Questions"
@click="alert('hello')"
<fw-card
title="Frequently Asked Questions"
@click="alert('A quick answer!')"
>
You have a question about Funkwhale? Get a quick answer!
Got a question about Funkwhale? Get a quick answer!
</fw-card>
## Category card
```html
Category cards are basic cards that contain only a title. To create a category card, pass a `category` prop.
```vue-html{2}
<fw-card
category
title="Example Translations"
@click="alert('hello')"
/>
```
<fw-card
category
title="Example Translations"
category
title="Example Translations"
@click="alert('hello')"
/>
## Card with an image
```html
## Image card
Cards can contain images for extra visual appeal. Pass an image URL to the `image` prop to create an image card.
```vue-html{3}
<fw-card
title="For music lovers"
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb"
>
Access your personnal music collection from anywhere. Beeing focused on the promotion of Free licensed content, Funkwhale sports advanced sharing features.
Access your personal music collection from anywhere. Funkwhale gives you access to publication and sharing tools that you can use to promote your content across the web.
</fw-card>
```
<fw-card
<fw-card
title="For music lovers"
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb"
>
Access your personnal music collection from anywhere. Beeing focused on the promotion of Free licensed content, Funkwhale sports advanced sharing features.
Access your personal music collection from anywhere. Funkwhale gives you access to publication and sharing tools that you can use to promote your content across the web.
</fw-card>
## Button card
You can add a button to the bottom of a card to present a clear action to users. Pass the title of the button to the `button-title` prop and pass an event to the `@click` handler.
::: info
When you add a `button-title` and a `@click` handler, you event only fires when the user clicks on the button.
:::
## Card with a button
```html
```vue-html{3}
<fw-card
title="Join an existing pod"
button-title="Find a pod"
@click="alert('hello')"
@click="alert('Open the pod picker')"
>
The easiest way to start using Funkwhale is to register an account on one of the many available pods.
The easiest way to get started with Funkwhale is to register an account on a public pod.
</fw-card>
```
<fw-card
<fw-card
title="Join an existing pod"
button-title="Find a pod"
@click="alert('hello')"
@click="alert('Open the pod picker')"
>
The easiest way to get started with Funkwhale is to register an account on a public pod.
</fw-card>
## Card tags
You can include tags on a card by adding a list of `tags`. These are rendered as [pills](../pill/index.md).
```vue-html{3}
<fw-card
title="For music lovers"
:tags="['rock', 'folk', 'punk']"
>
Access your personal music collection from anywhere. Funkwhale gives you access to publication and sharing tools that you can use to promote your content across the web.
</fw-card>
```
<fw-card
title="For music lovers"
:tags="['rock', 'folk', 'punk']"
>
The easiest way to start using Funkwhale is to register an account on one of the many available pods.
Access your personal music collection from anywhere. Funkwhale gives you access to publication and sharing tools that you can use to promote your content across the web.
</fw-card>
......@@ -15,10 +15,24 @@ const playlist = {
</script>
# Playlist card
## Normal card
```html
Playlist cards are specialized cards that represent playlists in Funkwhale's interface. Pass a playlist object to the `playlist` prop to generate a card with the following:
- A collage of up to 4 album covers from the playlist
- The playlist title
- The user who owns the playlist
- The number of tracks in the playlist
| Prop | Data type | Required? | Description |
| ---- | ---------- | ---------- | ------------ |
| `playlist` | Playlist object | Yes | The playlist represented by the card. |
The card includes a [play button](../button/play.md) that plays the playlist and a [popover](../popover/index.md) containing other actions the user can perform.
```vue-html
<fw-playlist-card :playlist="playlist" />
```
<div style="display: grid; grid-template-columns: auto auto 1fr; grid-gap: 2rem;">
<fw-playlist-card :playlist="playlist" />
<fw-playlist-card :playlist="{ ...playlist, album_covers: [] }" />
......
......@@ -15,8 +15,22 @@ const podcast = {
</script>
# Podcast card
## Normal card
```html
Podcast cards are specialized cards that represent a podcast in Funkwhale's interface. Pass a podcast object to the `podcast` prop to generate a card with the following:
- The podcast's image
- The podcast's title
- The owner of the podcast
- The date at which the podcast was last updated
| Prop | Data type | Required? | Description |
| ---- | ---------- | ---------- | ------------ |
| `podcast` | Podcast object | Yes | The podcast represented by the card. |
The card includes a [popover](../popover/index.md) containing other actions the user can perform.
```vue-html
<fw-podcast-card :podcast="podcast" />
```
<fw-podcast-card :podcast="podcast" />
......@@ -6,47 +6,91 @@ const radio = {
</script>
# Radio card
Radio cards are specialized cards that represent radios in Funkwhale's interface. Radio cards populate with the following information:
- The radio title
- The radio description
The card includes a [play button](../button/play.md) that starts the radio.
| Prop | Data type | Required? | Description |
| ---- | ---------- | ---------- | ------------ |
| `radio` | Radio object | Yes | The radio the card represents |
| `small` | Boolean | No | Controls whether the card is small or normal sized |
| `blue` | Boolean | No | Creates a blue card |
| `red` | Boolean | No | Creates a red card |
| `purple` | Boolean | No | Creates a purple card |
| `green` | Boolean | No | Creates a green card |
| `yellow` | Boolean | No | Creates a yellow card |
## Card colors
You can choose what color a radio card is by passing a supported color as a prop.
### Blue
This is the default color
```html
::: info
This is the default color. If you don't pass a color, a blue card is rendered.
:::
```vue-html
<fw-radio-card blue :radio="radio" />
```
<fw-radio-card blue :radio="radio" />
### Red
```html
```vue-html
<fw-radio-card red :radio="radio" />
```
<fw-radio-card red :radio="radio" />
### Purple
```html
```vue-html
<fw-radio-card purple :radio="radio" />
```
<fw-radio-card purple :radio="radio" />
### Green
```html
```vue-html
<fw-radio-card green :radio="radio" />
```
<fw-radio-card green :radio="radio" />
### Yellow
```html
```vue-html
<fw-radio-card yellow :radio="radio" />
```
<fw-radio-card yellow :radio="radio" />
## Card sizes
You can control the size of a radio card by adding a `small` prop.
### Normal card
```html
Normal radio cards contain the radio title and description.
```vue-html
<fw-radio-card :radio="radio" />
```
<fw-radio-card :radio="radio" />
### Small card
```html
Small radio cards contain only the radio title.
```vue-html
<fw-radio-card small :radio="radio" />
```
<fw-radio-card small :radio="radio" />
# Input
Inputs are areas in which users can enter information. In Funkwhale, these mostly take the form of search fields.
| Prop | Data type | Required? | Description |
| ----- | --------- | ---------- | ------------ |
| `placeholder` | String | No | The placeholder text that appears when the input is empty. |
| `icon` | String | No | The [Bootstrap icon](https://icons.getbootstrap.com/) to show on the input. |
| `v-model:value` | String | Yes | The text entered in the input. |
## Input model
```html
<fw-input v-model="value" placeholder="Search" />
You can link a user's input to form data by referencing the data in a `v-model` directive.
```vue-html{2}
<fw-input
v-model="value"
placeholder="Search"
/>
```
<fw-input placeholder="Search" />
## Input icons
You can use bootstrap icons
```html
<fw-input v-model="value" icon="bi-search" placeholder="Search" />
Add a [Bootstrap icon](https://icons.getbootstrap.com/) to an input to make its purpose more visually clear.
```vue-html{3}
<fw-input
v-model="value"
icon="bi-search"
placeholder="Search"
/>
```
<fw-input icon="bi-search" placeholder="Search" />
<fw-input icon="bi-search" placeholder="Search" />
## Input-right slot
```html
You can add a template on the right-hand side of the input to guide the user's input.
```vue-html{2-4}
<fw-input v-model="value" placeholder="Search">
<template #input-right>
suffix
</template>
</fw-input>
```
<fw-input placeholder="Search">
<template #input-right>
suffix
</template>
</fw-input>
......@@ -6,11 +6,21 @@
</style>
# Loader
```html
Loaders visually indicate when an operation is loading. This makes it visually clear that the user can't interact with the element until the loading process is complete.
| Prop | Data type | Required? | Description |
| ----- | --------- | ----------- | ----------- |
| `container` | Boolean | No | Whether to create a container for the loader |
## Normal loader
```vue-html
<div style="width: 50%">
<fw-loader />
</div>
```
<div class="docs-loader-container">
<div style="width: 50%">
<fw-loader />
......@@ -18,14 +28,17 @@
</div>
## No container
By default the `<fw-loader />` component creates a container that is 100% height of component's parent. Sometimes we do not want such behavior. In those cases we can disable this using `:container="false"` property. The loader will then be centered in the middle of the first parent that has `position: relative` set.
```html
By default the `<fw-loader />` component creates a container that takes up 100% of its parent's height. You can disable this by passing a `:container="false"` property. The loader renders centered in the middle of the first parent that has `position: relative` set.
```vue-html
<div style="position: relative">
<div style="width: 50%">
<fw-loader :container="false" />
</div>
</div>
```
<div class="docs-loader-container">
<div style="position: relative">
<div style="width: 50%">
......
......@@ -5,8 +5,20 @@ const page = ref(1)
</script>
# Pagination
The pagination component helps users navigate through large lists of results by splitting them up into pages.
| Prop | Data type | Required? | Description |
| ----- | --------- | ---------- | ------------ |
| `pages` | Number | Yes | The total number of pages to paginate. |
| `v-model:page` | Number | Yes | The page number of the current page. |
## Pagination model
```html
Create a pagination bar by passing the number of pages to the `pages` prop. Use `v-model` to sync the selected page to your page data. Users can click on each button or input a specific page and hit `return`.
```vue-html
<fw-pagination :pages="8" v-model:page="page" />
```
<fw-pagination :pages="8" v-model:page="page" />
# Pill
## Pill colors
### Primary pill
```html
Pills are decorative elements that display information about content they attach to. They can be links to other content or simple colored labels.
You can add text to pills by adding it between the `<fw-pill>` tags.
| Prop | Data type | Required? | Description |
|---------|-----------|-----------|----------------------------------------|
| `primary` | Boolean | No | Creates a primary pill |
| `secondary` | Boolean | No | Creates a secondary pill |
| `destructive` | Boolean | No | Creates a destructive pill |
| `blue` | Boolean | No | Creates a blue pill |
| `red` | Boolean | No | Creates a red pill |
| `purple` | Boolean | No | Creates a purple pill |
| `green` | Boolean | No | Creates a green pill |
| `yellow` | Boolean | No | Creates a yellow pill |
## Pill types
You can assign a type to your pill to indicate what kind of information it conveys.
::: details Types
- Primary
- Secondary
- Desctructive
:::
### Primary
Primary pills convey **positive** information.
```vue-html
<fw-pill primary>
Primary pill
</fw-pill>
```
<fw-pill primary>
Primary pill
</fw-pill>
### Secondary pill
This is the default pill color
```html
### Secondary
Secondary pills convey **neutral** or simple decorational information such as genre tags.
::: info
This is the default type for pills. If you don't specify a type, a **secondary** pill is rendered.
:::
```vue-html
<fw-pill>
Secondary pill
</fw-pill>
```
<fw-pill>
Secondary pill
</fw-pill>
### Destructive pill
```html
### Destructive
Destructive pills convey **destructive** or **negative** information. Use these to indicate that information could cause issues such as data loss.
```vue-html
<fw-pill destructive>
Destructive pill
</fw-pill>
```
<fw-pill destructive>
Destructive pill
</fw-pill>
## Pill colors
Funkwhale pills support a range of pastel colors to create visually appealing interfaces.
::: details Colors
- Red
- Blue
- Purple
- Green
- Yellow
:::
### Blue
```html
```vue-html
<fw-pill blue>
Blue pill
</fw-pill>
```
<fw-pill blue>
Blue pill
</fw-pill>
### Red
```html
```vue-html
<fw-pill red>
Red pill
</fw-pill>
```
<fw-pill red>
Red pill
</fw-pill>
### Purple
```html
```vue-html
<fw-pill purple>
Purple pill
</fw-pill>
```
<fw-pill purple>
Purple pill
</fw-pill>
### Green
```html
```vue-html
<fw-pill green>
Green pill
</fw-pill>
```
<fw-pill green>
Green pill
</fw-pill>
### Yellow
```html
```vue-html
<fw-pill yellow>
Yellow pill
</fw-pill>
```
<fw-pill yellow>
Yellow pill
</fw-pill>
## Image pills
Image pills contain a small circular image on their left. These can be used for decorative links such as artist links. To created an image pill, insert a link to the image between the pill tags as a `<template>`.
## Images
```html
```vue-html{2-4}
<fw-pill>
<template #image>
<img src="/images/awesome-artist.png" />
......
......@@ -119,12 +119,282 @@ const items = [
},
]
const oneButtonMenu = [
{
type: 'button',
text: 'Report',
icon: 'bi-exclamation',
click: () => {}
}
]
const oneSelectMenu = [
{
type: 'select',
text: 'Bandcamp',
model: bandcamp
}
]
const oneSeparatorMenu = [
{ type: 'separator', }
]
const nestedMenu = [
{
type: 'button',
text: 'Organize and share',
icon: 'bi-collection',
click: () => {},
items: [
{
type: 'select',
text: 'Bandcamp',
model: bandcamp,
}
]
}
]
const extraItemsMenu = [
{
type: 'select',
text: 'Bandcamp',
model: bandcamp,
extraItems: [
{
type: 'library-privacy-level',
model: bandcampPrivacy
}
]
},
{
type: 'select',
text: 'Creative Commons',
model: cc,
extraItems: [
{
type: 'circle-button',
icon: 'bi-exclamation',
click: () => {}
}
]
}
]
const open = ref(false)
const separator = ref(false)
const singleButton = ref(false)
const singleSelect = ref(false)
const extraItemsOpen = ref(false)
</script>
# Popover
```html
<fw-popover :items="items" />
Popovers are visually hiden menus of items activated by a simple button. Use popovers to create complex menus in a visually appealing way.
| Prop | Data type | Required? | Description |
| ----- | --------- | ----------- | ----------- |
| `items` | Array\<Item\> | Yes | A list of menu items. |
| `v-model:open` | Boolean | Yes | Controls whether the popover is open or not. |
| `clickOutside` | Boolean | No | Controls whether clicking outside the popover closes it. |
## Items
Popovers contain a list of menu items. Items can contain different information based on their type.
### Button
A button is a clickable item users can interact with. It can take the form of a link or an action.
| Property | Data type | Required? | Description |
| --------- | --------- | ---------- | ----------- |
|`type` | String | Yes | The item type (`button`). |
| `text` | String | Yes | The text that appears in the menu. |
| `icon` | String | Yes | The icon that appears in the menu. |
| `click` | Event | Yes | The action that triggers when a user clicks the button. |
```vue{2-9}
<script-setup lang="ts">
const items = [
{
type: 'button',
text: 'Report',
icon: 'bi-exclamation',
click: () => {}
}
]
const open = ref(false)
</script>
<template>
<fw-options-button @click="open = !open" />
<fw-popover :items="items" v-model:open="open" />
</template
```
<fw-options-button @click="singleButton = !singleButton" />
<fw-popover :items="oneButtonMenu" v-model:open="singleButton" />
### Select
A select is a checkbox item that users can select or deselect to modify data.
| Property | Data type | Required? | Description |
| --------- | --------- | ---------- | ----------- |
|`type` | String | Yes | The item type (`select`). |
| `text` | String | Yes | The text that appears in the menu. |
| `model` | Property | Yes | The property the select button maps to. |
```vue{2-8}
<script-setup lang="ts">
const items = [
{
type: 'select',
text: 'Bandcamp',
model: bandcamp
}
]
const open = ref(false)
</script>
<template>
<fw-options-button @click="open = !open" />
<fw-popover :items="items" v-model:open="open" />
</template>
```
<fw-options-button @click="singleSelect = !singleSelect" />
<fw-popover :items="oneSelectMenu" v-model:open="singleSelect" />
### Separator
| Property | Data type | Required? | Description |
| --------- | --------- | ---------- | ----------- |
|`type` | String | Yes | The item type (`separator`). |
Separators are visual separators that break the menu up into different sections.
```vue{2-6}
<script-setup lang="ts">
const items=[
{
type: 'separator'
}
]
</script>
<template>
<fw-options-button @click="open = !open" />
<fw-popover :items="items" v-model:open="open" />
</template>
```
<fw-options-button @click="separator = !separator" />
<fw-popover :items="oneSeparatorMenu" v-model:open="separator" />
## Nested items
To create a more complex menu, you can nest items within other menu items. Add a new `items` array inside an item to nest the array as an expanded list.
```vue{8-14}
<script-setup lang="ts">
const items = [
{
type: 'button',
text: 'Organize and share',
icon: 'bi-collection',
click: () => {},
items: [
{
type: 'select',
text: 'Bandcamp',
model: bandcamp,
}
]
}
]
const open = ref(false)
</script>
<template>
<fw-options-button @click="open = !open" />
<fw-popover :items="items" v-model:open="open" />
</template
```
<fw-options-button @click="singleButton = !singleButton" />
<fw-popover :items="nestedMenu" v-model:open="singleButton" />
## Extra items
::: info
Extra items can only be added to `button` and `select` items.
:::
You can extend items without creating submenus by attaching a small extra menu on the right hand side of the item.
| Property | Data type | Required? | Description |
| --------- | --------- | ---------- | ----------- |
|`type` | String | Yes | The item type. |
::: details Supported types
- `circle-button` – a small clickable circle button
- `library-privacy-level` – a selectable list of Funkwhale privacy levels
:::
```vue{7-12,18-24}
<script-setup lang="ts">
const items = [
{
type: 'select',
text: 'Bandcamp',
model: bandcamp,
extraItems: [
{
type: 'library-privacy-level',
model: bandcampPrivacy
}
]
},
{
type: 'select',
text: 'Creative Commons',
model: cc,
extraItems: [
{
type: 'circle-button',
icon: 'bi-exclamation',
click: () => {}
}
]
}
]
const open = ref(false)
</script>
<template>
<fw-options-button @click="open = !open" />
<fw-popover :items="items" v-model:open="open" />
</template>
```
<fw-options-button @click="extraItemsOpen = !extraItemsOpen" />
<fw-popover :items="extraItemsMenu" v-model:open="extraItemsOpen" />
## Menu
Here is an example of a completed menu containing all supported features.
```vue-html
<fw-options-button @click="open = !open" />
<fw-popover :items="items" v-model:open="open" />
```
<fw-options-button @click="open = !open" />
......
# Tabs
Tabs are used to hide information until a user chooses to see it. You can use tabs to show two sets of information on the same page without the user needing to navigate away.
| Prop | Data type | Required? | Description |
| ----- | ---------- | ---------- |------------ |
| `title` | String | Yes | The title of the tab |
## Tabbed elements
::: warning
The `<fw-tab>` components won't render outside of the `<fw-tabs>` component.
The `<fw-tab>` component must be nested inside a `<fw-tabs>` component.
:::
```html
```vue-html
<fw-tabs>
<fw-tab title="Overview">Overview content</fw-tab>
<fw-tab title="Activity">Activity content</fw-tab>
</fw-tabs>
```
<fw-tabs>
<fw-tab title="Overview">Overview content</fw-tab>
<fw-tab title="Activity">Activity content</fw-tab>
</fw-tabs>
## Tabs-right slot
```html
::: info
If you add the same tab multiple times, the tab is rendered once with the combined content from the duplicates.
:::
```vue-html{2,4}
<fw-tabs>
<fw-tab title="Overview">Overview content</fw-tab>
<fw-tab title="Activity">Activity content</fw-tab>
<template #tabs-right>
<fw-input icon="bi-search" placeholder="Search" />
</template>
<fw-tab title="Overview">More overview content</fw-tab>
</fw-tabs>
```
<fw-tabs>
<fw-tab title="Overview">Overview content</fw-tab>
<fw-tab title="Activity">Activity content</fw-tab>
<template #tabs-right>
<fw-input icon="bi-search" placeholder="Search" />
</template>
<fw-tab title="Overview">More overview content</fw-tab>
</fw-tabs>
## Duplicated tabs render as a single tab
```html
## Tabs-right slot
You can add a template to the right side of the tabs using the `#tabs-right` directive.
```vue-html{5-7}
<fw-tabs>
<fw-tab title="Overview">Overview content</fw-tab>
<fw-tab title="Activity">Activity content</fw-tab>
<fw-tab title="Overview">More overview content</fw-tab>
<template #tabs-right>
<fw-input icon="bi-search" placeholder="Search" />
</template>
</fw-tabs>
```
<fw-tabs>
<fw-tab title="Overview">Overview content</fw-tab>
<fw-tab title="Activity">Activity content</fw-tab>
<fw-tab title="Overview">More overview content</fw-tab>
<template #tabs-right>
<fw-input icon="bi-search" placeholder="Search" />
</template>
</fw-tabs>
......@@ -7,27 +7,59 @@ const text3 = ref('')
</script>
# Textarea
Textareas are input blocks that enable users to write in textual information. These blocks are used throughout the Funkwhale interface for entering item descriptions, moderation notes, and custom notifications.
::: tip
Funkwhale supports Markdown syntax in textarea blocks.
:::
| Prop | Data type | Required? | Description |
| ---- | ---------- | ----------- | ----------- |
| `max` | Number | No | The maximum number of characters a user can enter in the textarea. |
| `placeholder` | String | No | The placeholder text shown on an empty textarea. |
| `v-model:value` | String | Yes | The text entered into the textarea. |
## Textarea model
```html
<fw-textarea v-model="text" />
Create a textarea and attach its input to a value using a `v-model` directive.
```vue-html{2}
<fw-textarea
v-model="text"
/>
```
<ClientOnly>
<fw-textarea v-model="text1" />
</ClientOnly>
## Textarea max length
```html
<fw-textarea v-model="text" :max="20" />
You can set the maximum length (in characters) that a user can enter in a textarea by passing a `max` prop.
```vue-html{3}
<fw-textarea
v-model="text"
:max="20"
/>
```
<ClientOnly>
<fw-textarea v-model="text2" :max="20" />
</ClientOnly>
## Textarea placeholder
```html
<fw-textarea v-model="text" placeholder="Describe this track here…" />
Add a placeholder to a textarea to guide users on what they should enter by passing a `placeholder` prop.
```vue-html{3}
<fw-textarea
v-model="text"
placeholder="Describe this track here…"
/>
```
<ClientOnly>
<fw-textarea v-model="text3" placeholder="Describe this track here…" />
</ClientOnly>
# Table of Contents
The table of contents component renders a navigation bar on the right of the screen. Users can click on the items in the contents bar to skip to specific headers.
| Prop | Data type | Required? | Description |
| ----- | ---------- | --------- | ------------ |
| `heading` | Enum\<String\> | No | The heading level rendered in the table of contents |
::: details Supported headings
- `h1`
- `h2`
- `h3`
- `h4`
- `h5`
- `h6`
:::
## Default
By default table of contents is based on the `<h1>` tags
```html
By default table of contents only renders `<h1>` tags
```vue-html
<fw-toc>
<h1>This is a Table of Contents</h1>
Content...
......@@ -10,6 +30,7 @@ By default table of contents is based on the `<h1>` tags
More content...
</fw-toc>
```
<ClientOnly>
<fw-toc>
<h1>This is a Table of Contents</h1>
......@@ -36,8 +57,13 @@ By default table of contents is based on the `<h1>` tags
</ClientOnly>
## Custom headings
```html
<fw-toc heading="h2">
You can specify the heading level you want to render in the table of contents by passing it to the `heading` prop.
```vue-html{2}
<fw-toc
heading="h2"
>
<h1>This is a Table of Contents</h1>
Content...
......@@ -45,6 +71,7 @@ By default table of contents is based on the `<h1>` tags
More content...
</fw-toc>
```
<ClientOnly>
<fw-toc heading="h2">
<h1>This is a Table of Contents</h1>
......
......@@ -2,17 +2,37 @@
import { ref } from 'vue'
const toggle = ref(false)
const toggle2 = ref(false)
</script>
# Toggle
```html
Toggles are basic form inputs that visually represent a boolean value. Toggles can be **on** (`true`) or **off** (`false`).
| Prop | Data type | Required? | Description |
| ----- | ---------- | ---------- | ----------- |
| `big` | Boolean | No | Controls whether a toggle is big or not. |
| `v-model:value` | Boolean | Yes | The value controlled by the toggle. |
## Normal toggle
Link your toggle to an input using the `v-model` directive.
```vue-html
<fw-toggle v-model="toggle" />
```
<fw-toggle v-model="toggle" />
## Big toggle
```html
<fw-toggle big v-model="toggle" />
Pass a `big` prop to create a larger toggle.
```vue-html{2}
<fw-toggle
big
v-model="toggle"
/>
```
<fw-toggle big v-model="toggle" />
<fw-toggle big v-model="toggle2" />
# Hello VitePress
# Funkwhale design library
Welcome to the Funkwhale design library. This repository contains a collection of reusable components written in [Vue.js](https://vuejs.org) and [Sass](https://sass-lang.com).
<a href="https://design.funkwhale.audio" style="text-decoration: none">
<fw-card title="Looking for the designs?">
Check out the design system on our Penpot.
</fw-card>
</a>
[[toc]]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment