Make DropdownSelect component

This commit is contained in:
Christian Cueni 2022-09-06 10:26:50 +02:00
parent 1a41fe4f10
commit c35b5cce70
4 changed files with 88 additions and 36 deletions

View File

@ -1,6 +1,5 @@
<script setup lang="ts">
import {reactive} from 'vue'
import {Menu, MenuButton, MenuItems, MenuItem} from '@headlessui/vue'
const props = defineProps<{

View File

@ -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>

View File

@ -1,5 +1,4 @@
<script setup lang="ts">
import LinkCard from "@/components/mediacenter/LinkCard.vue";
import HandlungsfeldLayout from "@/views/HandlungsfeldLayout.vue";
const data = {

View File

@ -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>