Skip to content

Commit

Permalink
feat: Add Multiselect for tags
Browse files Browse the repository at this point in the history
  • Loading branch information
botmaster committed Feb 6, 2024
1 parent 67ba02b commit a5f1068
Show file tree
Hide file tree
Showing 11 changed files with 270 additions and 77 deletions.
8 changes: 6 additions & 2 deletions assets/scss/base/_forms.scss
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
// Select
select {
select.form-select {
@apply block w-full rounded-md border-0 py-1.5 text-body-txt shadow-sm ring-1 ring-inset ring-polarnight-nord-3
focus:ring-2 focus:ring-inset focus:ring-accent sm:max-w-xs sm:text-sm sm:leading-6;
}

input[type="text"] {
input[type="text"].form-input, .input-text {
@apply block w-full rounded-md border-0 py-1.5 text-body-txt shadow-sm ring-1 ring-inset ring-polarnight-nord-3
focus:ring-2 focus:ring-inset focus:ring-accent sm:max-w-xs sm:text-sm sm:leading-6;
}

input[type="checkbox"] {
@apply rounded border-b-polarnight-nord-0 text-body-txt shadow-sm focus:border-accent focus:ring focus:ring-offset-0 focus:ring-accent focus:ring-opacity-50;
}
114 changes: 114 additions & 0 deletions components/MultiSelectTag.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<script lang="ts" setup>
import { Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/vue';
// Props
const props = defineProps<{
options: { id: string, name: string }[]
}>();
const selectedOption = defineModel<string[]>({ required: true });
const query = ref('');
const filteredOption = computed(() =>
query.value === ''
? props.options
: props.options.filter(option =>
option.name
.toLowerCase()
.replace(/\s+/g, '')
.includes(query.value.toLowerCase().replace(/\s+/g, '')),
),
);
function displayValue(options: { id: string }[]) {
return options.map(option => option.name).join(', ');
}
</script>

<template>
<Combobox v-model="selectedOption" multiple nullable by="id">
<div class="multi-select form-multiselect">
<div
class="multi-select__label-container"
>
<!-- <span v-if="selectedOption.length === 0" class="multi-select__label">Select an option</span> -->
<ComboboxInput
class="multi-select__label" :display-value="displayValue"
placeholder="Select an option"
@change="query = $event.target.value"
/>
</div>

<ComboboxButton
class="ml-auto flex items-center"
>
<span>v</span>
</ComboboxButton>

<ComboboxOptions
class="multi-select__options"
>
<div
v-if="filteredOption.length === 0 && query !== ''"
class="multi-select__nothing-found"
>
Nothing found.
</div>
<ComboboxOption
v-for="option in filteredOption" :key="option.id" v-slot="{ active, selected }"
:value="option" as="template"
>
<li
class="multi-select__option" :aria-selected="selected" :class="{ active }"
>
<!-- <span class="block truncate" :class="[selected && 'font-semibold']">
{{ option.name }}
</span>
<span
v-if="selected" class="absolute inset-y-0 right-0 flex items-center pr-4"
:class="[active ? 'text-white' : 'text-accent']"
>
ok
</span> -->
<input class="form-checkbox" type="checkbox" :checked="selected"><span :class="[selected && 'font-semibold']">{{ option.name }}</span>
</li>
</ComboboxOption>
</ComboboxOptions>
</div>
</Combobox>
</template>

<style scoped lang="scss">
.multi-select {
@apply w-full relative flex items-center bg-white px-3
rounded-md border-0 py-1.5 text-body-txt shadow-sm ring-1 ring-inset ring-polarnight-nord-3
focus:ring-2 focus:ring-inset focus:ring-accent sm:max-w-xs sm:text-sm sm:leading-6;
&__label-container {
@apply flex items-center overflow-x-clip;
}
&__label {
color: red;
}
&__options {
@apply absolute left-0 top-[100%] z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm;
}
&__option {
@apply relative flex items-center gap-2 cursor-default select-none py-2 pl-3 pr-9;
&.active {
@apply bg-accent text-accent-content;
}
}
&__nothing-found {
@apply relative cursor-default select-none px-4 py-2;
}
}
</style>
34 changes: 34 additions & 0 deletions components/TestComponent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script setup>
import { ref } from 'vue';
import {
Combobox,
ComboboxInput,
ComboboxOption,
ComboboxOptions,
} from '@headlessui/vue';
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
];
const selectedPeople = ref([people[0], people[1]]);
</script>

<template>
<Combobox v-model="selectedPeople" as="div" multiple>
<ul v-if="selectedPeople.length > 0">
<li v-for="person in selectedPeople" :key="person.id">
{{ person.name }}
</li>
</ul>
<ComboboxInput />
<ComboboxOptions>
<ComboboxOption v-for="person in people" :key="person.id" :value="person">
{{ person.name }}
</ComboboxOption>
</ComboboxOptions>
</Combobox>
</template>
2 changes: 1 addition & 1 deletion components/shared/AppLoader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<style scoped>
.app-loader {
--uib-size: 1em;
--uib-color: black;
--uib-color: var(--color-body-text-hex, #000);
--uib-speed: 2s;
position: relative;
width: var(--uib-size);
Expand Down
1 change: 1 addition & 0 deletions locales/en.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"common": {
"clearFilters": "Clear filters",
"go": "Go",
"goToPage": "Go to page",
"languages": "Language",
Expand Down
1 change: 1 addition & 0 deletions locales/fr.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"common": {
"clearFilters": "Effacer les filtres",
"go": "Allez",
"goToPage": "Aller à la page",
"languages": "Langue",
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"dependencies": {
"@fontsource/inter": "^5.0.16",
"@fontsource/rubik": "^5.0.18",
"@headlessui/tailwindcss": "^0.2.0",
"@notionhq/client": "^2.2.14",
"@studio-freight/lenis": "^1.0.34",
"@vueuse/components": "^10.7.2",
Expand Down
Loading

0 comments on commit a5f1068

Please sign in to comment.