Skip to content

Commit bf01ade

Browse files
feat(ToggleGroup): added full width variant (#12374)
* feat(ToggleGroup): added full width variant * Updated types in example * Updated example description * Mentioned variants in example desc * Hyphenated words * Rebased + redeleted * Yarn lock
1 parent 30db3d9 commit bf01ade

10 files changed

Lines changed: 153 additions & 23 deletions

File tree

packages/react-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"tslib": "^2.8.1"
5555
},
5656
"devDependencies": {
57-
"@patternfly/patternfly": "6.5.0-prerelease.72",
57+
"@patternfly/patternfly": "6.5.0-prerelease.75",
5858
"case-anything": "^3.1.2",
5959
"css": "^3.0.0",
6060
"fs-extra": "^11.3.3"

packages/react-core/src/components/ToggleGroup/ToggleGroup.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export interface ToggleGroupProps extends React.HTMLProps<HTMLDivElement> {
1010
className?: string;
1111
/** Modifies the toggle group to include compact styling. */
1212
isCompact?: boolean;
13+
/** Modifies the toggle group items to fill the available space. */
14+
isFill?: boolean;
1315
/** Disable all toggle group items under this component. */
1416
areAllGroupsDisabled?: boolean;
1517
/** Accessible label for the toggle group */
@@ -20,6 +22,7 @@ export const ToggleGroup: React.FunctionComponent<ToggleGroupProps> = ({
2022
className,
2123
children,
2224
isCompact = false,
25+
isFill = false,
2326
areAllGroupsDisabled = false,
2427
'aria-label': ariaLabel,
2528
...props
@@ -32,7 +35,12 @@ export const ToggleGroup: React.FunctionComponent<ToggleGroupProps> = ({
3235

3336
return (
3437
<div
35-
className={css(styles.toggleGroup, isCompact && styles.modifiers.compact, className)}
38+
className={css(
39+
styles.toggleGroup,
40+
isCompact && styles.modifiers.compact,
41+
isFill && styles.modifiers.fill,
42+
className
43+
)}
3644
role="group"
3745
aria-label={ariaLabel}
3846
{...props}

packages/react-core/src/components/ToggleGroup/__tests__/ToggleGroup.test.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event';
33

44
import { ToggleGroup } from '../ToggleGroup';
55
import { ToggleGroupItem } from '../ToggleGroupItem';
6+
import styles from '@patternfly/react-styles/css/components/ToggleGroup/toggle-group';
67

78
const props = {
89
onChange: jest.fn(),
@@ -59,6 +60,28 @@ describe('ToggleGroup', () => {
5960
expect(asFragment()).toMatchSnapshot();
6061
});
6162

63+
test(`does not apply ${styles.modifiers.fill} modifier class by default`, () => {
64+
render(
65+
<ToggleGroup aria-label="Default toggle group">
66+
<ToggleGroupItem text="Test" />
67+
<ToggleGroupItem text="Test" />
68+
</ToggleGroup>
69+
);
70+
const toggleGroup = screen.getByRole('group');
71+
expect(toggleGroup).not.toHaveClass(styles.modifiers.fill);
72+
});
73+
74+
test(`applies ${styles.modifiers.fill} modifier class when isFill is true`, () => {
75+
render(
76+
<ToggleGroup isFill aria-label="Fill toggle group">
77+
<ToggleGroupItem text="Test" />
78+
<ToggleGroupItem text="Test" />
79+
</ToggleGroup>
80+
);
81+
const toggleGroup = screen.getByRole('group');
82+
expect(toggleGroup).toHaveClass(styles.modifiers.fill);
83+
});
84+
6285
test('should render non-ToggleGroupItem children', () => {
6386
const { asFragment } = render(
6487
<ToggleGroup isCompact aria-label="non-element children">

packages/react-core/src/components/ToggleGroup/examples/ToggleGroup.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ section: components
44
cssPrefix: pf-v6-c-toggle-group
55
propComponents: ['ToggleGroup', 'ToggleGroupItem']
66
---
7+
78
import './toggleGroup.css';
89

910
import { useRef, useState } from 'react';
@@ -21,6 +22,7 @@ A single select toggle group allows users to toggle between multiple items.
2122
To indicate whether a `<ToggleGroupItem>` is selected or not, use the `isSelected` property.
2223

2324
```ts file="./ToggleGroupDefaultSingle.tsx"
25+
2426
```
2527

2628
### Multi select toggle group
@@ -30,6 +32,7 @@ A multi select toggle group allows users to select multiple items at once.
3032
When a toggle item is disabled it cannot be selected. Click the "Disable all" button in the following example to see this in action.
3133

3234
```ts file="./ToggleGroupDefaultMultiple.tsx"
35+
3336
```
3437

3538
### With icons
@@ -39,6 +42,7 @@ You can use a recognizable icon as a toggle item label.
3942
To do this, pass an imported icon to the `icon` property of a `<ToggleGroupItem>`.
4043

4144
```ts file="./ToggleGroupIcon.tsx"
45+
4246
```
4347

4448
### With text and icons
@@ -50,13 +54,23 @@ To do this, pass a descriptive label to the `text` property of a `<ToggleGroupIt
5054
When passing both `text` and `icon` properties to a `<ToggleGroupItem>`, you can also pass in `iconPosition` to determine whether the icon is rendered at the start or end of the item.
5155

5256
```ts file="./ToggleGroupTextIcon.tsx"
57+
5358
```
5459

5560
### Compact toggle group
5661

57-
When space in a UI is limited, you can use a compact toggle group.
62+
When space in a UI is limited, you can use a compact toggle group.
5863

5964
To apply compact styling to a `<ToggleGroup>`, use `isCompact`.
6065

6166
```ts file="./ToggleGroupCompact.tsx"
67+
68+
```
69+
70+
### Full-width toggle group
71+
72+
To make toggle group items fill the available horizontal space, use `isFill` on a `<ToggleGroup>`. The following example shows full-width toggle groups for a single-select, multi-select, and single-select with disabled item.
73+
74+
```ts file="./ToggleGroupFill.tsx"
75+
6276
```
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { useState } from 'react';
2+
import { ToggleGroup, ToggleGroupItem } from '@patternfly/react-core';
3+
4+
export const ToggleGroupFill: React.FunctionComponent = () => {
5+
const [isSelectedBasic, setIsSelectedBasic] = useState('toggle-group-fill-1');
6+
const [isSelectedMulti, setIsSelectedMulti] = useState({
7+
'toggle-group-fill-multi-1': false,
8+
'toggle-group-fill-multi-2': false,
9+
'toggle-group-fill-multi-3': false
10+
});
11+
const [isSelectedDisabled, setIsSelectedDisabled] = useState('toggle-group-fill-disabled-1');
12+
13+
const handleItemClickBasic = (event: React.MouseEvent<any> | React.KeyboardEvent | MouseEvent) => {
14+
const id = event.currentTarget.id;
15+
setIsSelectedBasic(id);
16+
};
17+
18+
const handleItemClickMulti = (
19+
event: React.MouseEvent<any> | React.KeyboardEvent | MouseEvent,
20+
isSelected: boolean
21+
) => {
22+
const id = event.currentTarget.id;
23+
setIsSelectedMulti((prevIsSelected) => ({ ...prevIsSelected, [id]: isSelected }));
24+
};
25+
26+
const handleItemClickDisabled = (event: React.MouseEvent<any> | React.KeyboardEvent | MouseEvent) => {
27+
const id = event.currentTarget.id;
28+
setIsSelectedDisabled(id);
29+
};
30+
31+
return (
32+
<>
33+
<ToggleGroup isFill aria-label="Full width toggle group">
34+
<ToggleGroupItem
35+
text="Option 1"
36+
buttonId="toggle-group-fill-1"
37+
isSelected={isSelectedBasic === 'toggle-group-fill-1'}
38+
onChange={handleItemClickBasic}
39+
/>
40+
<ToggleGroupItem
41+
text="Option 2"
42+
buttonId="toggle-group-fill-2"
43+
isSelected={isSelectedBasic === 'toggle-group-fill-2'}
44+
onChange={handleItemClickBasic}
45+
/>
46+
<ToggleGroupItem
47+
text="Option 3"
48+
buttonId="toggle-group-fill-3"
49+
isSelected={isSelectedBasic === 'toggle-group-fill-3'}
50+
onChange={handleItemClickBasic}
51+
/>
52+
</ToggleGroup>
53+
<br />
54+
<ToggleGroup isFill aria-label="Full width multi-select toggle group">
55+
<ToggleGroupItem
56+
text="Option 1"
57+
buttonId="toggle-group-fill-multi-1"
58+
isSelected={isSelectedMulti['toggle-group-fill-multi-1']}
59+
onChange={handleItemClickMulti}
60+
/>
61+
<ToggleGroupItem
62+
text="Option 2"
63+
buttonId="toggle-group-fill-multi-2"
64+
isSelected={isSelectedMulti['toggle-group-fill-multi-2']}
65+
onChange={handleItemClickMulti}
66+
/>
67+
<ToggleGroupItem
68+
text="Option 3"
69+
buttonId="toggle-group-fill-multi-3"
70+
isSelected={isSelectedMulti['toggle-group-fill-multi-3']}
71+
onChange={handleItemClickMulti}
72+
/>
73+
</ToggleGroup>
74+
<br />
75+
<ToggleGroup isFill aria-label="Full width toggle group with disabled item">
76+
<ToggleGroupItem
77+
text="Option 1"
78+
buttonId="toggle-group-fill-disabled-1"
79+
isSelected={isSelectedDisabled === 'toggle-group-fill-disabled-1'}
80+
onChange={handleItemClickDisabled}
81+
/>
82+
<ToggleGroupItem
83+
text="Option 2"
84+
buttonId="toggle-group-fill-disabled-2"
85+
isSelected={isSelectedDisabled === 'toggle-group-fill-disabled-2'}
86+
onChange={handleItemClickDisabled}
87+
/>
88+
<ToggleGroupItem text="Option 3" isDisabled />
89+
</ToggleGroup>
90+
</>
91+
);
92+
};

packages/react-docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"test:a11y": "patternfly-a11y --config patternfly-a11y.config"
2424
},
2525
"dependencies": {
26-
"@patternfly/patternfly": "6.5.0-prerelease.72",
26+
"@patternfly/patternfly": "6.5.0-prerelease.75",
2727
"@patternfly/react-charts": "workspace:^",
2828
"@patternfly/react-code-editor": "workspace:^",
2929
"@patternfly/react-core": "workspace:^",

packages/react-icons/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"@fortawesome/free-brands-svg-icons": "^5.15.4",
3636
"@fortawesome/free-regular-svg-icons": "^5.15.4",
3737
"@fortawesome/free-solid-svg-icons": "^5.15.4",
38-
"@patternfly/patternfly": "6.5.0-prerelease.71",
38+
"@patternfly/patternfly": "6.5.0-prerelease.75",
3939
"@rhds/icons": "^2.1.0",
4040
"fs-extra": "^11.3.3",
4141
"tslib": "^2.8.1"

packages/react-styles/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"clean": "rimraf dist css"
2020
},
2121
"devDependencies": {
22-
"@patternfly/patternfly": "6.5.0-prerelease.72",
22+
"@patternfly/patternfly": "6.5.0-prerelease.75",
2323
"change-case": "^5.4.4",
2424
"fs-extra": "^11.3.3"
2525
},

packages/react-tokens/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
},
3131
"devDependencies": {
3232
"@adobe/css-tools": "^4.4.4",
33-
"@patternfly/patternfly": "6.5.0-prerelease.72",
33+
"@patternfly/patternfly": "6.5.0-prerelease.75",
3434
"fs-extra": "^11.3.3"
3535
}
3636
}

yarn.lock

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5070,17 +5070,10 @@ __metadata:
50705070
languageName: node
50715071
linkType: hard
50725072

5073-
"@patternfly/patternfly@npm:6.5.0-prerelease.71":
5074-
version: 6.5.0-prerelease.71
5075-
resolution: "@patternfly/patternfly@npm:6.5.0-prerelease.71"
5076-
checksum: 10c0/08ab7878527666704ae99f5250e1a0446959143f744d4f0f9508aeb7e2a143dd088b8dc6bb4b0ca6679e9923d5c7cd8068d176070bce7b0c7992c48a865864d9
5077-
languageName: node
5078-
linkType: hard
5079-
5080-
"@patternfly/patternfly@npm:6.5.0-prerelease.72":
5081-
version: 6.5.0-prerelease.72
5082-
resolution: "@patternfly/patternfly@npm:6.5.0-prerelease.72"
5083-
checksum: 10c0/b8d92a11b287d06efad3f410eb356ad60cbbdac3fbcb1e58a99c792253f81e7fcf154f57b0e5a40fbb9d7361364dab02925ecf21db2877e643a23101b8b0745a
5073+
"@patternfly/patternfly@npm:6.5.0-prerelease.75":
5074+
version: 6.5.0-prerelease.75
5075+
resolution: "@patternfly/patternfly@npm:6.5.0-prerelease.75"
5076+
checksum: 10c0/b2188c3befaff75716150370ccfffda4770a67615c3837af293559d8434aa965a3b5882eb1eaba9347a0871f44786555b0cd4824e8e4f34398184344a3aeb975
50845077
languageName: node
50855078
linkType: hard
50865079

@@ -5178,7 +5171,7 @@ __metadata:
51785171
version: 0.0.0-use.local
51795172
resolution: "@patternfly/react-core@workspace:packages/react-core"
51805173
dependencies:
5181-
"@patternfly/patternfly": "npm:6.5.0-prerelease.72"
5174+
"@patternfly/patternfly": "npm:6.5.0-prerelease.75"
51825175
"@patternfly/react-icons": "workspace:^"
51835176
"@patternfly/react-styles": "workspace:^"
51845177
"@patternfly/react-tokens": "workspace:^"
@@ -5199,7 +5192,7 @@ __metadata:
51995192
resolution: "@patternfly/react-docs@workspace:packages/react-docs"
52005193
dependencies:
52015194
"@patternfly/documentation-framework": "npm:^6.36.8"
5202-
"@patternfly/patternfly": "npm:6.5.0-prerelease.72"
5195+
"@patternfly/patternfly": "npm:6.5.0-prerelease.75"
52035196
"@patternfly/patternfly-a11y": "npm:5.1.0"
52045197
"@patternfly/react-charts": "workspace:^"
52055198
"@patternfly/react-code-editor": "workspace:^"
@@ -5239,7 +5232,7 @@ __metadata:
52395232
"@fortawesome/free-brands-svg-icons": "npm:^5.15.4"
52405233
"@fortawesome/free-regular-svg-icons": "npm:^5.15.4"
52415234
"@fortawesome/free-solid-svg-icons": "npm:^5.15.4"
5242-
"@patternfly/patternfly": "npm:6.5.0-prerelease.71"
5235+
"@patternfly/patternfly": "npm:6.5.0-prerelease.75"
52435236
"@rhds/icons": "npm:^2.1.0"
52445237
fs-extra: "npm:^11.3.3"
52455238
tslib: "npm:^2.8.1"
@@ -5326,7 +5319,7 @@ __metadata:
53265319
version: 0.0.0-use.local
53275320
resolution: "@patternfly/react-styles@workspace:packages/react-styles"
53285321
dependencies:
5329-
"@patternfly/patternfly": "npm:6.5.0-prerelease.72"
5322+
"@patternfly/patternfly": "npm:6.5.0-prerelease.75"
53305323
change-case: "npm:^5.4.4"
53315324
fs-extra: "npm:^11.3.3"
53325325
languageName: unknown
@@ -5368,7 +5361,7 @@ __metadata:
53685361
resolution: "@patternfly/react-tokens@workspace:packages/react-tokens"
53695362
dependencies:
53705363
"@adobe/css-tools": "npm:^4.4.4"
5371-
"@patternfly/patternfly": "npm:6.5.0-prerelease.72"
5364+
"@patternfly/patternfly": "npm:6.5.0-prerelease.75"
53725365
fs-extra: "npm:^11.3.3"
53735366
languageName: unknown
53745367
linkType: soft

0 commit comments

Comments
 (0)