Skip to content

Commit

Permalink
fix(forms): add support for disabled states
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Dec 6, 2023
1 parent 0f4d7bc commit e8d301c
Show file tree
Hide file tree
Showing 13 changed files with 242 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ showTabs: true
| `vertical` | _(optional)_ if set to `true`, will do the same as `label_direction` when set to **vertical**. |
| `size` | _(optional)_ define one of the following [heading size](/uilib/elements/heading/): `medium` or `large`. |
| `skeleton` | _(optional)_ if set to `true`, an overlaying skeleton with animation will be shown. |
| `disabled` | _(optional)_ if set to `true`, the label will behave as not interactive. |
| `element` | _(optional)_ defines the HTML element used. Defaults to `label`. |
| `innerRef` | _(optional)_ attach a React Ref to the inner label `element`. |
| [Space](/uilib/layout/space/properties) | _(optional)_ spacing properties like `top` or `bottom` are supported. |
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ showTabs: true
| `contentsWidth` | `string` or `false` | _(optional)_ `small`, `medium`, `large`, `stretch` or `false` for predefined standard widths. |
| `size` | `string` or `false` | _(optional)_ define one of the following [heading size](/uilib/elements/heading/): `medium` or `large`. |
| `asFieldset` | `boolean` | _(optional)_ use `true` when you have several form elements. This way a `fieldset` with a `legend` is used. |
| `disabled` | `boolean` | _(optional)_ set `true` to make the inner [FormLabel](/uilib/components/form-label/) behave as disabled. |
| `FieldProps` such as [Value.String-properties](/uilib/extensions/forms/create-component/Value/String/properties) | Various | _(optional)_ `FieldProps` properties. |
4 changes: 1 addition & 3 deletions packages/dnb-eufemia/src/components/form-label/FormLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,12 @@ export type FormLabelProps = {
size?: 'basis' | 'medium' | 'large'
id?: string
skeleton?: boolean
disabled?: boolean
label?: React.ReactNode
vertical?: boolean
srOnly?: boolean
innerRef?: React.RefObject<HTMLElement>

/** Is not a part of HTMLLabelElement and not documented as of now */
disabled?: boolean

/** @deprecated use forId instead */
for_id?: string
/** @deprecated use srOnly instead */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ function NumberComponent(props: Props) {
info={info}
warning={warning}
error={error}
disabled={disabled}
width={width === 'stretch' ? width : undefined}
contentsWidth={width !== false ? width : undefined}
{...pickSpacingProps(props)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ describe('Field.Number', () => {
expect(screen.getByLabelText('Number label')).toBeInTheDocument()
})

it('should support disabled prop', () => {
const { rerender } = render(
<Field.Number label="Disabled label" disabled />
)

const labelElement = () => document.querySelector('label')

expect(labelElement()).toHaveAttribute('disabled')

rerender(<Field.Number label="Disabled label" />)

expect(labelElement()).not.toHaveAttribute('disabled')
})

it('renders autoComplete', () => {
const { rerender } = render(
<Field.Number autoComplete="postalCode" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ function PhoneNumber(props: Props) {
info={info}
warning={warning}
error={error}
disabled={disabled}
{...pickSpacingProps(props)}
>
<Flex.Horizontal align="baseline">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ describe('Field.PhoneNumber', () => {
expect(selectedItemElement.textContent).toBe('+47 Norge')
})

it('should support disabled prop', () => {
const { rerender } = render(
<PhoneNumber label="Disabled label" disabled />
)

const labelElement = () => document.querySelector('label')

expect(labelElement()).toHaveAttribute('disabled')

rerender(<PhoneNumber label="Disabled label" />)

expect(labelElement()).not.toHaveAttribute('disabled')
})

it('should change locale', () => {
const { rerender } = render(
<Provider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ function StringComponent(props: Props) {
labelSecondary={labelSecondary ?? characterCounterElement}
info={info}
warning={warning}
disabled={disabled}
error={error}
width={width === 'stretch' ? width : undefined}
contentsWidth={width !== false ? width : undefined}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ describe('Field.String', () => {
).toBeInTheDocument()
})

it('renders label', () => {
render(<Field.String label="The label" />)
expect(screen.getByLabelText('The label')).toBeInTheDocument()
})

it('does not render placeholder when value is given', () => {
render(
<Field.String value="value-text" placeholder="placeholder-text" />
Expand All @@ -50,9 +55,18 @@ describe('Field.String', () => {
).not.toBeInTheDocument()
})

it('renders label', () => {
render(<Field.String label="The label" />)
expect(screen.getByLabelText('The label')).toBeInTheDocument()
it('should support disabled prop', () => {
const { rerender } = render(
<Field.String label="Disabled label" disabled />
)

const labelElement = () => document.querySelector('label')

expect(labelElement()).toHaveAttribute('disabled')

rerender(<Field.String label="Disabled label" />)

expect(labelElement()).not.toHaveAttribute('disabled')
})

it('input is connected to label', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ function Toggle(props: Props) {
info,
warning,
error,
disabled,
}

const fieldBlockProps = {
Expand All @@ -69,6 +70,7 @@ function Toggle(props: Props) {
label,
labelDescription,
labelSecondary,
disabled,
}

const isOn = value === valueOn
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,178 @@
import React from 'react'
import { render } from '@testing-library/react'
import Toggle, { Props } from '..'
import { fireEvent, render } from '@testing-library/react'
import Toggle, { Props } from '../Toggle'

describe('Field.Toggle', () => {
it('should render with props', () => {
const props: Props = { valueOn: 'checked', valueOff: 'unchecked' }
render(<Toggle {...props} />)
})

it('should support disabled prop', () => {
const { rerender } = render(
<Toggle
valueOn="checked"
valueOff="unchecked"
label="Disabled label"
disabled
/>
)

const labelElement = () => document.querySelector('label')

expect(labelElement()).toHaveAttribute('disabled')

rerender(
<Toggle
valueOn="checked"
valueOff="unchecked"
label="Disabled label"
/>
)

expect(labelElement()).not.toHaveAttribute('disabled')
})

describe('variants', () => {
describe('button', () => {
it('should render correct HTML', () => {
const onChange = jest.fn()

render(
<Toggle
valueOn="on"
valueOff="off"
variant="button"
value="on"
onChange={onChange}
/>
)

const element = document.querySelector(
'.dnb-toggle-button__button'
)

expect(element).toBeInTheDocument()
expect(element).toHaveAttribute('aria-pressed', 'true')

fireEvent.click(element)

expect(element).toHaveAttribute('aria-pressed', 'false')
expect(onChange).toHaveBeenCalledTimes(1)
expect(onChange).toHaveBeenLastCalledWith('off')

fireEvent.click(element)

expect(element).toHaveAttribute('aria-pressed', 'true')
expect(onChange).toHaveBeenCalledTimes(2)
expect(onChange).toHaveBeenLastCalledWith('on')
})
})

describe('buttons', () => {
it('should render correct HTML', () => {
const onChange = jest.fn()

render(
<Toggle
valueOn="on"
valueOff="off"
variant="buttons"
value="on"
onChange={onChange}
/>
)

const [yesElement, noElement]: Array<HTMLButtonElement> =
Array.from(
document.querySelectorAll('.dnb-toggle-button__button')
)

expect(yesElement).toHaveAttribute('aria-pressed', 'true')
expect(noElement).toHaveAttribute('aria-pressed', 'false')

fireEvent.click(noElement)

expect(yesElement).toHaveAttribute('aria-pressed', 'false')
expect(noElement).toHaveAttribute('aria-pressed', 'true')
expect(onChange).toHaveBeenCalledTimes(1)
expect(onChange).toHaveBeenLastCalledWith('off')

fireEvent.click(yesElement)

expect(yesElement).toHaveAttribute('aria-pressed', 'true')
expect(noElement).toHaveAttribute('aria-pressed', 'false')
expect(onChange).toHaveBeenCalledTimes(2)
expect(onChange).toHaveBeenLastCalledWith('on')
})
})

describe('checkbox-button', () => {
it('should render correct HTML', () => {
const onChange = jest.fn()

render(
<Toggle
valueOn="on"
valueOff="off"
variant="checkbox-button"
value="on"
onChange={onChange}
/>
)

const element = document.querySelector(
'.dnb-toggle-button__button .dnb-checkbox__input'
)

expect(element).toBeInTheDocument()
expect(element).toHaveAttribute('data-checked', 'true')

fireEvent.click(element)

expect(element).toHaveAttribute('data-checked', 'false')
expect(onChange).toHaveBeenCalledTimes(1)
expect(onChange).toHaveBeenLastCalledWith('off')

fireEvent.click(element)

expect(element).toHaveAttribute('data-checked', 'true')
expect(onChange).toHaveBeenCalledTimes(2)
expect(onChange).toHaveBeenLastCalledWith('on')
})
})

describe('checkbox', () => {
it('should render correct HTML', () => {
const onChange = jest.fn()

render(
<Toggle
valueOn="on"
valueOff="off"
variant="checkbox"
value="on"
onChange={onChange}
/>
)

const element = document.querySelector('.dnb-checkbox__input')

expect(element).toBeInTheDocument()
expect(element).toBeChecked()

fireEvent.click(element)

expect(element).not.toBeChecked()
expect(onChange).toHaveBeenCalledTimes(1)
expect(onChange).toHaveBeenLastCalledWith('off')

fireEvent.click(element)

expect(element).toBeChecked()
expect(onChange).toHaveBeenCalledTimes(2)
expect(onChange).toHaveBeenLastCalledWith('on')
})
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export type Props = Pick<
| 'info'
| 'warning'
| 'error'
| 'disabled'
> & {
forId?: string
contentClassName?: string
Expand Down Expand Up @@ -43,6 +44,7 @@ function FieldBlock(props: Props) {
info,
warning,
error: errorProp,
disabled,
width,
contentsWidth,
size,
Expand Down Expand Up @@ -151,6 +153,7 @@ function FieldBlock(props: Props) {
forId={enableFieldset ? undefined : forId}
space={{ top: 0, bottom: 'x-small' }}
size={size}
disabled={disabled}
>
{children}
</FormLabel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@ describe('FieldBlock', () => {
expect(element.classList).toContain('dnb-space__top--x-large')
})

it('should support disabled prop', () => {
const { rerender } = render(
<FieldBlock label="Disabled label" disabled>
content
</FieldBlock>
)

const labelElement = () => document.querySelector('label')

expect(labelElement()).toHaveAttribute('disabled')

rerender(<FieldBlock label="Disabled label">content</FieldBlock>)

expect(labelElement()).not.toHaveAttribute('disabled')
})

it('should support heading size prop', () => {
const { rerender } = render(
<FieldBlock label="Label" size="medium">
Expand Down

0 comments on commit e8d301c

Please sign in to comment.