import type { Meta, StoryObj } from '@storybook/nextjs-vite' import { expect } from 'storybook/test' import { Input } from './Input' import { TextField } from 'react-aria-components' import { MaterialIcon } from '../Icons/MaterialIcon' const meta: Meta = { title: 'Core Components/Input (New)', // @ts-expect-error Input does not support this, but wrapping does component: ({ isInvalid, validationState, ...props }) => ( ), argTypes: { label: { control: 'text', description: 'The label text displayed for the input field', table: { type: { summary: 'string' }, }, }, labelPosition: { control: 'select', options: ['floating', 'top'], description: 'Position of the label relative to the input', table: { type: { summary: "'floating' | 'top'" }, defaultValue: { summary: "'floating'" }, }, }, placeholder: { control: 'text', description: 'Placeholder text shown when input is empty', table: { type: { summary: 'string' }, defaultValue: { summary: 'undefined' }, }, }, required: { control: 'boolean', description: 'Whether the input is required', table: { type: { summary: 'boolean' }, defaultValue: { summary: 'false' }, }, }, disabled: { control: 'boolean', description: 'Whether the input is disabled', table: { type: { summary: 'boolean' }, defaultValue: { summary: 'false' }, }, }, showClearContentIcon: { control: 'boolean', description: 'Whether the clear content icon is shown', table: { type: { summary: 'boolean' }, defaultValue: { summary: 'false' }, }, }, }, } export default meta type Story = StoryObj export const Default: Story = { args: { label: 'Label', name: 'foo', required: false, }, play: async ({ canvas, userEvent }) => { const textbox = canvas.getByRole('textbox') expect(textbox).not.toBeDisabled() expect(textbox).toHaveValue('') await userEvent.type(textbox, 'Hello World') expect(textbox).toHaveValue('Hello World') await userEvent.clear(textbox) expect(textbox).toHaveValue('') }, } export const WithIconsFloatingLabel: Story = { args: { label: 'Label', name: 'foo', value: 'Value', leftIcon: , rightIcon: , showClearContentIcon: true, }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('Value') expect(textbox).not.toBeDisabled() }, } export const WithIconsTopLabel: Story = { args: { label: 'Label', name: 'foo', value: 'Value', labelPosition: 'top', leftIcon: , showClearContentIcon: true, }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('Value') expect(textbox).not.toBeDisabled() }, } export const WithIconsAndClearIconTopLabel: Story = { args: { label: 'Label', name: 'foo', value: 'Value', labelPosition: 'top', leftIcon: , rightIcon: , showClearContentIcon: true, }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('Value') expect(textbox).not.toBeDisabled() }, } export const Filled: Story = { args: { label: 'Label', name: 'foo', value: 'Value', }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('Value') expect(textbox).not.toBeDisabled() }, } export const Error: Story = { args: { label: 'Label', name: 'foo', // @ts-expect-error Input does not support this, but wrapping does isInvalid: true, }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveAttribute('aria-invalid', 'true') expect(textbox).not.toBeDisabled() }, } export const ErrorFilled: Story = { args: { label: 'Label', name: 'foo', // @ts-expect-error Input does not support this, but wrapping does isInvalid: true, value: 'Value', }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('Value') expect(textbox).toHaveAttribute('aria-invalid', 'true') expect(textbox).not.toBeDisabled() }, } export const Disabled: Story = { args: { label: 'Label', name: 'foo', disabled: true, }, play: async ({ canvas, userEvent }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('') expect(textbox).toBeDisabled() await userEvent.type(textbox, 'Hello World') expect(textbox).toHaveValue('') }, } export const DisabledFilled: Story = { args: { label: 'Label', name: 'foo', disabled: true, value: 'Value', }, play: async ({ canvas, userEvent }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('Value') expect(textbox).toBeDisabled() await userEvent.type(textbox, 'Hello World') expect(textbox).toHaveValue('Value') }, } export const WarningDefault: Story = { args: { label: 'Label', name: 'foo', // @ts-expect-error Input does not support this, but wrapping does validationState: 'warning', }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') // data-validation-state is on the parent label element, not the input const container = textbox.closest('[data-validation-state]') expect(container?.getAttribute('data-validation-state')).toBe('warning') expect(textbox).not.toBeDisabled() }, } export const WarningFilled: Story = { args: { label: 'Label', name: 'foo', // @ts-expect-error Input does not support this, but wrapping does validationState: 'warning', value: 'Value', }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('Value') // data-validation-state is on the parent label element, not the input const container = textbox.closest('[data-validation-state]') expect(container?.getAttribute('data-validation-state')).toBe('warning') expect(textbox).not.toBeDisabled() }, } export const DefaultTop: Story = { args: { label: 'Label', placeholder: 'Label', name: 'foo', required: false, labelPosition: 'top', }, play: async ({ canvas, userEvent }) => { const textbox = canvas.getByRole('textbox') expect(textbox).not.toBeDisabled() expect(textbox).toHaveValue('') await userEvent.type(textbox, 'Hello World') expect(textbox).toHaveValue('Hello World') await userEvent.clear(textbox) expect(textbox).toHaveValue('') }, } export const FilledTop: Story = { args: { label: 'Label', name: 'foo', value: 'Value', labelPosition: 'top', }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('Value') expect(textbox).not.toBeDisabled() }, } export const ErrorTop: Story = { args: { label: 'Label', name: 'foo', // @ts-expect-error Input does not support this, but wrapping does isInvalid: true, placeholder: 'Label', labelPosition: 'top', }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveAttribute('aria-invalid', 'true') expect(textbox).not.toBeDisabled() }, } export const ErrorFilledTop: Story = { args: { label: 'Label', name: 'foo', // @ts-expect-error Input does not support this, but wrapping does isInvalid: true, value: 'Value', labelPosition: 'top', }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('Value') expect(textbox).toHaveAttribute('aria-invalid', 'true') expect(textbox).not.toBeDisabled() }, } export const DisabledTop: Story = { args: { label: 'Label', name: 'foo', disabled: true, labelPosition: 'top', placeholder: 'Label', }, play: async ({ canvas, userEvent }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('') expect(textbox).toBeDisabled() await userEvent.type(textbox, 'Hello World') expect(textbox).toHaveValue('') }, } export const DisabledFilledTop: Story = { args: { label: 'Label', name: 'foo', disabled: true, value: 'Value', labelPosition: 'top', }, play: async ({ canvas, userEvent }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('Value') expect(textbox).toBeDisabled() await userEvent.type(textbox, 'Hello World') expect(textbox).toHaveValue('Value') }, } export const WarningDefaultTop: Story = { args: { label: 'Label', name: 'foo', // @ts-expect-error Input does not support this, but wrapping does validationState: 'warning', labelPosition: 'top', placeholder: 'Label', }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') // data-validation-state is on the parent label element, not the input const container = textbox.closest('[data-validation-state]') expect(container?.getAttribute('data-validation-state')).toBe('warning') expect(textbox).not.toBeDisabled() }, } export const WarningFilledTop: Story = { args: { label: 'Label', name: 'foo', // @ts-expect-error Input does not support this, but wrapping does validationState: 'warning', value: 'Value', labelPosition: 'top', }, play: async ({ canvas }) => { const textbox = canvas.getByRole('textbox') expect(textbox).toHaveValue('Value') // data-validation-state is on the parent label element, not the input const container = textbox.closest('[data-validation-state]') expect(container?.getAttribute('data-validation-state')).toBe('warning') expect(textbox).not.toBeDisabled() }, }