UNPKG

@mozaic-ds/vue

Version:

Mozaic-Vue is the Vue.js implementation of ADEO Design system

192 lines (170 loc) 4.5 kB
import type { Meta, StoryObj } from '@storybook/vue3-vite'; import MCombobox from './MCombobox.vue'; import { computed, ref } from 'vue'; import type { ListboxOption } from '../optionListbox/MOptionListbox.vue'; import MTag from '../tag/MTag.vue'; import MButton from '../button/MButton.vue'; const defaultOptions = Array.from({ length: 12 }).map((_el, index) => { return { label: `Option ${index + 1}`, value: `option${index + 1}`, }; }); let optionCount = 0; const optionsWithSections: ListboxOption[] = Array.from({ length: 12 }).map( (_el, index) => { const isSection = index % 3 === 0; if (!isSection) { optionCount++; } return { label: `${isSection ? 'Section' : 'Option'} ${isSection ? index / 3 + 1 : optionCount}`, value: !isSection ? `option${optionCount}` : undefined, type: isSection ? 'section' : 'option', }; }, ); const meta: Meta<typeof MCombobox> = { title: 'Form elements/Combobox', component: MCombobox, tags: ['v2'], parameters: { docs: { description: { component: 'A combobox is an input field that allows users to select an option from a dropdown list or enter a custom value. It combines the functionality of a text input and a dropdown menu, providing flexibility and ease of use in forms and user interfaces.', }, story: { height: '300px', }, }, }, args: { open: false, modelValue: null, checkableSections: true, options: defaultOptions, }, render: (args) => ({ components: { MCombobox }, setup() { const counterLabel = computed( () => `${(args.modelValue as Array<unknown>)?.length} selected`, ); return { args, counterLabel }; }, template: ` <MCombobox v-bind="args" v-model="args.modelValue" v-model:open="args.open" :counter-label="counterLabel"></MCombobox> `, }), }; export default meta; type Story = StoryObj<typeof MCombobox>; export const Default: Story = {}; export const Multiple: Story = { args: { multiple: true, modelValue: [], }, }; export const SearchInput: Story = { args: { search: true, modelValue: [], multiple: true, }, }; export const ActionButtons: Story = { args: { modelValue: [], multiple: true, actions: true, }, }; export const WithSections: Story = { args: { options: optionsWithSections, }, }; export const SelectableSections: Story = { args: { modelValue: [], multiple: true, options: optionsWithSections, checkableSections: true, }, }; export const Clearable = { args: { clearable: true, }, }; export const Disabled: Story = { args: { disabled: true, }, }; export const Readonly: Story = { args: { readonly: true, }, }; export const Invalid: Story = { args: { invalid: true, }, }; export const AdditionalInformation: Story = { args: { options: defaultOptions.map((option) => ({ ...option, content: 'Additional information', })), }, }; export const RemovableTags: Story = { args: { modelValue: [], options: defaultOptions, multiple: true, }, render: (args) => ({ components: { MCombobox, MTag, MButton }, setup() { function findByValue(value: string | number) { return args.options.find((option) => option.value === value); } const open = ref(false); const maxResultsDisplayed = ref(9); const counterLabel = computed( () => `${(args.modelValue as Array<unknown>)?.length} selected`, ); return { args, counterLabel, maxResultsDisplayed, findByValue, open }; }, template: ` <MCombobox v-bind="args" v-model="args.modelValue" :counter-label="counterLabel" @update:open="open = $event"></MCombobox> <template v-if="!open" > <div style="width: 300px; display: flex;align-items: center;gap: 10px;flex-wrap: wrap;margin: 16px 0;"> <MTag v-for="(item, index) in args.modelValue?.slice(0, maxResultsDisplayed)" :key="index" id="tag" :label="findByValue(item)?.label || ''" type="removable" size="s" /> </div> <MButton v-if="args.modelValue?.length > maxResultsDisplayed" outlined size="s" @click="maxResultsDisplayed = args.modelValue?.length" > Show more </MButton> </template> `, }), };