import type { Meta, StoryObj } from '@storybook/vue3'; import { ref } from 'vue'; import TitanFormSection from './TitanFormSection.vue'; const meta = { component: TitanFormSection, title: 'Layout/TitanFormSection', tags: ['autodocs'], argTypes: { schema: { control: 'object', description: 'Array of form schema elements defining the form structure', table: { type: { summary: 'FormSchemaElement[]' }, }, }, modelValue: { control: 'object', description: 'Form data object (v-model)', table: { type: { summary: 'Record' }, }, }, 'onUpdate:modelValue': { action: 'update:modelValue', description: 'Emitted when form data changes', }, }, } satisfies Meta; export default meta; type Story = StoryObj; /** * Simple form with just text inputs. * Demonstrates basic schema-based form rendering with TitanInput components. */ export const SimpleForm: Story = { render: (args) => ({ components: { TitanFormSection }, setup() { const formData = ref({ firstName: '', lastName: '', email: '', }); const schema = [ { component: 'TitanInput', props: { label: 'First Name', type: 'text', required: true }, model: 'firstName', }, { component: 'TitanInput', props: { label: 'Last Name', type: 'text', required: true }, model: 'lastName', }, { component: 'TitanInput', props: { label: 'Email', type: 'email', required: true }, model: 'email', }, ]; return { args, formData, schema }; }, template: `

Form Data:

{{ JSON.stringify(formData, null, 2) }}
`, }), }; /** * Complex form with mixed components including subheaders and textareas. * This pattern is used for multi-section forms like obituary details. */ export const ComplexForm: Story = { render: (args) => ({ components: { TitanFormSection }, setup() { const formData = ref({ paradeElements: '', colors: '', additionalNotes: '', }); const schema = [ { component: 'TitanSubheader', props: { text: 'What are you envisioning for the parade elements?' }, }, { component: 'TitanTextarea', props: { label: 'Notes', rows: 3 }, model: 'paradeElements', }, { component: 'TitanSubheader', props: { text: 'Any particular colors you would like represented?' }, }, { component: 'TitanTextarea', props: { label: 'Notes', rows: 3 }, model: 'colors', }, { component: 'TitanSubheader', props: { text: 'Additional notes or special requests' }, }, { component: 'TitanTextarea', props: { label: 'Notes', rows: 4, maxlength: 500 }, model: 'additionalNotes', }, ]; return { args, formData, schema }; }, template: `

Form Data:

{{ JSON.stringify(formData, null, 2) }}
`, }), }; /** * Form with validation errors. * Shows how error states are passed through the schema to components. */ export const WithValidationErrors: Story = { render: (args) => ({ components: { TitanFormSection }, setup() { const formData = ref({ email: '', password: '', }); const schema = [ { component: 'TitanInput', props: { label: 'Email', type: 'email', required: true, error: true, errorMessage: 'Please enter a valid email address', }, model: 'email', }, { component: 'TitanInput', props: { label: 'Password', type: 'password', required: true, error: true, errorMessage: 'Password must be at least 8 characters', }, model: 'password', }, ]; return { args, formData, schema }; }, template: `
`, }), }; /** * Form with mixed component types. * Demonstrates TitanInput, TitanTextarea, TitanSelect, and TitanDatePicker. */ export const MixedComponents: Story = { render: (args) => ({ components: { TitanFormSection }, setup() { const formData = ref({ name: '', birthdate: '', relationship: '', biography: '', }); const schema = [ { component: 'TitanSubheader', props: { text: 'Personal Information' }, }, { component: 'TitanInput', props: { label: 'Full Name', type: 'text', required: true }, model: 'name', }, { component: 'TitanDatePicker', props: { label: 'Date of Birth', required: true }, model: 'birthdate', }, { component: 'TitanSelect', props: { label: 'Relationship', options: ['Spouse', 'Parent', 'Child', 'Sibling', 'Friend', 'Other'], }, model: 'relationship', }, { component: 'TitanSubheader', props: { text: 'Biography' }, }, { component: 'TitanTextarea', props: { label: 'Life Story', rows: 6, maxlength: 1000 }, model: 'biography', }, ]; return { args, formData, schema }; }, template: `

Form Data:

{{ JSON.stringify(formData, null, 2) }}
`, }), }; /** * Empty schema handling. * Tests graceful handling when no schema is provided. */ export const EmptySchema: Story = { render: (args) => ({ components: { TitanFormSection }, setup() { const formData = ref({}); const schema = []; return { args, formData, schema }; }, template: `

No schema provided - form section should handle this gracefully.

`, }), }; /** * Form with pre-filled data. * Demonstrates how to initialize the form with existing values. */ export const WithInitialData: Story = { render: (args) => ({ components: { TitanFormSection }, setup() { const formData = ref({ name: 'John Doe', email: 'john.doe@example.com', phone: '555-1234', notes: 'Some existing notes about the person.', }); const schema = [ { component: 'TitanInput', props: { label: 'Name', type: 'text' }, model: 'name', }, { component: 'TitanInput', props: { label: 'Email', type: 'email' }, model: 'email', }, { component: 'TitanInput', props: { label: 'Phone', type: 'tel' }, model: 'phone', }, { component: 'TitanTextarea', props: { label: 'Notes', rows: 4 }, model: 'notes', }, ]; return { args, formData, schema }; }, template: `

Form Data:

{{ JSON.stringify(formData, null, 2) }}
`, }), }; /** * Within a TitanCard context. * Shows real-world usage pattern where forms are rendered inside cards. */ export const InCardContext: Story = { render: (args) => ({ components: { TitanFormSection }, setup() { const formData = ref({ paradeElements: '', colors: '', }); const schema = [ { component: 'TitanSubheader', props: { text: 'What are you envisioning for the parade elements?' }, }, { component: 'TitanTextarea', props: { label: 'Notes', rows: 3 }, model: 'paradeElements', }, { component: 'TitanSubheader', props: { text: 'Any particular colors you would like represented?' }, }, { component: 'TitanTextarea', props: { label: 'Notes', rows: 3 }, model: 'colors', }, ]; return { args, formData, schema }; }, template: `

Obituary Details

`, }), }; /** * Interactive playground for testing schema configurations. */ export const Playground: Story = { render: (args) => ({ components: { TitanFormSection }, setup() { const formData = ref({ field1: '', field2: '', }); const schema = args.schema || [ { component: 'TitanInput', props: { label: 'Field 1', type: 'text' }, model: 'field1', }, { component: 'TitanInput', props: { label: 'Field 2', type: 'text' }, model: 'field2', }, ]; return { args, formData, schema }; }, template: `

Form Data:

{{ JSON.stringify(formData, null, 2) }}
`, }), args: { schema: [ { component: 'TitanInput', props: { label: 'Field 1', type: 'text' }, model: 'field1', }, { component: 'TitanInput', props: { label: 'Field 2', type: 'text' }, model: 'field2', }, ], }, };