Add CheckboxGroup story and initial implementation (#33051)

* Add CheckboxGroup story and initial implementation

Signed-off-by: Deepthi Ajith <deepthi.ajith@infosys.com>

* Add CheckboxGroup implementation and docs coverage

Signed-off-by: Deepthi Ajith <deepthi.ajith@infosys.com>

* update api-reports

Signed-off-by: Deepthi Ajith <deepthi.ajith@infosys.com>

* fix: add more story variations, docs page, and fix JSDoc comments

Signed-off-by: Deepthi Ajith <deepthi.ajith@infosys.com>

* fix: address review feedback for CheckboxGroup component

Signed-off-by: Deepthi Ajith <deepthi.ajith@infosys.com>

---------

Signed-off-by: Deepthi Ajith <deepthi.ajith@infosys.com>
This commit is contained in:
deepthi-28
2026-04-07 14:28:29 +05:30
committed by GitHub
parent 38950237e3
commit aa47a370eb
17 changed files with 809 additions and 17 deletions
@@ -0,0 +1,81 @@
'use client';
import { CheckboxGroup } from '../../../../../packages/ui/src/components/CheckboxGroup/CheckboxGroup';
import { Checkbox } from '../../../../../packages/ui/src/components/Checkbox/Checkbox';
export const Default = () => {
return (
<CheckboxGroup
label="Choose platforms for notifications"
defaultValue={['github']}
>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack">Slack</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>
);
};
export const Horizontal = () => (
<CheckboxGroup
label="Choose platforms for notifications"
defaultValue={['github']}
orientation="horizontal"
>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack">Slack</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>
);
export const Disabled = () => (
<CheckboxGroup
label="Choose platforms for notifications"
defaultValue={['github']}
isDisabled
>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack">Slack</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>
);
export const DisabledSingle = () => (
<CheckboxGroup
label="Choose platforms for notifications"
defaultValue={['github']}
>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack" isDisabled>
Slack
</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>
);
export const Validation = () => (
<CheckboxGroup
label="Choose platforms for notifications"
defaultValue={['github', 'slack']}
validationBehavior="aria"
validate={(value: string[]) =>
value.includes('slack') ? 'Slack is not available in your region.' : null
}
>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack">Slack</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>
);
export const ReadOnly = () => (
<CheckboxGroup
label="Choose platforms for notifications"
defaultValue={['github']}
isReadOnly
>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack">Slack</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>
);
@@ -0,0 +1,110 @@
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import { ReactAriaLink } from '@/components/ReactAriaLink';
import { checkboxGroupPropDefs } from './props-definition';
import {
checkboxGroupUsageSnippet,
defaultSnippet,
horizontalSnippet,
disabledSnippet,
disabledSingleSnippet,
validationSnippet,
readOnlySnippet,
} from './snippets';
import {
Default,
Horizontal,
Disabled,
DisabledSingle,
Validation,
ReadOnly,
} from './components';
import { PageTitle } from '@/components/PageTitle';
import { Theming } from '@/components/Theming';
import { ChangelogComponent } from '@/components/ChangelogComponent';
import { CodeBlock } from '@/components/CodeBlock';
import { CheckboxGroupDefinition } from '../../../utils/definitions';
export const reactAriaUrls = {
checkboxGroup: 'https://react-aria.adobe.com/CheckboxGroup',
};
<PageTitle
title="CheckboxGroup"
description="A group of checkboxes for selecting multiple options from a list."
/>
<Snippet align="center" py={4} preview={<Default />} code={defaultSnippet} />
## Usage
<CodeBlock code={checkboxGroupUsageSnippet} />
## API reference
### CheckboxGroup
<PropsTable data={checkboxGroupPropDefs} />
<ReactAriaLink component="CheckboxGroup" href={reactAriaUrls.checkboxGroup} />
## Examples
### Horizontal
<Snippet
align="center"
py={4}
open
layout="side-by-side"
preview={<Horizontal />}
code={horizontalSnippet}
/>
### Disabled
<Snippet
align="center"
py={4}
open
layout="side-by-side"
preview={<Disabled />}
code={disabledSnippet}
/>
### Disabled single checkbox
<Snippet
align="center"
py={4}
open
layout="side-by-side"
preview={<DisabledSingle />}
code={disabledSingleSnippet}
/>
### Validation
<Snippet
align="center"
py={4}
open
layout="side-by-side"
preview={<Validation />}
code={validationSnippet}
/>
### Read only
<Snippet
align="center"
py={4}
open
layout="side-by-side"
preview={<ReadOnly />}
code={readOnlySnippet}
/>
<Theming definition={CheckboxGroupDefinition} />
<ChangelogComponent component="checkbox-group" />
@@ -0,0 +1,82 @@
import {
classNamePropDefs,
childrenPropDefs,
stylePropDefs,
type PropDef,
} from '@/utils/propDefs';
import { Chip } from '@/components/Chip';
export const checkboxGroupPropDefs: Record<string, PropDef> = {
label: {
type: 'string',
description: 'The visible label for the checkbox group.',
},
'aria-label': {
type: 'string',
description:
'Accessible label when a visible label is not provided. Either label, aria-label, or aria-labelledby is required.',
},
'aria-labelledby': {
type: 'string',
description:
'ID of an element that labels the checkbox group. Either label, aria-label, or aria-labelledby is required.',
},
secondaryLabel: {
type: 'string',
description: (
<>
Secondary label text. Defaults to <Chip>Required</Chip> when isRequired
is true.
</>
),
},
description: {
type: 'string',
description: 'Helper text displayed below the label.',
},
orientation: {
type: 'enum',
values: ['horizontal', 'vertical'],
default: 'vertical',
description: 'The axis the checkboxes should align with.',
},
value: {
type: 'enum',
values: ['string[]'],
description: 'The selected values (controlled).',
},
defaultValue: {
type: 'enum',
values: ['string[]'],
description: 'The initial selected values (uncontrolled).',
},
onChange: {
type: 'enum',
values: ['(value: string[]) => void'],
description: 'Handler called when the selected values change.',
},
isDisabled: {
type: 'boolean',
description: 'Whether all checkboxes in the group are disabled.',
},
isReadOnly: {
type: 'boolean',
description: 'Whether all checkboxes in the group are read-only.',
},
isRequired: {
type: 'boolean',
description:
'Whether at least one selection is required for form submission.',
},
isInvalid: {
type: 'boolean',
description: 'Whether the checkbox group is in an invalid state.',
},
name: {
type: 'string',
description: 'The name used for form submission.',
},
...childrenPropDefs,
...classNamePropDefs,
...stylePropDefs,
};
@@ -0,0 +1,65 @@
export const checkboxGroupUsageSnippet = `import { CheckboxGroup, Checkbox } from '@backstage/ui';
<CheckboxGroup label="Choose platforms for notifications" defaultValue={['github']}>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack">Slack</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>`;
export const defaultSnippet = `<CheckboxGroup label="Choose platforms for notifications" defaultValue={['github']}>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack">Slack</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>`;
export const horizontalSnippet = `<CheckboxGroup
label="Choose platforms for notifications"
defaultValue={['github']}
orientation="horizontal"
>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack">Slack</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>`;
export const disabledSnippet = `<CheckboxGroup
label="Choose platforms for notifications"
defaultValue={['github']}
isDisabled
>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack">Slack</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>`;
export const disabledSingleSnippet = `<CheckboxGroup
label="Choose platforms for notifications"
defaultValue={['github']}
>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack" isDisabled>Slack</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>`;
export const validationSnippet = `<CheckboxGroup
label="Choose platforms for notifications"
defaultValue={['github', 'slack']}
validationBehavior="aria"
validate={value =>
value.includes('slack') ? 'Slack is not available in your region.' : null
}
>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack">Slack</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>`;
export const readOnlySnippet = `<CheckboxGroup
label="Choose platforms for notifications"
defaultValue={['github']}
isReadOnly
>
<Checkbox value="github">GitHub</Checkbox>
<Checkbox value="slack">Slack</Checkbox>
<Checkbox value="email">Email</Checkbox>
</CheckboxGroup>`;
+4
View File
@@ -45,6 +45,10 @@ export const components: Page[] = [
title: 'Checkbox',
slug: 'checkbox',
},
{
title: 'CheckboxGroup',
slug: 'checkbox-group',
},
{
title: 'Container',
slug: 'container',
+1
View File
@@ -17,6 +17,7 @@ export type Component =
| 'cell-profile'
| 'cell-text'
| 'checkbox'
| 'checkbox-group'
| 'collapsible'
| 'column'
| 'container'