import type { Meta, StoryObj } from '@storybook/vue3-vite' import { ref } from 'vue' import CpSelectMenu from '@/components/CpSelectMenu.vue' interface SelectValue { label: string value: string } const meta = { title: 'Molecules/CpSelectMenu', component: CpSelectMenu, argTypes: { values: { control: 'object', description: 'Array of options to display' }, selectedValue: { control: 'object', description: 'Currently selected value' }, hasFilter: { control: 'boolean', description: 'Whether to show search filter' }, dropdownTitle: { control: 'text', description: 'Title text for the dropdown' }, dropdownFilterPlaceholder: { control: 'text', description: 'Placeholder text for the filter input' }, dropdownEmptyViewPlaceholder: { control: 'text', description: 'Text to show when no options match the filter', }, closeOnSelect: { control: 'boolean', description: 'Whether to close dropdown after selection' }, }, decorators: [() => ({ template: '
' })], } satisfies Meta export default meta type Story = StoryObj type SelectMenuStoryArgs = NonNullable function pickSelectMenuBindProps(args: SelectMenuStoryArgs) { return { closeOnSelect: args.closeOnSelect, dropdownEmptyViewPlaceholder: args.dropdownEmptyViewPlaceholder, dropdownFilterPlaceholder: args.dropdownFilterPlaceholder, dropdownTitle: args.dropdownTitle, hasFilter: args.hasFilter, } } const sampleOptions = [ { value: '1', label: 'Apple' }, { value: '2', label: 'Banana' }, { value: '3', label: 'Orange' }, { value: '4', label: 'Mango' }, { value: '5', label: 'Strawberry' }, { value: '6', label: 'Blueberry' }, { value: '7', label: 'Cherry' }, ] /** * Default select menu. Use the controls to experiment with each prop in * isolation. */ export const Default: Story = { args: { values: sampleOptions, selectedValue: { value: '1', label: 'Apple' }, hasFilter: false, dropdownTitle: 'Select value', dropdownFilterPlaceholder: 'Filter...', dropdownEmptyViewPlaceholder: 'No option found', closeOnSelect: true, }, render: (args: SelectMenuStoryArgs) => ({ components: { CpSelectMenu }, setup() { const selectedValue = ref({ ...args.selectedValue }) const values = ref([...(args.values ?? [])]) const menuProps = pickSelectMenuBindProps(args) const onUpdateSelectedValue = (data: SelectValue) => { selectedValue.value = data } return { menuProps, onUpdateSelectedValue, selectedValue, values } }, template: `
`, }), } export const WithFilter: Story = { args: { ...Default.args, hasFilter: true, dropdownTitle: 'Search for a fruit', }, render: (args: SelectMenuStoryArgs) => ({ components: { CpSelectMenu }, setup() { const selectedValue = ref({ ...args.selectedValue }) const values = ref([...(args.values ?? [])]) const menuProps = pickSelectMenuBindProps(args) const searchQuery = ref('') const onUpdateSelectedValue = (data: SelectValue) => { selectedValue.value = data } const onFilterChange = (data: string) => { searchQuery.value = data values.value = sampleOptions.filter((option) => option.label.toLowerCase().includes(searchQuery.value.toLowerCase()), ) } return { menuProps, onFilterChange, onUpdateSelectedValue, selectedValue, values } }, template: `
`, }), } /** * Override the dropdown title via `dropdownTitle`. */ export const CustomTitle: Story = { args: { ...Default.args, dropdownTitle: 'My custom title', }, }