Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

### Enhancements

- `CheckboxControl`: Mark as not recommended for use in a WordPress environment, in favour of `CheckboxControl` from `@wordpress/ui` ([#83771](https://github.com/WordPress/gutenberg/pull/83771)).
- `RadioControl`: Match the `@wordpress/ui` Radio colors ([#83270](https://github.com/WordPress/gutenberg/pull/83270)).
- `CheckboxControl`: Keep the default checkbox at 16px on narrow screens while retaining a 24px click target ([#83612](https://github.com/WordPress/gutenberg/pull/83612)).
- `FormToggle`: Match the `@wordpress/ui` `Switch` track, thumb, and border colors across unchecked, checked, hover, and disabled states ([#83773](https://github.com/WordPress/gutenberg/pull/83773)).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { VStack } from '../../v-stack';
import { HStack } from '../../h-stack';

const meta: Meta< typeof CheckboxControl > = {
tags: [ 'manifest' ],
component: CheckboxControl,
title: 'Components/@wordpress-components/Selection & Input/Common/CheckboxControl',
id: 'components-checkboxcontrol',
Expand All @@ -27,9 +26,9 @@ const meta: Meta< typeof CheckboxControl > = {
},
docs: { canvas: { sourceState: 'shown' } },
componentStatus: {
status: 'recommended',
status: 'not-recommended',
whereUsed: 'global',
notes: 'Will be superseded by [`CheckboxControl`](?path=/docs/design-system-components-form-checkboxcontrol--docs) in `@wordpress/ui`, but continue using for now.',
notes: 'Use [`CheckboxControl`](?path=/docs/design-system-components-form-checkboxcontrol--docs) from `@wordpress/ui` instead. See the [migration guide](?path=/docs/components-checkboxcontrol--migration-guide).',
},
},
};
Expand Down
106 changes: 106 additions & 0 deletions packages/components/src/checkbox-control/stories/migration-guide.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Markdown, Meta } from '@storybook/addon-docs/blocks';
import * as CheckboxControlStories from './index.story';

<Meta of={ CheckboxControlStories } name="Migration Guide" />

# CheckboxControl migration guide

Migrate from [`CheckboxControl`](?path=/docs/components-checkboxcontrol--docs) in `@wordpress/components` to [`CheckboxControl`](?path=/docs/design-system-components-form-checkboxcontrol--docs) in `@wordpress/ui`.

## Basic migration

Update the import and replace the callback and help props:

```jsx
// Before
import { CheckboxControl } from '@wordpress/components';

<CheckboxControl
label="Is author"
checked={ isChecked }
onChange={ setChecked }
help="Give this user author permissions."
/>;

// After
import { CheckboxControl } from '@wordpress/ui';

<CheckboxControl
label="Is author"
checked={ isChecked }
onCheckedChange={ setChecked }
description="Give this user author permissions."
/>;
```

## Prop mapping

<Markdown>{ `
| \`@wordpress/components\` | \`@wordpress/ui\` | Notes |
| --- | --- | --- |
| \`onChange\` | \`onCheckedChange\` | Receives the next checked state as a boolean. |
| \`help\` | \`description\` | Use plain text only. |
| \`help\` with links or other markup | \`details\` | Use when the help text needs semantic content. |
| \`checked\` | \`checked\` | Continue passing the state for a controlled checkbox. |

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.

Could we document the default form value change from "1" to "on" and show value="1" when preserving the legacy payload? A named checkbox migrated using these steps otherwise submits a different value.

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.

Good catch, added in d1f6652.

` }</Markdown>

## Form values

When a checked checkbox has a `name` but no `value`, the legacy component submits `"1"` with the form, while the new component submits `"on"`, the native default for checkboxes. If your form handler expects the legacy value, pass `value="1"` to the new component:

```jsx
<CheckboxControl
name="isAuthor"
value="1"
label="Is author"
checked={ isChecked }
onCheckedChange={ setChecked }
/>
```

If the legacy component already has a custom `value`, keep that value instead.

## Labels

The new `CheckboxControl` requires a `label` prop with a plain `string` value. The legacy component treats `label` as optional. Give every checkbox a descriptive label, even when the text is already visible elsewhere:

```jsx
<CheckboxControl
label="Receive notifications"
hideLabelFromVision
checked={ isChecked }
onCheckedChange={ setChecked }
/>
```

For a custom label layout, compose the [`Checkbox`](?path=/docs/design-system-components-form-primitives-checkbox--docs) and [`Field`](?path=/docs/design-system-components-form-primitives-field--docs) primitives.

## Checkbox groups

If a legacy checkbox uses `indeterminate` to show that only some items are selected, move the selected items into a `CheckboxGroup` instead of calculating the parent checkbox state yourself. Pass the child values to `allValues` and mark the select-all checkbox with `parent`. The group updates the parent checkbox when children change and selects or clears all children when the parent is clicked.

```jsx
import { useState } from '@wordpress/element';
import { CheckboxControl, CheckboxGroup } from '@wordpress/ui';

function FruitCheckboxes() {
const [ selectedFruits, setSelectedFruits ] = useState( [ 'apple' ] );

return (
<CheckboxGroup
value={ selectedFruits }
onValueChange={ setSelectedFruits }
allValues={ [ 'apple', 'orange' ] }
aria-label="Fruit"
>
<CheckboxControl parent value="fruit" label="Select all fruit" />
<CheckboxGroup.NestedItems>
<CheckboxControl value="apple" label="Apple" />
<CheckboxControl value="orange" label="Orange" />
</CheckboxGroup.NestedItems>
</CheckboxGroup>
);
}
```

See the [Checkbox Groups stories](?path=/docs/design-system-components-form-checkbox-groups--docs) for other grouping patterns.
1 change: 1 addition & 0 deletions packages/eslint-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

### Enhancements

- `use-recommended-components`: Recommend `Checkbox`, `CheckboxControl`, and `CheckboxGroup` from `@wordpress/ui`, and flag `CheckboxControl` from `@wordpress/components` ([#83771](https://github.com/WordPress/gutenberg/pull/83771)).
- `use-recommended-components`: Update the "Use with caution" entry from `LinkButton` to `ButtonLink` to match the renamed `@wordpress/ui` component ([#83789](https://github.com/WordPress/gutenberg/pull/83789)).
- Update `use-recommended-components` rule to prefer `Badge` from `@wordpress/ui` over the private `@wordpress/components` `Badge`. ([#82379](https://github.com/WordPress/gutenberg/pull/82379))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ The rule checks named imports and direct destructuring from `unlock( privateApis

## Migration guides

- `CheckboxControl` — [`CheckboxControl` migration guide][checkboxcontrol-migration-guide]
- `__experimentalInputControl` — [`InputControl` migration guide][inputcontrol-migration-guide]
- `TextControl` — [`InputControl` migration guide][inputcontrol-migration-guide]
- `TextareaControl` — [`TextareaControl` migration guide][textareacontrol-migration-guide]

[checkboxcontrol-migration-guide]: https://wordpress.github.io/gutenberg/?path=/docs/components-checkboxcontrol--migration-guide
[inputcontrol-migration-guide]: https://wordpress.github.io/gutenberg/?path=/docs/components-inputcontrol--migration-guide
[textareacontrol-migration-guide]: https://wordpress.github.io/gutenberg/?path=/docs/components-textareacontrol--migration-guide

Expand Down
7 changes: 5 additions & 2 deletions packages/eslint-plugin/rules/use-recommended-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ const ALLOWLIST = {
'Badge',
'Calendar',
'Card',
'Checkbox',
'CheckboxControl',
'CheckboxGroup',
'Collapsible',
'CollapsibleCard',
'ControlWithError',
Expand Down Expand Up @@ -60,8 +63,6 @@ const ALLOWLIST = {
'Breadcrumb',
'Button',
'ButtonLink',
'Checkbox',
'CheckboxGroup',
'Combobox',
'Dialog',
'Drawer',
Expand Down Expand Up @@ -121,6 +122,8 @@ const DENYLIST = {
CardHeader:
'Use `Card.Header` (and optionally `Card.Title`) from `@wordpress/ui` instead.',
CardMedia: 'Use `Card.FullBleed` from `@wordpress/ui` instead.',
CheckboxControl:
'Use `CheckboxControl` from `@wordpress/ui` instead. See migration guide in the lint rule documentation.',
Flex: 'For use cases not covered by `Stack` from `@wordpress/ui`, write your own CSS instead.',
FlexBlock:
'For use cases not covered by `Stack` from `@wordpress/ui`, write your own CSS instead.',
Expand Down
1 change: 1 addition & 0 deletions packages/ui/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

### Enhancements

- `Checkbox`, `CheckboxControl`, `CheckboxGroup`: Mark as recommended for use in a WordPress environment ([#83771](https://github.com/WordPress/gutenberg/pull/83771)).
- `Spinner`: Show a trackless half-circle like the `Button` loading indicator, with a `color` prop that accepts any CSS color value and defaults to weak neutral foreground. Keep the arc visible in forced-colors mode ([#83775](https://github.com/WordPress/gutenberg/pull/83775)).
- Native text inputs and textareas use at least 16px below 600px to avoid iOS Safari zoom. Prefix and suffix text on `Input` match that size. Select and combobox trigger text stay at the `md` font size. ([#82764](https://github.com/WordPress/gutenberg/pull/82764))
- `Menu`: Add development-only checks against nesting `Group` and `RadioGroup` within each other, and document how to label radio groups ([#83792](https://github.com/WordPress/gutenberg/pull/83792)).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ import {
} from '../../stories/shared';

const meta: Meta< typeof CheckboxControl > = {
tags: [ 'manifest' ],
title: 'Components/@wordpress-ui/Form/CheckboxControl',
id: 'design-system-components-form-checkboxcontrol',
component: CheckboxControl,
argTypes: {
checked: { control: false },
onCheckedChange: { action: 'onCheckedChange' },
},
parameters: {
componentStatus: {
status: 'recommended',
whereUsed: 'global',
},
},
};
export default meta;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Checkbox } from '../../checkbox';
import { CheckboxGroup } from '../';

const meta: Meta< typeof CheckboxGroup > = {
tags: [ 'manifest' ],
title: 'Components/@wordpress-ui/Form/Primitives/CheckboxGroup',
id: 'design-system-components-form-primitives-checkboxgroup',
component: CheckboxGroup,
Expand All @@ -15,9 +16,8 @@ const meta: Meta< typeof CheckboxGroup > = {
},
parameters: {
componentStatus: {
status: 'use-with-caution',
status: 'recommended',
whereUsed: 'global',
notes: 'Not yet recommended for use alongside components from `@wordpress/components`, pending review of style consistency with `@wordpress/components` and component set completeness. See [WordPress/gutenberg#76135](https://github.com/WordPress/gutenberg/issues/76135).',
},
},
};
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/form/primitives/checkbox-group/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { ComponentProps } from '../../../utils/types';
import type { Stack } from '../../../stack';

export type CheckboxGroupProps = ComponentProps< typeof _CheckboxGroup > & {
/** The checkboxes and optional nested items in the group. */
children?: React.ReactNode;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite';
import { Checkbox } from '../';

const meta: Meta< typeof Checkbox > = {
tags: [ 'manifest' ],
title: 'Components/@wordpress-ui/Form/Primitives/Checkbox',
id: 'design-system-components-form-primitives-checkbox',
component: Checkbox,
Expand All @@ -10,9 +11,8 @@ const meta: Meta< typeof Checkbox > = {
},
parameters: {
componentStatus: {
status: 'use-with-caution',
status: 'recommended',
whereUsed: 'global',
notes: 'Not yet recommended for use alongside components from `@wordpress/components`, pending review of style consistency with `@wordpress/components` and component set completeness. See [WordPress/gutenberg#76135](https://github.com/WordPress/gutenberg/issues/76135).',
},
},
};
Expand Down
65 changes: 61 additions & 4 deletions storybook/components-manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -279,16 +279,73 @@
- className
- render
- style
- name: Checkbox
props:
- checked
- className
- defaultChecked
- disabled
- form
- id
- indeterminate
- inputRef
- name
- nativeButton
- onCheckedChange
- parent
- readOnly
- render
- required
- style
- uncheckedValue
- value
- name: CheckboxControl
props:
- __nextHasNoMarginBottom
- checked
- className
- defaultChecked
- description
- details
- disabled
- heading
- help
- form
- hideLabelFromVision
- id
- indeterminate
- inputRef
- label
- onChange
- name
- nativeButton
- onCheckedChange
- parent
- readOnly
- render
- required
- style
- uncheckedValue
- value
- name: CheckboxGroup
props:
- allValues
- children
- className
- defaultValue
- disabled
- onValueChange
- render
- style
- value
subcomponents:
- name: CheckboxGroup.NestedItems
props:
- align
- children
- className
- direction
- gap
- justify
- render
- style
- wrap
- name: Collapsible.Root
props:
- children
Expand Down
1 change: 0 additions & 1 deletion storybook/prop-description-allowlist.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"Autocomplete.Root>Autocomplete.Value:children",
"BaseControl:className",
"BaseControl>BaseControl.VisualLabel",
"CheckboxControl:heading",
"ComboboxControl:className",
"Composite>Composite.Context",
"Field.Root:children",
Expand Down
Loading
Loading