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',
},
}