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

154 lines
3.6 KiB
Markdown

<script setup>
import { computed, ref } from 'vue'
import Pills from '~/components/ui/Pills.vue';
import Spacer from '~/components/ui/Spacer.vue';
import Layout from '~/components/ui/Layout.vue';
import Input from '~/components/ui/Input.vue';
const nullModel = ref({
current: [],
});
const staticModel = ref({
current: ["#Noise", "#FieldRecording", "#Experiment"],
});
const interactiveModel = ref({
current: ["#Noise", "#FieldRecording", "#Experiment"],
others: ["#Melody", "#Rhythm"],
});
const customModel = ref({
current: ["custom", "#FieldRecording", "#Experiment"],
others: ["#Melody", "#Rhythm"],
custom: ["custom"],
});
const search = ref()
</script>
```ts
import Pills from "~/components/ui/Pills.vue"
```
# Pills
Show a dense list of pills representing tags, categories or options.
Users can select a subset of given options and create new ones.
The model you provide will be mutated by this component:
- `current`: these pills are currently selected
- `others`: these pills are currently not selected (but can be selected by the user). This prop is optional. By adding it, you allow users to change the selection.
- `custom`: these pills were created by the user. This prop is optional. Users can edit, add and remove any pill defined in this array. Note that the `custom` array should only contain pills that are either in `current` or in `others`.
::: warning
If you place custom pills into `others`, the user will be able to select, edit and delete them but not to deselect them. If there is a use case for this, we have to design a good UX for deselecting custom pills.
:::
## No pills
```ts
const nullModel = ref({
current: []
});
```
```vue-html
<Pills v-model="nullModel" />
```
<Layout class="preview" style="padding:16px">
<Pills v-model="nullModel" />
</Layout>
## Predefined list of pills
```ts
const staticModel = ref({
current: ["#Noise", "#FieldRecording", "#Experiment"]
});
```
```vue-html
<Pills v-model="staticModel" label="Tags" />
```
<Layout class="preview" style="padding:16px">
<Pills v-model="staticModel" label="Tags" />
</Layout>
## Let users select and unselect pills
Select a set of pills from presets, and add and remove custom ones
```ts
const interactiveModel = ref({
current: ["#Noise", "#FieldRecording", "#Experiment"],
others: ["#Melody", "#Rhythm"]
});
```
```vue-html
<Pills v-model="interactiveModel" label="Tags" />
```
<Layout class="preview" style="padding:16px">
<Pills v-model="interactiveModel" label="Tags" />
</Layout>
## Let users add, remove and edit custom pills
Use [reactive](https://vuejs.org/guide/essentials/reactivity-fundamentals.html#reactive-variables-with-ref) methods [such as `computed(...)`](https://vuejs.org/guide/essentials/computed.html) and `watch(...)` to query the model.
```ts
const customModel = ref({
current: ["custom", "#FieldRecording", "#Experiment"],
others: ["#Melody", "#Rhythm"],
custom: ["custom"]
});
```
```vue-html
<Pills v-model="customModel" label="Custom" />
```
<Layout class="preview" style="padding:16px">
<Pills v-model="customModel" label="Custom" />
</Layout>
## Combine Pills with other input fields
<Spacer />
<Layout form flex>
<Input
v-model="search"
label="Search"
style="max-width: 150px;"
/>
<Pills
v-model="customModel"
label="Filter by tags"
style="max-width: 250px;"
/>
<Layout stack noGap label>
<span class="label"> Ordering </span>
<select>
<option
v-for="key in ['by date', 'by duration']"
:value="key"
>
key
</option>
</select>
</Layout>
<Input
v-model="search"
label="Option"
style="max-width: 50px;"
/>
</Layout>