feat(ui-docs): add usability warning; make encapsulating popover state the default example; add example with long list; add TOC
This commit is contained in:
parent
e1072b9dbb
commit
adec453e83
|
@ -1,5 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
import { SUPPORTED_LOCALES, setI18nLanguage } from '~/init/locale'
|
||||||
|
|
||||||
import Button from "~/components/ui/Button.vue"
|
import Button from "~/components/ui/Button.vue"
|
||||||
import OptionsButton from "~/components/ui/button/Options.vue"
|
import OptionsButton from "~/components/ui/button/Options.vue"
|
||||||
|
@ -51,22 +52,55 @@ Common uses:
|
||||||
- Settings menus
|
- Settings menus
|
||||||
- Context menus (right-click menus)
|
- Context menus (right-click menus)
|
||||||
|
|
||||||
|
::: warning
|
||||||
|
|
||||||
|
This component has severe usability issues and cannot be used as-is:
|
||||||
|
|
||||||
|
- I can't operate the popup with a keyboard. Remove barrier for people not using a mouse (A11y)
|
||||||
|
- Switching to submenus is error-prone. When moving cursor into freshly opened submenu, it should not close if the cursor crosses another menu item
|
||||||
|
- Large menus disappear. When menus get big, they need to scroll.
|
||||||
|
|
||||||
|
Common Ui libraries in the Vue ecosystem such as vuetify or shadcn-vue all implement these features. It may be prudent to use their components.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
| Prop | Data type | Required? | Description |
|
| Prop | Data type | Required? | Description |
|
||||||
| ------ | --------- | --------- | ---------------------------------------------------------- |
|
| ------ | --------- | --------- | ---------------------------------------------------------- |
|
||||||
| `open` | Boolean | No | Controls whether the popover is open. Defaults to `false`. |
|
| `open` | Boolean | No | Controls whether the popover is open. Defaults to `false`. |
|
||||||
|
|
||||||
## Options button
|
[[toc]]
|
||||||
|
|
||||||
The options button (`OptionsButton`) is a stylized button you can use to hide and show your popover. Use [Vue event handling](https://vuejs.org/guide/essentials/event-handling.html) to map the button to a boolean value.
|
```vue-html
|
||||||
|
<Popover>
|
||||||
|
<template #default="{ toggleOpen }">
|
||||||
|
<OptionsButton @click="toggleOpen" />
|
||||||
|
</template>
|
||||||
|
</Popover>
|
||||||
|
```
|
||||||
|
|
||||||
|
<Popover>
|
||||||
|
<template #default="{ toggleOpen }">
|
||||||
|
<OptionsButton @click="toggleOpen" />
|
||||||
|
</template>
|
||||||
|
</Popover>
|
||||||
|
|
||||||
|
Destructure the function `toggleOpen` and let
|
||||||
|
a [default dropdown button: `OptionsButton`](./button/options.md) trigger it. This way, the state of the component is encapsulated.
|
||||||
|
|
||||||
|
## Bind to `isOpen`
|
||||||
|
|
||||||
|
If you want to process or influence the expansion of the menu in the containing component, you can bind it to a `ref`.
|
||||||
|
|
||||||
|
Use [Vue event handling](https://vuejs.org/guide/essentials/event-handling.html) to map the button to a boolean value.
|
||||||
|
|
||||||
```vue{7}
|
```vue{7}
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const open = ref(false)
|
const isOpen = ref(false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Popover v-model:open="open">
|
<Popover v-model:open="isOpen">
|
||||||
<OptionsButton @click="open = !open" />
|
<OptionsButton @click="isOpen = !isOpen" />
|
||||||
</Popover>
|
</Popover>
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
@ -75,25 +109,27 @@ The options button (`OptionsButton`) is a stylized button you can use to hide an
|
||||||
<OptionsButton @click="emptyMenu = !emptyMenu" />
|
<OptionsButton @click="emptyMenu = !emptyMenu" />
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
You can also use the `toggleOpen` prop in the `<template #default`> tag if you prefer not to use refs to control the menu's visibility.
|
## Customize the dropdown button
|
||||||
|
|
||||||
```vue{8-12}
|
```vue
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const open = ref(false)
|
const open = ref(false);
|
||||||
const privacyChoices = ['pod', 'public', 'private']
|
const privacyChoices = ["pod", "public", "private"];
|
||||||
const bcPrivacy = ref('pod')
|
const bcPrivacy = ref("pod");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Popover v-model:open="isOpen">
|
<Popover v-model:open="isOpen">
|
||||||
<template #default="{ toggleOpen }">
|
<template #default="{ toggleOpen }">
|
||||||
<Pill
|
<Pill
|
||||||
@click="(e) => {
|
@click="
|
||||||
|
(e) => {
|
||||||
console.log('Pill clicked');
|
console.log('Pill clicked');
|
||||||
console.log('Before toggleOpen:', isOpen);
|
console.log('Before toggleOpen:', isOpen);
|
||||||
toggleOpen();
|
toggleOpen();
|
||||||
console.log('After toggleOpen:', isOpen);
|
console.log('After toggleOpen:', isOpen);
|
||||||
}"
|
}
|
||||||
|
"
|
||||||
:blue="bcPrivacy === 'pod'"
|
:blue="bcPrivacy === 'pod'"
|
||||||
:red="bcPrivacy === 'public'"
|
:red="bcPrivacy === 'public'"
|
||||||
>
|
>
|
||||||
|
@ -101,7 +137,7 @@ const bcPrivacy = ref('pod')
|
||||||
</Pill>
|
</Pill>
|
||||||
</template>
|
</template>
|
||||||
<template #items>
|
<template #items>
|
||||||
<PopoverRadio v-model="bcPrivacy" :choices="privacyChoices"/>
|
<PopoverRadio v-model="bcPrivacy" :choices="privacyChoices" />
|
||||||
</template>
|
</template>
|
||||||
</Popover>
|
</Popover>
|
||||||
</template>
|
</template>
|
||||||
|
@ -426,6 +462,19 @@ const privacyChoices = ["private", "pod", "public"];
|
||||||
<Popover v-model:open="open">
|
<Popover v-model:open="open">
|
||||||
<OptionsButton @click="open = !open" />
|
<OptionsButton @click="open = !open" />
|
||||||
<template #items>
|
<template #items>
|
||||||
|
<PopoverSubmenu>
|
||||||
|
<i class="bi bi-music-note-list" />
|
||||||
|
Change language
|
||||||
|
<template #items>
|
||||||
|
<PopoverItem
|
||||||
|
v-for="(language, key) in SUPPORTED_LOCALES"
|
||||||
|
:key="key"
|
||||||
|
@click="setI18nLanguage(key)"
|
||||||
|
>
|
||||||
|
{{ language }}
|
||||||
|
</PopoverItem>
|
||||||
|
</template>
|
||||||
|
</PopoverSubmenu>
|
||||||
<PopoverItem>
|
<PopoverItem>
|
||||||
<i class="bi bi-arrow-up-right" />
|
<i class="bi bi-arrow-up-right" />
|
||||||
Play next
|
Play next
|
||||||
|
@ -536,6 +585,17 @@ const privacyChoices = ["private", "pod", "public"];
|
||||||
<i class="bi bi-arrow-down-right" />
|
<i class="bi bi-arrow-down-right" />
|
||||||
Append to queue
|
Append to queue
|
||||||
</PopoverItem>
|
</PopoverItem>
|
||||||
|
<PopoverSubmenu>
|
||||||
|
<i class="bi bi-music-note-list" />
|
||||||
|
Change language
|
||||||
|
<template #items>
|
||||||
|
<PopoverItem v-for="(language, key) in SUPPORTED_LOCALES"
|
||||||
|
:key="key"
|
||||||
|
@click="setI18nLanguage(key)" >
|
||||||
|
{{ language }}
|
||||||
|
</PopoverItem>
|
||||||
|
</template>
|
||||||
|
</PopoverSubmenu>
|
||||||
<PopoverSubmenu>
|
<PopoverSubmenu>
|
||||||
<i class="bi bi-music-note-list" />
|
<i class="bi bi-music-note-list" />
|
||||||
Add to playlist
|
Add to playlist
|
||||||
|
|
Loading…
Reference in New Issue