Make DropdownSelect component
This commit is contained in:
parent
1a41fe4f10
commit
c35b5cce70
|
|
@ -1,6 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
|
||||
import {reactive} from 'vue'
|
||||
import {Menu, MenuButton, MenuItems, MenuItem} from '@headlessui/vue'
|
||||
|
||||
const props = defineProps<{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
<script setup lang="ts">
|
||||
import { watch, onMounted, reactive, defineEmits, computed } from 'vue'
|
||||
import {Listbox, ListboxButton, ListboxOption, ListboxOptions} from '@headlessui/vue';
|
||||
|
||||
export interface DropdownSelectable {
|
||||
id: number|string,
|
||||
name: string
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/64775876/vue-3-pass-reactive-object-to-component-with-two-way-binding
|
||||
export interface Props {
|
||||
modelValue: {
|
||||
id: string|number
|
||||
name: string
|
||||
},
|
||||
items: DropdownSelectable[]
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', data: object): void
|
||||
}>()
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: {
|
||||
id: -1,
|
||||
name: ''
|
||||
},
|
||||
items: [],
|
||||
})
|
||||
|
||||
const dropdownSelected = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Listbox as="div" v-model="dropdownSelected">
|
||||
<div class="mt-1 relative w-128">
|
||||
<ListboxButton
|
||||
class="bg-white relative w-full border border-gray-500 pl-5 pr-10 py-3 text-left cursor-default font-bold">
|
||||
<span class="block truncate">{{ dropdownSelected.name }}</span>
|
||||
<span class="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
||||
<it-icon-arrow-down class="h-5 w-5" aria-hidden="true"/>
|
||||
</span>
|
||||
</ListboxButton>
|
||||
|
||||
<transition leave-active-class="transition ease-in duration-100" leave-from-class="opacity-100"
|
||||
leave-to-class="opacity-0">
|
||||
<ListboxOptions
|
||||
class="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm">
|
||||
<ListboxOption
|
||||
as="template"
|
||||
v-for="item in items"
|
||||
:key="item.id"
|
||||
:value="item"
|
||||
v-slot="{ active, selected }">
|
||||
<li
|
||||
:class="[active ? 'text-white bg-blue-900' : 'text-black', 'cursor-default select-none relative py-2 pl-3 pr-9']">
|
||||
<span :class="[dropdownSelected ? 'font-semibold' : 'font-normal', 'block truncate']">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
|
||||
<span v-if="dropdownSelected"
|
||||
class="text-blue-900 absolute inset-y-0 right-0 flex items-center pr-4">
|
||||
<it-icon-check
|
||||
v-if="selected"
|
||||
class="h-5 w-5"
|
||||
aria-hidden="true"/>
|
||||
</span>
|
||||
</li>
|
||||
</ListboxOption>
|
||||
</ListboxOptions>
|
||||
</transition>
|
||||
</div>
|
||||
</Listbox>
|
||||
</template>
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
<script setup lang="ts">
|
||||
import LinkCard from "@/components/mediacenter/LinkCard.vue";
|
||||
import HandlungsfeldLayout from "@/views/HandlungsfeldLayout.vue";
|
||||
|
||||
const data = {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
|
||||
import {reactive} from 'vue'
|
||||
import {Listbox, ListboxButton, ListboxOption, ListboxOptions} from '@headlessui/vue'
|
||||
import ItCheckbox from '@/components/ui/ItCheckbox.vue';
|
||||
import ItDropdown from "@/components/ui/ItDropdown.vue";
|
||||
import IconLogout from "@/components/icons/IconLogout.vue"
|
||||
import IconSettings from "@/components/icons/IconSettings.vue"
|
||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||
|
||||
|
||||
const state = reactive({
|
||||
|
|
@ -22,7 +22,10 @@ const state = reactive({
|
|||
{id: 9, name: 'Claudie Smitham'},
|
||||
{id: 10, name: 'Emil Schaefer'},
|
||||
],
|
||||
dropdownSelected: {id: 8},
|
||||
dropdownSelected: {
|
||||
id: -1,
|
||||
name: 'Select a name'
|
||||
},
|
||||
})
|
||||
|
||||
const dropdownData = [
|
||||
|
|
@ -294,38 +297,11 @@ function log(data: any) {
|
|||
|
||||
<h2 class="mt-8 mb-8">Dropdown (Work-in-progress)</h2>
|
||||
|
||||
<Listbox as="div" v-model="state.dropdownSelected">
|
||||
<div class="mt-1 relative w-128">
|
||||
<ListboxButton
|
||||
class="bg-white relative w-full border border-gray-500 pl-5 pr-10 py-3 text-left cursor-default font-bold">
|
||||
<span class="block truncate">{{ state.dropdownSelected.name }}</span>
|
||||
<span class="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
||||
<it-icon-arrow-down class="h-5 w-5" aria-hidden="true"/>
|
||||
</span>
|
||||
</ListboxButton>
|
||||
|
||||
<transition leave-active-class="transition ease-in duration-100" leave-from-class="opacity-100"
|
||||
leave-to-class="opacity-0">
|
||||
<ListboxOptions
|
||||
class="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm">
|
||||
<ListboxOption as="template" v-for="person in state.dropdownValues" :key="person.id" :value="person"
|
||||
v-slot="{ active, selected }">
|
||||
<li
|
||||
:class="[active ? 'text-white bg-blue-900' : 'text-black', 'cursor-default select-none relative py-2 pl-3 pr-9']">
|
||||
<span :class="[state.dropdownSelected ? 'font-semibold' : 'font-normal', 'block truncate']">
|
||||
{{ person.name }}
|
||||
</span>
|
||||
|
||||
<span v-if="state.dropdownSelected"
|
||||
:class="[active ? 'text-white' : 'text-blue-900', 'absolute inset-y-0 right-0 flex items-center pr-4']">
|
||||
<it-icon-check class="h-5 w-5" aria-hidden="true"/>
|
||||
</span>
|
||||
</li>
|
||||
</ListboxOption>
|
||||
</ListboxOptions>
|
||||
</transition>
|
||||
</div>
|
||||
</Listbox>
|
||||
<ItDropdownSelect
|
||||
v-model="state.dropdownSelected"
|
||||
:items="state.dropdownValues">
|
||||
</ItDropdownSelect>
|
||||
{{state.dropdownSelected}}
|
||||
|
||||
<h2 class="mt-8 mb-8">Checkbox</h2>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue