-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add radio option to ButtonGroup #20805
Merged
Merged
Changes from all commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
5ccd36f
Add radio mode to ButtonGroup with aria attributes
ajlende c942d56
Destructure child props
ajlende 9c85fc3
Add tab index for radio buttons
ajlende 726ac0e
Add keyboard handlers
ajlende 42e671c
Remove TODO comment
ajlende 4a061ff
Add storybook example
ajlende 4373a44
Add documentation example
ajlende adf8bab
Add StoryShot snapshot
ajlende cb97066
Mention ButtonGroup in RadioControl
ajlende 0ca5022
Merge branch 'master' of github.com:WordPress/gutenberg into try/radi…
ajlende a39023b
Merge branch 'master' of github.com:WordPress/gutenberg into try/radi…
ajlende f798e69
Convert to using context instead of cloneElement
ajlende 1af2d22
Merge refs so forwardRef is still usable with radio group
ajlende daca280
Refactor to move button props to button component
ajlende c946eab
Refactor for readability
ajlende 3083dc6
Add comment about default value
ajlende 4242001
Consolidate ref and className
ajlende 86d1088
Fix useMemo return value
ajlende 282ed66
Update snapshots
ajlende c0d3d51
Partially revert snapshots
ajlende bd0f097
Update prop order to match snapshots
ajlende 287c9f0
Update comments for clarity
ajlende a0b7581
Merge branch 'master' of github.com:WordPress/gutenberg into try/radi…
ajlende 213673e
Move changes to radio-group and radio
ajlende 4b2851c
Merge branch 'master' into try/radio-button-group
ajlende d724209
Remove radio button group storybook snapshot
ajlende 10d7e26
Update ButtonGroup extra props to override role
ajlende c01c3bf
Implement forwardRef for ButtonGroup
ajlende 3129af7
Update snapshot with forwardRef(ButtonGroup)
ajlende 37dc2b1
Update RadioControl to mention RadioGroup
ajlende c07e117
Replace Radio/RadioGroup with Reakit version
ajlende 3def111
Add storybook stories for Radio/RadioGroup
ajlende 4f66910
Update Radio/RadioGroup READMEs
ajlende c611871
Update docs manifest
ajlende 7a417ac
Add __experimental prefix for Radio/RadioGroup
ajlende 538538f
Pass through disabled state to children
ajlende da54def
Remove Radio ids from stories
ajlende f2dad34
Update snapshots
ajlende File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { createContext } from '@wordpress/element'; | ||
|
||
const RadioContext = createContext( { | ||
state: null, | ||
setState: () => {}, | ||
} ); | ||
|
||
export default RadioContext; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# RadioGroup | ||
|
||
Use a RadioGroup component when you want users to select one option from a small set of options. | ||
|
||
![RadioGroup component](https://wordpress.org/gutenberg/files/2018/12/s_96EC471FE9C9D91A996770229947AAB54A03351BDE98F444FD3C1BF0CED365EA_1541792995815_ButtonGroup.png) | ||
|
||
## Table of contents | ||
|
||
1. [Design guidelines](#design-guidelines) | ||
2. [Development guidelines](#development-guidelines) | ||
3. [Related components](#related-components) | ||
|
||
## Design guidelines | ||
|
||
### Usage | ||
|
||
#### Selected action | ||
|
||
Only one option in a radio group can be selected and active at a time. Selecting one option deselects any other. | ||
|
||
### Best practices | ||
|
||
Radio groups should: | ||
|
||
- **Be clearly and accurately labeled.** | ||
- **Clearly communicate that clicking or tapping will trigger an action.** | ||
- **Use established colors appropriately.** For example, only use red buttons for actions that are difficult or impossible to undo. | ||
- **Have consistent locations in the interface.** | ||
- **Have a default option already selected.** | ||
|
||
### States | ||
|
||
#### Active and available radio groups | ||
|
||
A radio group’s state makes it clear which option is active. Hover and focus states express the available selection options for buttons in a button group. | ||
|
||
#### Disabled radio groups | ||
|
||
Radio groups that cannot be selected can either be given a disabled state, or be hidden. | ||
ajlende marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Development guidelines | ||
|
||
### Usage | ||
|
||
#### Controlled | ||
|
||
```jsx | ||
import { Radio, RadioGroup } from '@wordpress/components'; | ||
import { useState } from '@wordpress/element'; | ||
|
||
const MyControlledRadioRadioGroup = () => { | ||
const [ checked, setChecked ] = useState( '25' ); | ||
return ( | ||
<RadioGroup accessibilityLabel="Width" onChange={ setChecked } checked={ checked }> | ||
<Radio value="25">25%</Radio> | ||
<Radio value="50">50%</Radio> | ||
<Radio value="75">75%</Radio> | ||
<Radio value="100">100%</Radio> | ||
</RadioGroup> | ||
); | ||
}; | ||
``` | ||
|
||
#### Uncontrolled | ||
|
||
When using the RadioGroup component as an uncontrolled component, the default value can be set with the `defaultChecked` prop. | ||
|
||
```jsx | ||
import { Radio, RadioGroup } from '@wordpress/components'; | ||
import { useState } from '@wordpress/element'; | ||
|
||
const MyUncontrolledRadioRadioGroup = () => { | ||
return ( | ||
<RadioGroup accessibilityLabel="Width" defaultChecked="25"> | ||
<Radio value="25">25%</Radio> | ||
<Radio value="50">50%</Radio> | ||
<Radio value="75">75%</Radio> | ||
<Radio value="100">100%</Radio> | ||
</RadioGroup> | ||
); | ||
}; | ||
``` | ||
|
||
## Related components | ||
|
||
- For simple buttons that are related, use a `ButtonGroup` component. | ||
- For traditional radio options, use a `RadioControl` component. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { useRadioState, RadioGroup as ReakitRadioGroup } from 'reakit/Radio'; | ||
|
||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { forwardRef } from '@wordpress/element'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import ButtonGroup from '../button-group'; | ||
import RadioContext from '../radio-context'; | ||
|
||
function RadioGroup( | ||
{ | ||
accessibilityLabel, | ||
checked, | ||
defaultChecked, | ||
disabled, | ||
onChange, | ||
...props | ||
}, | ||
ref | ||
) { | ||
const radioState = useRadioState( { | ||
state: defaultChecked, | ||
baseId: props.id, | ||
} ); | ||
const radioContext = { | ||
...radioState, | ||
disabled, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very clever! 👍 |
||
// controlled or uncontrolled | ||
state: checked || radioState.state, | ||
setState: onChange || radioState.setState, | ||
}; | ||
|
||
return ( | ||
<RadioContext.Provider value={ radioContext }> | ||
<ReakitRadioGroup | ||
ref={ ref } | ||
as={ ButtonGroup } | ||
aria-label={ accessibilityLabel } | ||
{ ...radioState } | ||
{ ...props } | ||
/> | ||
</RadioContext.Provider> | ||
); | ||
} | ||
|
||
export default forwardRef( RadioGroup ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useState } from '@wordpress/element'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import Radio from '../../radio'; | ||
import RadioGroup from '../'; | ||
|
||
export default { title: 'Components/RadioGroup', component: RadioGroup }; | ||
|
||
export const _default = () => { | ||
/* eslint-disable no-restricted-syntax */ | ||
return ( | ||
<RadioGroup | ||
// id is required for server side rendering | ||
id="default-radiogroup" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might start inlining the comment in id 😂 id=“required-for-server-side-rendering-only”? |
||
accessibilityLabel="options" | ||
defaultChecked="option2" | ||
> | ||
<Radio value="option1">Option 1</Radio> | ||
<Radio value="option2">Option 2</Radio> | ||
<Radio value="option3">Option 3</Radio> | ||
</RadioGroup> | ||
); | ||
/* eslint-enable no-restricted-syntax */ | ||
}; | ||
|
||
export const disabled = () => { | ||
/* eslint-disable no-restricted-syntax */ | ||
return ( | ||
<RadioGroup | ||
// id is required for server side rendering | ||
id="disabled-radiogroup" | ||
disabled | ||
accessibilityLabel="options" | ||
defaultChecked="option2" | ||
> | ||
<Radio value="option1">Option 1</Radio> | ||
<Radio value="option2">Option 2</Radio> | ||
<Radio value="option3">Option 3</Radio> | ||
</RadioGroup> | ||
); | ||
/* eslint-enable no-restricted-syntax */ | ||
}; | ||
|
||
const ControlledRadioGroupWithState = () => { | ||
const [ checked, setChecked ] = useState( 'option2' ); | ||
|
||
/* eslint-disable no-restricted-syntax */ | ||
return ( | ||
<RadioGroup | ||
// id is required for server side rendering | ||
id="controlled-radiogroup" | ||
accessibilityLabel="options" | ||
checked={ checked } | ||
onChange={ setChecked } | ||
> | ||
<Radio value="option1">Option 1</Radio> | ||
<Radio value="option2">Option 2</Radio> | ||
<Radio value="option3">Option 3</Radio> | ||
</RadioGroup> | ||
); | ||
/* eslint-enable no-restricted-syntax */ | ||
}; | ||
|
||
export const controlled = () => { | ||
return <ControlledRadioGroupWithState />; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { Radio as ReakitRadio } from 'reakit/Radio'; | ||
|
||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useContext, forwardRef } from '@wordpress/element'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import Button from '../button'; | ||
import RadioContext from '../radio-context'; | ||
|
||
function Radio( { children, value, ...props }, ref ) { | ||
const radioContext = useContext( RadioContext ); | ||
const checked = radioContext.state === value; | ||
|
||
return ( | ||
<ReakitRadio | ||
ref={ ref } | ||
as={ Button } | ||
isPrimary={ checked } | ||
isSecondary={ ! checked } | ||
value={ value } | ||
{ ...radioContext } | ||
{ ...props } | ||
> | ||
{ children || value } | ||
</ReakitRadio> | ||
); | ||
} | ||
|
||
export default forwardRef( Radio ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import RadioGroup from '../../radio-group'; | ||
import Radio from '../'; | ||
|
||
export default { title: 'Components/Radio', component: Radio }; | ||
|
||
export const _default = () => { | ||
// Radio components must be a descendent of a RadioGroup component. | ||
/* eslint-disable no-restricted-syntax */ | ||
return ( | ||
// id is required for server side rendering | ||
<RadioGroup id="default-radiogroup" accessibilityLabel="options"> | ||
<Radio value="option1">Option 1</Radio> | ||
<Radio value="option2">Option 2</Radio> | ||
</RadioGroup> | ||
); | ||
/* eslint-enable no-restricted-syntax */ | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, it’s experimental but we expose it in developer documentation. I hope to have a look into it and figure out how we can improve it. The good part is that https://developer.wordpress.org/block-editor/components/ is generated from the branch that targets WP 5.4 😃