import type { Meta, StoryObj } from '@storybook/vue3-vite' import { ref } from 'vue' import CpRadioGroup from '@/components/CpRadioGroup.vue' const radioGroupSizes = ['md', 'lg'] as const const radioGroupDirections = ['vertical', 'horizontal'] as const const meta = { title: 'Molecules/CpRadioGroup', component: CpRadioGroup, argTypes: { modelValue: { control: 'text', description: 'The selected radio value', }, options: { control: 'object', description: 'Array of radio options', }, groupName: { control: 'text', description: 'Name attribute for radio group', }, autofocus: { control: 'boolean', description: 'Whether to autofocus the first radio', }, direction: { control: 'select', options: radioGroupDirections, description: 'Stack options vertically or place them in a row', }, groupLabel: { control: 'text', description: 'Visible label for the whole radio group', }, groupHelperText: { control: 'text', description: 'Helper text shown below the group label', }, required: { control: 'boolean', description: 'When true, shows a required indicator on the group label (if set) or on each option', }, size: { control: 'select', options: radioGroupSizes, description: 'The size of the radio', }, }, } satisfies Meta export default meta type Story = StoryObj const sampleOptions = [ { value: 'option1', label: 'Option 1' }, { value: 'option2', label: 'Option 2', helperText: 'This is a helper text' }, { value: 'option3', label: 'Option 3' }, ] const wrappedRender = (args: { modelValue?: string }) => ({ components: { CpRadioGroup }, setup() { const value = ref(args.modelValue) return { args, value } }, template: `
`, }) /** * Default radio group, stacked vertically. Use the controls to experiment * with each prop in isolation. */ export const Default: Story = { args: { modelValue: 'option1', options: sampleOptions, groupName: 'radio-group', autofocus: false, required: false, groupLabel: '', groupHelperText: '', direction: 'vertical', size: 'md', }, render: (args) => ({ components: { CpRadioGroup }, setup() { const value = ref(args.modelValue) return { args, value } }, template: `

modelValue: {{ value }}

`, }), } /** * Arrange the options on a single row with `direction="horizontal"`. */ export const Horizontal: Story = { args: { ...Default.args, direction: 'horizontal', }, } /** * Add a visible label and helper text describing the whole group. Setting * `required` puts the asterisk on the group label. */ export const WithGroupLabel: Story = { args: { ...Default.args, groupLabel: 'Billing frequency', groupHelperText: 'You can change this later in your account settings.', required: true, }, } /** * Attach a `helperText` to individual options — useful for short * explanations next to each choice. */ export const WithHelperText: Story = { args: { ...Default.args, options: [ { value: 'option1', label: 'Basic Plan', helperText: 'Perfect for individuals' }, { value: 'option2', label: 'Pro Plan', helperText: 'Great for small teams' }, { value: 'option3', label: 'Enterprise Plan', helperText: 'For large organizations' }, ], }, } /** * Disable individual options; the rest of the group stays selectable. */ export const WithDisabledOption: Story = { args: { ...Default.args, options: [ { value: 'option1', label: 'Option 1' }, { value: 'option2', label: 'Option 2', disabled: true }, { value: 'option3', label: 'Option 3' }, ], }, render: wrappedRender, } /** * A disabled option can still be the current value. Use this pattern for * read-only pre-selections. */ export const CheckedDisabled: Story = { args: { ...Default.args, options: [ { value: 'option1', label: 'Option 1', disabled: true }, { value: 'option2', label: 'Option 2' }, { value: 'option3', label: 'Option 3' }, ], modelValue: 'option1', }, render: wrappedRender, }