11import type { Meta , StoryObj } from '@storybook/vue3-vite'
2+ import type { MultiSelectProps } from 'primevue/multiselect'
23import { ref } from 'vue'
34
45import MultiSelect from './MultiSelect.vue'
56
6- const meta : Meta < typeof MultiSelect > = {
7+ // Combine our component props with PrimeVue MultiSelect props
8+ // Since we use v-bind="$attrs", all PrimeVue props are available
9+ interface ExtendedProps extends Partial < MultiSelectProps > {
10+ // Our custom props
11+ label ?: string
12+ showSearchBox ?: boolean
13+ showSelectedCount ?: boolean
14+ showClearButton ?: boolean
15+ searchPlaceholder ?: string
16+ // Override modelValue type to match our Option type
17+ modelValue ?: Array < { name : string ; value : string } >
18+ }
19+
20+ const meta : Meta < ExtendedProps > = {
721 title : 'Components/Input/MultiSelect' ,
822 component : MultiSelect ,
923 tags : [ 'autodocs' ] ,
@@ -13,7 +27,35 @@ const meta: Meta<typeof MultiSelect> = {
1327 } ,
1428 options : {
1529 control : 'object'
30+ } ,
31+ showSearchBox : {
32+ control : 'boolean' ,
33+ description : 'Toggle searchBar visibility'
34+ } ,
35+ showSelectedCount : {
36+ control : 'boolean' ,
37+ description : 'Toggle selected count visibility'
38+ } ,
39+ showClearButton : {
40+ control : 'boolean' ,
41+ description : 'Toggle clear button visibility'
42+ } ,
43+ searchPlaceholder : {
44+ control : 'text'
1645 }
46+ } ,
47+ args : {
48+ label : 'Select' ,
49+ options : [
50+ { name : 'Vue' , value : 'vue' } ,
51+ { name : 'React' , value : 'react' } ,
52+ { name : 'Angular' , value : 'angular' } ,
53+ { name : 'Svelte' , value : 'svelte' }
54+ ] ,
55+ showSearchBox : false ,
56+ showSelectedCount : false ,
57+ showClearButton : false ,
58+ searchPlaceholder : 'Search...'
1759 }
1860}
1961
@@ -25,7 +67,7 @@ export const Default: Story = {
2567 components : { MultiSelect } ,
2668 setup ( ) {
2769 const selected = ref ( [ ] )
28- const options = [
70+ const options = args . options || [
2971 { name : 'Vue' , value : 'vue' } ,
3072 { name : 'React' , value : 'react' } ,
3173 { name : 'Angular' , value : 'angular' } ,
@@ -38,8 +80,11 @@ export const Default: Story = {
3880 <MultiSelect
3981 v-model="selected"
4082 :options="options"
41- label="Select Frameworks"
42- v-bind="args"
83+ :label="args.label"
84+ :showSearchBox="args.showSearchBox"
85+ :showSelectedCount="args.showSelectedCount"
86+ :showClearButton="args.showClearButton"
87+ :searchPlaceholder="args.searchPlaceholder"
4388 />
4489 <div class="mt-4 p-3 bg-gray-50 dark-theme:bg-zinc-800 rounded">
4590 <p class="text-sm">Selected: {{ selected.length > 0 ? selected.map(s => s.name).join(', ') : 'None' }}</p>
@@ -50,36 +95,54 @@ export const Default: Story = {
5095}
5196
5297export const WithPreselectedValues : Story = {
53- render : ( ) => ( {
98+ render : ( args ) => ( {
5499 components : { MultiSelect } ,
55100 setup ( ) {
56- const options = [
101+ const options = args . options || [
57102 { name : 'JavaScript' , value : 'js' } ,
58103 { name : 'TypeScript' , value : 'ts' } ,
59104 { name : 'Python' , value : 'python' } ,
60105 { name : 'Go' , value : 'go' } ,
61106 { name : 'Rust' , value : 'rust' }
62107 ]
63108 const selected = ref ( [ options [ 0 ] , options [ 1 ] ] )
64- return { selected, options }
109+ return { selected, options, args }
65110 } ,
66111 template : `
67112 <div>
68113 <MultiSelect
69114 v-model="selected"
70115 :options="options"
71- label="Select Languages"
116+ :label="args.label"
117+ :showSearchBox="args.showSearchBox"
118+ :showSelectedCount="args.showSelectedCount"
119+ :showClearButton="args.showClearButton"
120+ :searchPlaceholder="args.searchPlaceholder"
72121 />
73122 <div class="mt-4 p-3 bg-gray-50 dark-theme:bg-zinc-800 rounded">
74123 <p class="text-sm">Selected: {{ selected.map(s => s.name).join(', ') }}</p>
75124 </div>
76125 </div>
77126 `
78- } )
127+ } ) ,
128+ args : {
129+ label : 'Select Languages' ,
130+ options : [
131+ { name : 'JavaScript' , value : 'js' } ,
132+ { name : 'TypeScript' , value : 'ts' } ,
133+ { name : 'Python' , value : 'python' } ,
134+ { name : 'Go' , value : 'go' } ,
135+ { name : 'Rust' , value : 'rust' }
136+ ] ,
137+ showSearchBox : false ,
138+ showSelectedCount : false ,
139+ showClearButton : false ,
140+ searchPlaceholder : 'Search...'
141+ }
79142}
80143
81144export const MultipleSelectors : Story = {
82- render : ( ) => ( {
145+ render : ( args ) => ( {
83146 components : { MultiSelect } ,
84147 setup ( ) {
85148 const frameworkOptions = ref ( [
@@ -114,7 +177,8 @@ export const MultipleSelectors: Story = {
114177 tagOptions,
115178 selectedFrameworks,
116179 selectedProjects,
117- selectedTags
180+ selectedTags,
181+ args
118182 }
119183 } ,
120184 template : `
@@ -124,28 +188,89 @@ export const MultipleSelectors: Story = {
124188 v-model="selectedFrameworks"
125189 :options="frameworkOptions"
126190 label="Select Frameworks"
191+ :showSearchBox="args.showSearchBox"
192+ :showSelectedCount="args.showSelectedCount"
193+ :showClearButton="args.showClearButton"
194+ :searchPlaceholder="args.searchPlaceholder"
127195 />
128196 <MultiSelect
129197 v-model="selectedProjects"
130198 :options="projectOptions"
131199 label="Select Projects"
200+ :showSearchBox="args.showSearchBox"
201+ :showSelectedCount="args.showSelectedCount"
202+ :showClearButton="args.showClearButton"
203+ :searchPlaceholder="args.searchPlaceholder"
132204 />
133205 <MultiSelect
134206 v-model="selectedTags"
135207 :options="tagOptions"
136208 label="Select Tags"
209+ :showSearchBox="args.showSearchBox"
210+ :showSelectedCount="args.showSelectedCount"
211+ :showClearButton="args.showClearButton"
212+ :searchPlaceholder="args.searchPlaceholder"
137213 />
138214 </div>
139215
140216 <div class="p-4 bg-gray-50 dark-theme:bg-zinc-800 rounded">
141- <h4 class="font-medium mb-2 ">Current Selection:</h4>
142- <div class="space-y-1 text-sm">
217+ <h4 class="font-medium mt-0 ">Current Selection:</h4>
218+ <div class="flex flex-col text-sm">
143219 <p>Frameworks: {{ selectedFrameworks.length > 0 ? selectedFrameworks.map(s => s.name).join(', ') : 'None' }}</p>
144220 <p>Projects: {{ selectedProjects.length > 0 ? selectedProjects.map(s => s.name).join(', ') : 'None' }}</p>
145221 <p>Tags: {{ selectedTags.length > 0 ? selectedTags.map(s => s.name).join(', ') : 'None' }}</p>
146222 </div>
147223 </div>
148224 </div>
149225 `
150- } )
226+ } ) ,
227+ args : {
228+ showSearchBox : false ,
229+ showSelectedCount : false ,
230+ showClearButton : false ,
231+ searchPlaceholder : 'Search...'
232+ }
233+ }
234+
235+ export const WithSearchBox : Story = {
236+ ...Default ,
237+ args : {
238+ ...Default . args ,
239+ showSearchBox : true
240+ }
241+ }
242+
243+ export const WithSelectedCount : Story = {
244+ ...Default ,
245+ args : {
246+ ...Default . args ,
247+ showSelectedCount : true
248+ }
249+ }
250+
251+ export const WithClearButton : Story = {
252+ ...Default ,
253+ args : {
254+ ...Default . args ,
255+ showClearButton : true
256+ }
257+ }
258+
259+ export const AllHeaderFeatures : Story = {
260+ ...Default ,
261+ args : {
262+ ...Default . args ,
263+ showSearchBox : true ,
264+ showSelectedCount : true ,
265+ showClearButton : true
266+ }
267+ }
268+
269+ export const CustomSearchPlaceholder : Story = {
270+ ...Default ,
271+ args : {
272+ ...Default . args ,
273+ showSearchBox : true ,
274+ searchPlaceholder : 'Filter packages...'
275+ }
151276}
0 commit comments