Merged in feat/SW-3655-input-component (pull request #3296)
feat: (SW-3655) new Input and FormInput components * First version new Input and FormInput components * Handle aria-describedby with react-aria instead of manually add it * Update breaking unit and stories tests * Merge branch 'master' into feat/SW-3655-input-component * Update example form * Merge branch 'master' into feat/SW-3655-input-component * New lock file Approved-by: Linus Flood
This commit is contained in:
416
packages/design-system/lib/components/InputNew/Input.stories.tsx
Normal file
416
packages/design-system/lib/components/InputNew/Input.stories.tsx
Normal file
@@ -0,0 +1,416 @@
|
||||
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<typeof Input> = {
|
||||
title: 'Components/Input (New)',
|
||||
// @ts-expect-error Input does not support this, but wrapping <TextField> does
|
||||
component: ({ isInvalid, validationState, ...props }) => (
|
||||
<TextField isInvalid={isInvalid} data-validation-state={validationState}>
|
||||
<Input {...props} data-validation-state={validationState} />
|
||||
</TextField>
|
||||
),
|
||||
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<typeof Input>
|
||||
|
||||
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: <MaterialIcon icon="sell" />,
|
||||
rightIcon: <MaterialIcon icon="lock" />,
|
||||
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: <MaterialIcon icon="email" />,
|
||||
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: <MaterialIcon icon="person" />,
|
||||
rightIcon: <MaterialIcon icon="email" />,
|
||||
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 <TextField> 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 <TextField> 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 <TextField> 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 <TextField> 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 <TextField> 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 <TextField> 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 <TextField> 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 <TextField> 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()
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user