import { useState } from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { CalendarDaysIcon } from '@heroicons/react/24/solid'; import { DatePicker } from './DatePicker'; const meta = { title: 'Components/DatePicker', component: DatePicker, tags: ['autodocs'], parameters: { docs: { description: { component: 'In-house date/time selection field with InputField-compatible API. Uses a custom popup (not native browser pickers) and supports date, time, and date-time modes.', }, }, }, 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: 'DatePicker mode.', options: ['date', 'date-time', 'time'], control: 'inline-radio', table: { type: { summary: "'date' | 'date-time' | 'time'" } }, }, 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' } }, }, format: { description: 'Optional input/output format. Supported tokens: `dd`, `mm`, `yyyy`, `HH` (for example `dd/mm/yyyy HH:mm`).', control: 'text', table: { type: { summary: 'string' } }, }, min: { description: 'Optional minimum value in the same format as `value`.', control: 'text', table: { type: { summary: 'string' } }, }, max: { description: 'Optional maximum value in the same format as `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.', 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: 'Schedule at', type: 'date-time', value: '', size: 'md', width: 'md', layout: 'stacked', }, } satisfies Meta; export default meta; type Story = StoryObj; export const DateOnly: Story = { args: { type: 'date', label: 'Publish date', }, render: function DateOnlyRender(args) { const [value, setValue] = useState('2031/05/20'); return ( { setValue(event.target.value); args.onChange?.(event); }} /> ); }, }; export const DateTime: Story = { args: { type: 'date-time', label: 'Schedule at', }, render: function DateTimeRender(args) { const [value, setValue] = useState('2031/05/20 14:30'); return ( { setValue(event.target.value); args.onChange?.(event); }} /> ); }, }; export const TimeOnlyInline: Story = { args: { type: 'time', label: 'Start time', layout: 'inline', size: 'sm', rightIcon: , }, render: function TimeOnlyInlineRender(args) { const [value, setValue] = useState('09:00'); return ( { setValue(event.target.value); args.onChange?.(event); }} /> ); }, }; export const ErrorState: Story = { name: 'Error', args: { type: 'date-time', label: 'Schedule at', value: '', error: 'Pick a valid future date and time', }, }; export const Disabled: Story = { args: { type: 'date-time', label: 'Published at', value: '2031/05/20 14:30', disabled: true, }, }; export const SizeMatrix: Story = { args: { type: 'date-time', label: 'Schedule at', }, render: function SizeMatrixRender(args) { const [value, setValue] = useState('2031/05/20 14:30'); return (
setValue(event.target.value)} /> setValue(event.target.value)} /> setValue(event.target.value)} /> setValue(event.target.value)} />
); }, }; export const CustomFormatWithRange: Story = { args: { type: 'date-time', label: 'Starts at', format: 'dd/mm/yyyy HH:mm', min: '10/03/2026 09:00', max: '24/03/2026 18:30', }, render: function CustomFormatWithRangeRender(args) { const [value, setValue] = useState('22/03/2026 14:30'); return ( { setValue(event.target.value); args.onChange?.(event); }} /> ); }, };