100 lines
2.3 KiB
Vue
100 lines
2.3 KiB
Vue
<template>
|
|
<div class="dropdown-wrapper">
|
|
<button
|
|
:aria-label="buttonLabel"
|
|
:aria-expanded="isOpen"
|
|
class="dropdown-selector transparent"
|
|
@click="toggleDropdown"
|
|
>
|
|
<slot></slot>
|
|
</button>
|
|
<ul class="dropdown-list" v-if="isOpen">
|
|
<li
|
|
class="dropdown-item"
|
|
:class="{ selected: option.value === selected }"
|
|
v-for="(option, index) in dropdownOptions"
|
|
:key="index"
|
|
tabindex="0"
|
|
@click="updateSelected(option)"
|
|
@keydown.enter="updateSelected(option)"
|
|
role="button"
|
|
>
|
|
{{ option.label }}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, toRefs, watch } from 'vue'
|
|
import { useRoute } from 'vue-router'
|
|
|
|
import type { IDropdownOption, TDropdownOptions } from '@/types/forms'
|
|
interface Props {
|
|
options: TDropdownOptions
|
|
selected: string
|
|
buttonLabel: string
|
|
}
|
|
const props = defineProps<Props>()
|
|
const { options } = toRefs(props)
|
|
|
|
const emit = defineEmits({
|
|
selected: (option: IDropdownOption) => option,
|
|
})
|
|
|
|
const route = useRoute()
|
|
const isOpen = ref(false)
|
|
const dropdownOptions = options.value.map((option) => option)
|
|
|
|
function toggleDropdown() {
|
|
isOpen.value = !isOpen.value
|
|
}
|
|
function updateSelected(option: IDropdownOption) {
|
|
emit('selected', option)
|
|
isOpen.value = false
|
|
}
|
|
|
|
watch(
|
|
() => route.path,
|
|
() => (isOpen.value = false)
|
|
)
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
@import '~@/scss/vars.scss';
|
|
.dropdown-wrapper {
|
|
.dropdown-selector {
|
|
margin: 0;
|
|
padding: $default-padding * 0.5;
|
|
}
|
|
|
|
.dropdown-list {
|
|
list-style-type: none;
|
|
background-color: var(--dropdown-background-color);
|
|
padding: 0 !important;
|
|
margin-top: 5px;
|
|
margin-left: -20px !important;
|
|
position: absolute;
|
|
text-align: left;
|
|
border: solid 1px var(--dropdown-border-color);
|
|
box-shadow: 2px 2px 5px var(--app-shadow-color);
|
|
width: auto !important;
|
|
|
|
.dropdown-item {
|
|
padding: 3px 12px;
|
|
&.selected {
|
|
font-weight: bold;
|
|
}
|
|
|
|
&.selected::after {
|
|
content: ' ✔';
|
|
}
|
|
|
|
&:hover {
|
|
background-color: var(--dropdown-hover-color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|