fix ui
This commit is contained in:
82
src/components/SortDropdown.vue
Normal file
82
src/components/SortDropdown.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, ref } from "vue";
|
||||
|
||||
type Option = {
|
||||
label: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
const props = defineProps<{
|
||||
label?: string;
|
||||
modelValue: string;
|
||||
options: Option[];
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
"update:modelValue": [value: string];
|
||||
}>();
|
||||
|
||||
const open = ref(false);
|
||||
const root = ref<HTMLElement | null>(null);
|
||||
|
||||
const selectedLabel = computed(
|
||||
() =>
|
||||
props.options.find((option) => option.value === props.modelValue)?.label ??
|
||||
props.options[0]?.label ??
|
||||
"",
|
||||
);
|
||||
|
||||
function toggle() {
|
||||
open.value = !open.value;
|
||||
}
|
||||
|
||||
function select(value: string) {
|
||||
emit("update:modelValue", value);
|
||||
open.value = false;
|
||||
}
|
||||
|
||||
function handleDocumentPointer(event: PointerEvent) {
|
||||
if (!root.value) return;
|
||||
const target = event.target;
|
||||
if (target instanceof Node && !root.value.contains(target)) {
|
||||
open.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
window.addEventListener("pointerdown", handleDocumentPointer);
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
window.removeEventListener("pointerdown", handleDocumentPointer);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="root" class="sort-dropdown">
|
||||
<span v-if="label" class="sort-dropdown-label">{{ label }}</span>
|
||||
<button
|
||||
class="sort-dropdown-trigger"
|
||||
:class="{ open }"
|
||||
type="button"
|
||||
@click="toggle"
|
||||
>
|
||||
<span>{{ selectedLabel }}</span>
|
||||
<span class="sort-dropdown-caret" aria-hidden="true"></span>
|
||||
</button>
|
||||
<div v-if="open" class="sort-dropdown-menu">
|
||||
<button
|
||||
v-for="option in options"
|
||||
:key="option.value"
|
||||
class="sort-dropdown-option"
|
||||
:class="{ active: option.value === modelValue }"
|
||||
type="button"
|
||||
@click="select(option.value)"
|
||||
>
|
||||
{{ option.label }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user