Skip to content
34 changes: 32 additions & 2 deletions packages/components/src/select-control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Position the label centered over the select, or right aligned against the side o
- Menu items should be short — ideally, single words — and use sentence capitalization.
- Do not use full sentences inside menu items.
- Ensure that menu items are ordered in a way that is most useful to users. Alphabetical or recency ordering is preferred.
- Menu items can optionally be grouped into option groups if this results in a more understandable presentation of options.

![](https://wordpress.org/gutenberg/files/2018/12/select-do-options.png)

Expand Down Expand Up @@ -118,6 +119,35 @@ Render a user interface to select multiple users from a list.
/>
```

Render a user interface to select users from a list grouped by role.

```jsx
<SelectControl
multiple
label={ __( 'Select some users:' ) }
value={ this.state.users } // e.g: value = [ 'a', 'c' ]
onChange={ ( users ) => { this.setState( { users } ) } }
options={ [
{ label: 'Select a User', value: null, disabled: true },
{ label: 'Admins', value: [
{ label: 'User A', value: 'a' },
{ label: 'User B', value: 'b' },
{ label: 'User C', value: 'c' },
] },
{ label: 'Editors', value: [
{ label: 'User D', value: 'd' },
{ label: 'User E', value: 'e' },
{ label: 'User F', value: 'f' },
] },
{ label: 'Subscribers', value: [
{ label: 'User G', value: 'g' },
{ label: 'User H', value: 'h' },
{ label: 'User I', value: 'i' },
] }
] }
/>
```

### Props

- The set of props accepted by the component will be specified below.
Expand Down Expand Up @@ -158,8 +188,8 @@ If this property is added, multiple values can be selected. The value passed sho
#### options

An array of objects containing the following properties:
- `label`: (string) The label to be shown to the user.
- `value`: (Object) The internal value used to choose the selected value. This is also the value passed to onChange when the option is selected.
- `label`: (string) The label to be shown to the user. (If the `value` property contains an array rather than a scalar, this will be the label for the option group.)
- `value`: (Object) The internal value used to choose the selected value. This is also the value passed to onChange when the option is selected. If this is an array rather than a scalar, an option group will be created with the options contained in the array.
- `disabled`: (boolean) Whether or not the option should have the disabled attribute.
- Type: `Array`
- Required: No
Expand Down
54 changes: 41 additions & 13 deletions packages/components/src/select-control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,19 +110,47 @@ function SelectControl(
value={ valueProp }
>
{ options.map( ( option, index ) => {
const key =
option.id ||
`${ option.label }-${ option.value }-${ index }`;

return (
<option
key={ key }
value={ option.value }
disabled={ option.disabled }
>
{ option.label }
</option>
);
//if the option.value is an array rather than a scalar, we're dealing with an optgroup
if ( Array.isArray( option.value ) ) {
const optgroupkey =
option.id ||
`${ option.label }-${ index }`;
return (
<optgroup
key={ optgroupkey }
label={ option.label }
disabled={ option.disabled }
>
{ option.value.map( ( groupedOption, groupedOptionIndex ) => {
const key =
groupedOption.id ||
`${ groupedOption.label }-${ groupedOption.value }-${ groupedOptionIndex }`;
return (
<option
key={ key }
value={ groupedOption.value }
disabled={ groupedOption.disabled }
>
{ groupedOption.label }
</option>
);
} ) }
</optgroup>
);
} else {
const key =
option.id ||
`${ option.label }-${ option.value }-${ index }`;
return (
<option
key={ key }
value={ option.value }
disabled={ option.disabled }
>
{ option.label }
</option>
);
}
} ) }
</Select>
</InputBase>
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/select-control/stories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export const _default = () => {
{ value: 'a', label: 'Option A' },
{ value: 'b', label: 'Option B' },
{ value: 'c', label: 'Option C' },
{ value: [ { value: 'd', label: 'Option D'}, { value: 'e', label: 'Option E' } ], label: 'Group A' },
{ value: [ { value: 'f', label: 'Option F'}, { value: 'g', label: 'Option G' } ], label: 'Group B' },
] ),
size: select(
'size',
Expand Down