Skip to content

Commit

Permalink
RadioControl: Convert component to TypeScript (#41568)
Browse files Browse the repository at this point in the history
  • Loading branch information
Petter Walbø Johnsgård committed Jun 8, 2022
1 parent 9abede0 commit 2eee3a2
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 133 deletions.
2 changes: 2 additions & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
### Internal

- `FormTokenField`: Convert to TypeScript and refactor to functional component ([#41216](https://github.com/WordPress/gutenberg/pull/41216)).
- `RadioControl`: Convert to TypeScript ([#41568](https://github.com/WordPress/gutenberg/pull/41568)).

## 19.12.0 (2022-06-01)

Expand Down Expand Up @@ -41,6 +42,7 @@
- `Surface`: Convert to TypeScript ([#41212](https://github.com/WordPress/gutenberg/pull/41212)).
- `Autocomplete` updated to satisfy `react/exhuastive-deps` eslint rule ([#41382](https://github.com/WordPress/gutenberg/pull/41382))
- `DateDayPicker` updated to satisfy `react/exhuastive-deps` eslint rule ([#41470](https://github.com/WordPress/gutenberg/pull/41470)).

### Experimental

- `Spacer`: Add RTL support. ([#41172](https://github.com/WordPress/gutenberg/pull/41172))
Expand Down
40 changes: 17 additions & 23 deletions packages/components/src/radio-control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,57 +75,51 @@ const MyRadioControl = () => {
onChange={ ( value ) => setOption( value ) }
/>
);
}
};
```

### Props

The component accepts the following props:

### hideLabelFromVision
#### `help`: `string | WPElement`

If true, the label will only be visible to screen readers.
If this property is added, a help text will be generated using help property as the content.

- Type: `Boolean`
- Required: No

#### label
#### `hideLabelFromVision`: `boolean`

If this property is added, a label will be generated using label property as the content.
If true, the label will only be visible to screen readers.

- Type: `String`
- Required: No

#### help
#### `label`: `string`

If this property is added, a help text will be generated using help property as the content.
If this property is added, a label will be generated using label property as the content.

- Type: `String|WPElement`
- Required: No

#### selected
#### `onChange`: `( value: string ) => void`

The value property of the currently selected option.
A function that receives the value of the new option that is being selected as input.

- Type: `Object`
- Required: No
- Required: Yes

#### options
#### `options`: `{ label: string, value: string }[]`

An array of objects containing the following properties:
An array of objects containing the value and label of the options.

- `label`: (string) The label to be shown to the user.
- `value`: (Object) The internal value compared against select and passed to onChange.
- `label`: `string` The label to be shown to the user.
- `value`: `string` The internal value compared against select and passed to onChange.

* Type: `Array`
* Required: No

#### onChange
#### `selected`: `string`

A function that receives the value of the new option that is being selected as input.
The value property of the currently selected option.

- Type: `function`
- Required: Yes
- Required: No

## Related components

Expand Down
69 changes: 0 additions & 69 deletions packages/components/src/radio-control/index.js

This file was deleted.

107 changes: 107 additions & 0 deletions packages/components/src/radio-control/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* External dependencies
*/
import { isEmpty } from 'lodash';
import classnames from 'classnames';
import type { ChangeEvent } from 'react';

/**
* WordPress dependencies
*/
import { useInstanceId } from '@wordpress/compose';

/**
* Internal dependencies
*/
import BaseControl from '../base-control';
import type { WordPressComponentProps } from '../ui/context';
import type { RadioControlProps } from './types';

/**
* Render a user interface to select the user type using radio inputs.
*
* ```jsx
* import { RadioControl } from '@wordpress/components';
* import { useState } from '@wordpress/element';
*
* const MyRadioControl = () => {
* const [ option, setOption ] = useState( 'a' );
*
* return (
* <RadioControl
* label="User type"
* help="The type of the current user"
* selected={ option }
* options={ [
* { label: 'Author', value: 'a' },
* { label: 'Editor', value: 'e' },
* ] }
* onChange={ ( value ) => setOption( value ) }
* />
* );
* };
* ```
*/
export function RadioControl(
// ref is omitted until we have `WordPressComponentPropsWithoutRef` or add
// ref forwarding to RadioControl.
props: Omit<
WordPressComponentProps< RadioControlProps, 'input', false >,
'ref'
>
) {
const {
label,
className,
selected,
help,
onChange,
hideLabelFromVision,
options = [],
...additionalProps
} = props;
const instanceId = useInstanceId( RadioControl );
const id = `inspector-radio-control-${ instanceId }`;
const onChangeValue = ( event: ChangeEvent< HTMLInputElement > ) =>
onChange( event.target.value );

if ( isEmpty( options ) ) {
return null;
}

return (
<BaseControl
label={ label }
id={ id }
hideLabelFromVision={ hideLabelFromVision }
help={ help }
className={ classnames( className, 'components-radio-control' ) }
>
{ options.map( ( option, index ) => (
<div
key={ `${ id }-${ index }` }
className="components-radio-control__option"
>
<input
id={ `${ id }-${ index }` }
className="components-radio-control__input"
type="radio"
name={ id }
value={ option.value }
onChange={ onChangeValue }
checked={ option.value === selected }
aria-describedby={
!! help ? `${ id }__help` : undefined
}
{ ...additionalProps }
/>
<label htmlFor={ `${ id }-${ index }` }>
{ option.label }
</label>
</div>
) ) }
</BaseControl>
);
}

export default RadioControl;
41 changes: 0 additions & 41 deletions packages/components/src/radio-control/stories/index.js

This file was deleted.

72 changes: 72 additions & 0 deletions packages/components/src/radio-control/stories/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* External dependencies
*/
import type { ComponentMeta, ComponentStory } from '@storybook/react';

/**
* WordPress dependencies
*/
import { useState } from '@wordpress/element';

/**
* Internal dependencies
*/
import RadioControl from '..';

const meta: ComponentMeta< typeof RadioControl > = {
component: RadioControl,
title: 'Components/RadioControl',
argTypes: {
onChange: {
action: 'onChange',
},
selected: {
control: { type: null },
},
label: {
control: { type: 'text' },
},
help: {
control: { type: 'text' },
},
},
parameters: {
controls: {
expanded: true,
},
docs: { source: { state: 'open' } },
},
};
export default meta;

const Template: ComponentStory< typeof RadioControl > = ( {
onChange,
options,
...args
} ) => {
const [ value, setValue ] = useState( options?.[ 0 ]?.value );

return (
<RadioControl
{ ...args }
selected={ value }
options={ options }
onChange={ ( v ) => {
setValue( v );
onChange( v );
} }
/>
);
};

export const Default: ComponentStory< typeof RadioControl > = Template.bind(
{}
);
Default.args = {
label: 'Post visibility',
options: [
{ label: 'Public', value: 'public' },
{ label: 'Private', value: 'private' },
{ label: 'Password Protected', value: 'password' },
],
};
Loading

0 comments on commit 2eee3a2

Please sign in to comment.