import type { Meta, StoryObj } from '@storybook/vue3' import { ref } from 'vue' import TitanIconSelectRenderer from './TitanIconSelectRenderer.vue' import type { IconSelectOption } from '@/types/components' const meta = { component: TitanIconSelectRenderer, title: 'UI/Internal/TitanIconSelectRenderer', tags: ['autodocs'], argTypes: { options: { control: 'object', description: 'Array of icon select options' }, showCheckmark: { control: 'boolean', description: 'Show checkmark on selected items' }, label: { control: 'text', description: 'Label displayed above the icon cards' }, disabled: { control: 'boolean', description: 'Disable all options' }, error: { control: 'boolean', description: 'Show error state' }, errorMessage: { control: 'text', description: 'Error message text' } } } satisfies Meta export default meta type Story = StoryObj /** * Default icon select renderer with two options */ export const Default: Story = { render: (args) => ({ components: { TitanIconSelectRenderer }, setup() { const selectedValue = ref('buried') const isSelected = (option: IconSelectOption) => selectedValue.value === option.value const handleSelect = (option: IconSelectOption) => { if (option.disabled) return selectedValue.value = selectedValue.value === option.value ? '' : option.value } const getStateClasses = (option: IconSelectOption) => ({ base: 'w-[100px] h-[102px] flex flex-col items-center justify-center rounded-lg border-2 transition-colors cursor-pointer', state: isSelected(option) ? 'bg-titan-purple-500 text-white border-titan-purple-500 shadow-sm' : 'bg-titan-green-800/10 text-titan-green-800 border-titan-green-800/20 hover:bg-titan-green-800/15', disabled: option.disabled ? 'opacity-50 cursor-not-allowed' : '' }) const getOptionAriaAttributes = (option: IconSelectOption) => ({ role: 'radio', 'aria-checked': isSelected(option), 'aria-disabled': option.disabled }) return { args, isSelected, handleSelect, getStateClasses, getOptionAriaAttributes } }, template: ` ` }), args: { options: [ { value: 'buried', label: 'Buried' }, { value: 'cremated', label: 'Cremated' } ] } } /** * Icon select with checkmark on selected item */ export const WithCheckmark: Story = { render: (args) => ({ components: { TitanIconSelectRenderer }, setup() { const selectedValue = ref('cremated') const isSelected = (option: IconSelectOption) => selectedValue.value === option.value const handleSelect = (option: IconSelectOption) => { if (option.disabled) return selectedValue.value = selectedValue.value === option.value ? '' : option.value } const getStateClasses = (option: IconSelectOption) => ({ base: 'w-[100px] h-[102px] flex flex-col items-center justify-center rounded-lg border-2 transition-colors cursor-pointer', state: isSelected(option) ? 'bg-titan-purple-500 text-white border-titan-purple-500 shadow-sm' : 'bg-titan-green-800/10 text-titan-green-800 border-titan-green-800/20 hover:bg-titan-green-800/15', disabled: option.disabled ? 'opacity-50 cursor-not-allowed' : '' }) const getOptionAriaAttributes = (option: IconSelectOption) => ({ role: 'radio', 'aria-checked': isSelected(option), 'aria-disabled': option.disabled }) return { args, isSelected, handleSelect, getStateClasses, getOptionAriaAttributes } }, template: ` ` }), args: { options: [ { value: 'buried', label: 'Buried' }, { value: 'cremated', label: 'Cremated' } ], showCheckmark: true } } /** * Icon select with three options */ export const ThreeOptions: Story = { render: (args) => ({ components: { TitanIconSelectRenderer }, setup() { const selectedValue = ref('') const isSelected = (option: IconSelectOption) => selectedValue.value === option.value const handleSelect = (option: IconSelectOption) => { if (option.disabled) return selectedValue.value = selectedValue.value === option.value ? '' : option.value } const getStateClasses = (option: IconSelectOption) => ({ base: 'w-[100px] h-[102px] flex flex-col items-center justify-center rounded-lg border-2 transition-colors cursor-pointer', state: isSelected(option) ? 'bg-titan-purple-500 text-white border-titan-purple-500 shadow-sm' : 'bg-titan-green-800/10 text-titan-green-800 border-titan-green-800/20 hover:bg-titan-green-800/15', disabled: option.disabled ? 'opacity-50 cursor-not-allowed' : '' }) const getOptionAriaAttributes = (option: IconSelectOption) => ({ role: 'radio', 'aria-checked': isSelected(option), 'aria-disabled': option.disabled }) return { args, isSelected, handleSelect, getStateClasses, getOptionAriaAttributes } }, template: ` ` }), args: { options: [ { value: 'buried', label: 'Buried' }, { value: 'cremated', label: 'Cremated' }, { value: 'other', label: 'Other' } ] } } /** * Icon select with disabled option */ export const WithDisabledOption: Story = { render: (args) => ({ components: { TitanIconSelectRenderer }, setup() { const selectedValue = ref('') const isSelected = (option: IconSelectOption) => selectedValue.value === option.value const handleSelect = (option: IconSelectOption) => { if (option.disabled) return selectedValue.value = selectedValue.value === option.value ? '' : option.value } const getStateClasses = (option: IconSelectOption) => ({ base: 'w-[100px] h-[102px] flex flex-col items-center justify-center rounded-lg border-2 transition-colors cursor-pointer', state: isSelected(option) ? 'bg-titan-purple-500 text-white border-titan-purple-500 shadow-sm' : 'bg-titan-green-800/10 text-titan-green-800 border-titan-green-800/20 hover:bg-titan-green-800/15', disabled: option.disabled ? 'opacity-50 cursor-not-allowed' : '' }) const getOptionAriaAttributes = (option: IconSelectOption) => ({ role: 'radio', 'aria-checked': isSelected(option), 'aria-disabled': option.disabled }) return { args, isSelected, handleSelect, getStateClasses, getOptionAriaAttributes } }, template: ` ` }), args: { options: [ { value: 'buried', label: 'Buried' }, { value: 'cremated', label: 'Cremated', disabled: true } ] } } /** * Icon select with label */ export const WithLabel: Story = { render: (args) => ({ components: { TitanIconSelectRenderer }, setup() { const selectedValue = ref('buried') const isSelected = (option: IconSelectOption) => selectedValue.value === option.value const handleSelect = (option: IconSelectOption) => { if (option.disabled) return selectedValue.value = selectedValue.value === option.value ? '' : option.value } const getStateClasses = (option: IconSelectOption) => ({ base: 'w-[100px] h-[102px] flex flex-col items-center justify-center rounded-lg border-2 transition-colors cursor-pointer', state: isSelected(option) ? 'bg-titan-purple-500 text-white border-titan-purple-500 shadow-sm' : 'bg-titan-green-800/10 text-titan-green-800 border-titan-green-800/20 hover:bg-titan-green-800/15', disabled: option.disabled ? 'opacity-50 cursor-not-allowed' : '' }) const getOptionAriaAttributes = (option: IconSelectOption) => ({ role: 'radio', 'aria-checked': isSelected(option), 'aria-disabled': option.disabled }) return { args, isSelected, handleSelect, getStateClasses, getOptionAriaAttributes } }, template: ` ` }), args: { options: [ { value: 'buried', label: 'Buried' }, { value: 'cremated', label: 'Cremated' } ], label: 'CHOOSE A DISPOSITION' } } /** * Interactive playground for testing different configurations */ export const Playground: Story = { render: (args) => ({ components: { TitanIconSelectRenderer }, setup() { const selectedValue = ref('') const isSelected = (option: IconSelectOption) => selectedValue.value === option.value const handleSelect = (option: IconSelectOption) => { if (option.disabled || args.disabled) return selectedValue.value = selectedValue.value === option.value ? '' : option.value } const getStateClasses = (option: IconSelectOption) => ({ base: 'w-[100px] h-[102px] flex flex-col items-center justify-center rounded-lg border-2 transition-colors cursor-pointer', state: isSelected(option) ? 'bg-titan-purple-500 text-white border-titan-purple-500 shadow-sm' : 'bg-titan-green-800/10 text-titan-green-800 border-titan-green-800/20 hover:bg-titan-green-800/15', disabled: option.disabled || args.disabled ? 'opacity-50 cursor-not-allowed' : '' }) const getOptionAriaAttributes = (option: IconSelectOption) => ({ role: 'radio', 'aria-checked': isSelected(option), 'aria-disabled': option.disabled || args.disabled }) return { args, isSelected, handleSelect, getStateClasses, getOptionAriaAttributes, selectedValue } }, template: `

Selected: {{ selectedValue || 'None' }}

` }), args: { options: [ { value: 'buried', label: 'Buried' }, { value: 'cremated', label: 'Cremated' }, { value: 'other', label: 'Other' } ], showCheckmark: false, label: 'CHOOSE A DISPOSITION', disabled: false, error: false, errorMessage: '' } }