import { useState } from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { MagnifyingGlassIcon } from '@heroicons/react/24/solid'; import { InputField } from './InputField'; const meta = { title: 'Components/InputField', component: InputField, tags: ['autodocs'], parameters: { docs: { description: { component: 'Text input field with optional label, validation state, size/layout variants, and password visibility toggle.', }, }, }, argTypes: { label: { description: 'Label text shown above (stacked) or on the left (inline).', control: 'text', table: { type: { summary: 'string' } }, }, placeholder: { description: 'Input placeholder text.', control: 'text', table: { type: { summary: 'string' } }, }, type: { description: 'Native input type.', options: ['text', 'password', 'email'], control: 'inline-radio', table: { type: { summary: "'text' | 'password' | 'email'" } }, }, size: { description: 'Input size.', options: ['sm', 'md', 'lg', 'full'], control: 'inline-radio', table: { type: { summary: "'sm' | 'md' | 'lg' | 'full'" } }, }, width: { description: 'Input width constraint.', options: ['sm', 'md', 'lg', 'full'], control: 'inline-radio', table: { type: { summary: "'sm' | 'md' | 'lg' | 'full'" } }, }, layout: { description: 'Label/input layout mode.', options: ['stacked', 'inline'], control: 'inline-radio', table: { type: { summary: "'stacked' | 'inline'" } }, }, value: { description: 'Controlled input value.', control: 'text', table: { type: { summary: 'string' } }, }, name: { description: 'Native input `name` attribute.', control: 'text', table: { type: { summary: 'string' } }, }, disabled: { description: 'Disables the input.', control: 'boolean', table: { type: { summary: 'boolean' } }, }, required: { description: 'Sets the native HTML `required` attribute.', control: 'boolean', table: { type: { summary: 'boolean' } }, }, error: { description: 'Validation message shown below the field.', control: 'text', table: { type: { summary: 'string' } }, }, rightIcon: { description: 'Optional trailing icon node (ignored for password type because toggle icon is used).', control: false, table: { type: { summary: 'ReactNode' } }, }, className: { description: 'Extra CSS classes for the outer wrapper.', control: 'text', table: { type: { summary: 'string' } }, }, inputClassName: { description: 'Extra CSS classes for the `` element.', control: 'text', table: { type: { summary: 'string' } }, }, onChange: { description: 'Change handler callback.', action: 'changed', table: { type: { summary: 'ChangeEventHandler' } }, }, onBlur: { description: 'Blur handler callback.', control: false, table: { type: { summary: 'FocusEventHandler' } }, }, inputRef: { description: 'Ref forwarded to the native `` element.', control: false, table: { type: { summary: 'Ref' } }, }, }, args: { label: 'Email', type: 'email', placeholder: 'name@example.com', value: '', size: 'md', width: 'md', layout: 'stacked', }, } satisfies Meta; export default meta; type Story = StoryObj; export const Text: Story = { args: { type: 'text', label: 'Title', placeholder: 'Write a title', }, render: function TextRender(args) { const [value, setValue] = useState('Storybook integration'); return ( { setValue(event.target.value); args.onChange?.(event); }} /> ); }, }; export const PasswordWithToggle: Story = { args: { type: 'password', label: 'Password', placeholder: 'Type a strong password', }, render: function PasswordWithToggleRender(args) { const [value, setValue] = useState('pa55word'); return ( { setValue(event.target.value); args.onChange?.(event); }} /> ); }, }; export const InlineWithIcon: Story = { args: { type: 'text', label: 'Search', layout: 'inline', size: 'sm', rightIcon: , }, render: function InlineWithIconRender(args) { const [value, setValue] = useState('posts'); return ( { setValue(event.target.value); args.onChange?.(event); }} /> ); }, }; export const ErrorState: Story = { name: 'Error', args: { type: 'email', label: 'Email', value: 'invalid.mail', error: 'Enter a valid email address', }, }; export const Disabled: Story = { args: { type: 'text', label: 'Read only field', value: 'Locked content', disabled: true, }, }; export const SizeMatrix: Story = { args: { type: 'text', label: 'Name', placeholder: 'Enter value', }, render: function SizeMatrixRender(args) { const [value, setValue] = useState('Beatrice'); return (
setValue(event.target.value)} /> setValue(event.target.value)} /> setValue(event.target.value)} /> setValue(event.target.value)} />
); }, };