Skip to content

Add Spectrum CheckboxGroup component#1003

Merged
dannify merged 9 commits into
mainfrom
checkbox-group
Aug 25, 2020
Merged

Add Spectrum CheckboxGroup component#1003
dannify merged 9 commits into
mainfrom
checkbox-group

Conversation

@devongovett
Copy link
Copy Markdown
Member

@devongovett devongovett commented Aug 21, 2020

Followup from #868
Closes #798

This adds a CheckboxGroup component to @react-spectrum/checkbox. It follows the same styling as RadioGroup but for checkboxes. This component accepts Checkbox elements as children, and passes the group state to them via context.

Additional changes to the hooks:

  • name handling was moved from stately to aria. This was a mistake in RadioGroup since it's web-specific and it's being deprecated and moved to aria in Fix remaining SSR tests #994. Also, for checkbox groups, there's no need to auto generate a form name like for radio groups, because the name isn't used by the browser for behavior. So we only need to pass through the given name for the group to each checkbox.
  • isDisabled and isReadOnly are now passed through from the group to the checkboxes automatically by storing the values in state.
  • aria-invalid and required DOM props are removed from individual checkboxes within a group since they don't make sense there. Instead, these are exposed at the group level, e.g. in Spectrum the necessity indicator can be used to specify that the group is required. This is up to individual design systems to implement.
  • Renamed checkboxGroupProps in the return value to just groupProps to match the pattern of using the aria role as the name of the property.

Also renamed docs to a temp name so they don't get picked up by the deploy to prod before publishing.

@adobe-bot
Copy link
Copy Markdown

Build successful! 🎉

@adobe-bot
Copy link
Copy Markdown

Build successful! 🎉

@adobe-bot
Copy link
Copy Markdown

Build successful! 🎉

@adobe-bot
Copy link
Copy Markdown

Build successful! 🎉

...props,
isReadOnly: props.isReadOnly || state.isReadOnly,
isDisabled: props.isDisabled || state.isDisabled,
name: props.name || checkboxGroupNames.get(state)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make sense for me unless I miss something. It seems important to keep the same name for all "checkbox group items" as this "groups" them when sending the containing form element.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking it might be possible to have a single "group" client side, but maybe you submit to a server using separate names for each checkbox.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from what i remember of form submission, there are some specials names that work with some servers? i think the name has to include "[]" on the end
if you don't include that then checkboxes with the same name will overwrite each other
but not everything recognizes that special name syntax, so probably better to have them be individually named and just 'look' like a group

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking it might be possible to have a single "group" client side, but maybe you submit to a server using separate names for each checkbox.

How realistic this use case is? Shouldn't this really be considered bad practice?

interface CheckboxGroupAria {
/** Props for the checkbox group wrapper element. */
checkboxGroupProps: HTMLAttributes<HTMLElement>,
groupProps: HTMLAttributes<HTMLElement>,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while I understand the sentiment to match against the returned role, isn't this confusing (DX-wise)? given that useRadioGroup returns radioGroupProps?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, in that case the role is radiogroup.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, the role is mainly opaque to users though - the point of React Aria is so people don't have to worry about this. Seems like one might not really know what exact role is being prefilled by React Aria in the returned objects, but they certainly know how the component that they have just used is named.

I don't care about this as much as TS will help me with this anyway but I kinda find the choice somewhat odd as the chosen name focuses on the low-level implementation detail that is hidden from the user, rather than on a high-level feature that is actually used directly by them.

},
addValue(value) {
if (props.isReadOnly) {
if (props.isReadOnly || props.isDisabled) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this hasn't been covered by the related unit tests 😉

name,
value: selectedValue,
value: selectedValues,
setValue,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if addValue, removeValue and toggleValue check props.isReadOnly || props.isDisabled before actually changing the value, shouldn't the same check apply here?

expect(state.value).toEqual([]);
expect(state.isDisabled).toBe(false);
expect(state.isReadOnly).toBe(false);
expect(typeof state.setValue).toBe('function');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test should also check if isSelected is provided by the hook

expect(state.isReadOnly).toBe(true);

return null;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be great to add a simple test for isSelected functionality as well

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess. We tend not to do too much unit testing of the stately part by itself given that it's already covered by the ARIA/Spectrum tests indirectly. This tends to lead to more maintainable tests. But I suppose since the others are already tested I can add a quick one.

@@ -160,7 +159,7 @@ describe('useCheckboxGroup', () => {
});

it('sets aria-disabled when isDisabled is true', () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that those test names should be adjusted now as a little more than just aria-disabled is being tested here

@adobe-bot
Copy link
Copy Markdown

Build successful! 🎉

Comment thread packages/@react-aria/checkbox/docs/useCheckboxGroup.mdx Outdated
Comment thread packages/@react-spectrum/checkbox/docs/CheckboxGroup.mdx Outdated
Co-authored-by: Danni <drobinson@livefyre.com>
@adobe-bot
Copy link
Copy Markdown

Build successful! 🎉

@dannify dannify merged commit de800ea into main Aug 25, 2020
@dannify dannify deleted the checkbox-group branch August 25, 2020 01:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add CheckboxGroup component

5 participants