@patternfly/react-templates 1.0.0-prerelease.3 → 1.0.0-prerelease.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/components/package.json +1 -1
- package/dist/dynamic/components/Select/package.json +1 -1
- package/dist/esm/components/Select/CheckboxSelect.d.ts +24 -0
- package/dist/esm/components/Select/CheckboxSelect.d.ts.map +1 -0
- package/dist/esm/components/Select/CheckboxSelect.js +37 -0
- package/dist/esm/components/Select/CheckboxSelect.js.map +1 -0
- package/dist/esm/components/Select/index.d.ts +1 -0
- package/dist/esm/components/Select/index.d.ts.map +1 -1
- package/dist/esm/components/Select/index.js +1 -0
- package/dist/esm/components/Select/index.js.map +1 -1
- package/dist/js/components/Select/CheckboxSelect.d.ts +24 -0
- package/dist/js/components/Select/CheckboxSelect.d.ts.map +1 -0
- package/dist/js/components/Select/CheckboxSelect.js +40 -0
- package/dist/js/components/Select/CheckboxSelect.js.map +1 -0
- package/dist/js/components/Select/index.d.ts +1 -0
- package/dist/js/components/Select/index.d.ts.map +1 -1
- package/dist/js/components/Select/index.js +1 -0
- package/dist/js/components/Select/index.js.map +1 -1
- package/dist/umd/react-templates.min.js +1 -1
- package/package.json +3 -3
- package/src/components/Select/CheckboxSelect.test.tsx +256 -0
- package/src/components/Select/CheckboxSelect.tsx +113 -0
- package/src/components/Select/CheckboxSelectSnapshots.test.tsx +32 -0
- package/src/components/Select/__snapshots__/CheckboxSelectSnapshots.test.tsx.snap +212 -0
- package/src/components/Select/examples/CheckboxSelectDemo.tsx +13 -0
- package/src/components/Select/examples/SelectTemplates.md +7 -2
- package/src/components/Select/index.ts +1 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { render, screen, waitForElementToBeRemoved } from '@testing-library/react';
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
4
|
+
import { CheckboxSelect } from './CheckboxSelect';
|
|
5
|
+
import styles from '@patternfly/react-styles/css/components/Badge/badge';
|
|
6
|
+
|
|
7
|
+
test('renders checkbox select with options', async () => {
|
|
8
|
+
const initialOptions = [
|
|
9
|
+
{ content: 'Option 1', value: 'option1' },
|
|
10
|
+
{ content: 'Option 2', value: 'option2' },
|
|
11
|
+
{ content: 'Option 3', value: 'option3' }
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const user = userEvent.setup();
|
|
15
|
+
|
|
16
|
+
render(<CheckboxSelect initialOptions={initialOptions} />);
|
|
17
|
+
|
|
18
|
+
const toggle = screen.getByRole('button', { name: 'Filter by status' });
|
|
19
|
+
|
|
20
|
+
await user.click(toggle);
|
|
21
|
+
|
|
22
|
+
const option1 = screen.getByRole('checkbox', { name: 'Option 1' });
|
|
23
|
+
const option2 = screen.getByRole('checkbox', { name: 'Option 2' });
|
|
24
|
+
const option3 = screen.getByRole('checkbox', { name: 'Option 3' });
|
|
25
|
+
|
|
26
|
+
expect(option1).toBeInTheDocument();
|
|
27
|
+
expect(option2).toBeInTheDocument();
|
|
28
|
+
expect(option3).toBeInTheDocument();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('selects options when clicked', async () => {
|
|
32
|
+
const initialOptions = [
|
|
33
|
+
{ content: 'Option 1', value: 'option1' },
|
|
34
|
+
{ content: 'Option 2', value: 'option2' },
|
|
35
|
+
{ content: 'Option 3', value: 'option3' }
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const user = userEvent.setup();
|
|
39
|
+
|
|
40
|
+
render(<CheckboxSelect initialOptions={initialOptions} />);
|
|
41
|
+
|
|
42
|
+
const toggle = screen.getByRole('button', { name: 'Filter by status' });
|
|
43
|
+
|
|
44
|
+
await user.click(toggle);
|
|
45
|
+
|
|
46
|
+
const option1 = screen.getByRole('checkbox', { name: 'Option 1' });
|
|
47
|
+
|
|
48
|
+
expect(option1).not.toBeChecked();
|
|
49
|
+
|
|
50
|
+
await user.click(option1);
|
|
51
|
+
|
|
52
|
+
expect(option1).toBeChecked();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('deselects options when an already selected option is clicked', async () => {
|
|
56
|
+
const initialOptions = [
|
|
57
|
+
{ content: 'Option 1', value: 'option1' },
|
|
58
|
+
{ content: 'Option 2', value: 'option2' },
|
|
59
|
+
{ content: 'Option 3', value: 'option3' }
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
const user = userEvent.setup();
|
|
63
|
+
|
|
64
|
+
render(<CheckboxSelect initialOptions={initialOptions} />);
|
|
65
|
+
|
|
66
|
+
const toggle = screen.getByRole('button', { name: 'Filter by status' });
|
|
67
|
+
|
|
68
|
+
await user.click(toggle);
|
|
69
|
+
|
|
70
|
+
const option1 = screen.getByRole('checkbox', { name: 'Option 1' });
|
|
71
|
+
|
|
72
|
+
await user.click(option1);
|
|
73
|
+
await user.click(option1);
|
|
74
|
+
|
|
75
|
+
expect(option1).not.toBeChecked();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('calls the onSelect callback with the selected value when an option is selected', async () => {
|
|
79
|
+
const initialOptions = [
|
|
80
|
+
{ content: 'Option 1', value: 'option1' },
|
|
81
|
+
{ content: 'Option 2', value: 'option2' },
|
|
82
|
+
{ content: 'Option 3', value: 'option3' }
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
const user = userEvent.setup();
|
|
86
|
+
const onSelectMock = jest.fn();
|
|
87
|
+
|
|
88
|
+
render(<CheckboxSelect initialOptions={initialOptions} onSelect={onSelectMock} />);
|
|
89
|
+
|
|
90
|
+
const toggle = screen.getByRole('button', { name: 'Filter by status' });
|
|
91
|
+
|
|
92
|
+
await user.click(toggle);
|
|
93
|
+
|
|
94
|
+
const option1 = screen.getByRole('checkbox', { name: 'Option 1' });
|
|
95
|
+
|
|
96
|
+
await user.click(option1);
|
|
97
|
+
|
|
98
|
+
expect(onSelectMock).toHaveBeenCalledTimes(1);
|
|
99
|
+
expect(onSelectMock).toHaveBeenCalledWith(expect.anything(), 'option1');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('does not call the onSelect callback when no options are selected', async () => {
|
|
103
|
+
const initialOptions = [
|
|
104
|
+
{ content: 'Option 1', value: 'option1' },
|
|
105
|
+
{ content: 'Option 2', value: 'option2' },
|
|
106
|
+
{ content: 'Option 3', value: 'option3' }
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
const user = userEvent.setup();
|
|
110
|
+
const onSelectMock = jest.fn();
|
|
111
|
+
|
|
112
|
+
render(<CheckboxSelect initialOptions={initialOptions} onSelect={onSelectMock} />);
|
|
113
|
+
|
|
114
|
+
const toggle = screen.getByRole('button', { name: 'Filter by status' });
|
|
115
|
+
|
|
116
|
+
await user.click(toggle);
|
|
117
|
+
|
|
118
|
+
expect(onSelectMock).not.toHaveBeenCalled();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test('toggles the select menu when the toggle button is clicked', async () => {
|
|
122
|
+
const initialOptions = [
|
|
123
|
+
{ content: 'Option 1', value: 'option1' },
|
|
124
|
+
{ content: 'Option 2', value: 'option2' },
|
|
125
|
+
{ content: 'Option 3', value: 'option3' }
|
|
126
|
+
];
|
|
127
|
+
|
|
128
|
+
const user = userEvent.setup();
|
|
129
|
+
|
|
130
|
+
render(<CheckboxSelect initialOptions={initialOptions} />);
|
|
131
|
+
|
|
132
|
+
const toggleButton = screen.getByRole('button', { name: 'Filter by status' });
|
|
133
|
+
|
|
134
|
+
await user.click(toggleButton);
|
|
135
|
+
|
|
136
|
+
expect(screen.getByRole('menu')).toBeInTheDocument();
|
|
137
|
+
|
|
138
|
+
await user.click(toggleButton);
|
|
139
|
+
|
|
140
|
+
await waitForElementToBeRemoved(() => screen.queryByRole('menu'));
|
|
141
|
+
|
|
142
|
+
expect(screen.queryByRole('menu')).not.toBeInTheDocument();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test('displays custom toggle content', async () => {
|
|
146
|
+
const initialOptions = [
|
|
147
|
+
{ content: 'Option 1', value: 'option1' },
|
|
148
|
+
{ content: 'Option 2', value: 'option2' },
|
|
149
|
+
{ content: 'Option 3', value: 'option3' }
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
render(<CheckboxSelect initialOptions={initialOptions} toggleContent="Custom Toggle" />);
|
|
153
|
+
|
|
154
|
+
const toggleButton = screen.getByRole('button', { name: 'Custom Toggle' });
|
|
155
|
+
|
|
156
|
+
expect(toggleButton).toBeInTheDocument();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('calls the onToggle callback when the select opens or closes', async () => {
|
|
160
|
+
const initialOptions = [
|
|
161
|
+
{ content: 'Option 1', value: 'option1' },
|
|
162
|
+
{ content: 'Option 2', value: 'option2' },
|
|
163
|
+
{ content: 'Option 3', value: 'option3' }
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
const user = userEvent.setup();
|
|
167
|
+
const onToggleMock = jest.fn();
|
|
168
|
+
|
|
169
|
+
render(<CheckboxSelect initialOptions={initialOptions} onToggle={onToggleMock} />);
|
|
170
|
+
|
|
171
|
+
const toggle = screen.getByRole('button', { name: 'Filter by status' });
|
|
172
|
+
|
|
173
|
+
await user.click(toggle);
|
|
174
|
+
|
|
175
|
+
expect(onToggleMock).toHaveBeenCalledTimes(1);
|
|
176
|
+
expect(onToggleMock).toHaveBeenCalledWith(true);
|
|
177
|
+
|
|
178
|
+
await user.click(toggle);
|
|
179
|
+
|
|
180
|
+
expect(onToggleMock).toHaveBeenCalledTimes(2);
|
|
181
|
+
expect(onToggleMock).toHaveBeenCalledWith(false);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test('does not call the onToggle callback when the toggle is not clicked', async () => {
|
|
185
|
+
const initialOptions = [
|
|
186
|
+
{ content: 'Option 1', value: 'option1' },
|
|
187
|
+
{ content: 'Option 2', value: 'option2' },
|
|
188
|
+
{ content: 'Option 3', value: 'option3' }
|
|
189
|
+
];
|
|
190
|
+
|
|
191
|
+
const onToggleMock = jest.fn();
|
|
192
|
+
|
|
193
|
+
render(<CheckboxSelect initialOptions={initialOptions} onToggle={onToggleMock} />);
|
|
194
|
+
|
|
195
|
+
expect(onToggleMock).not.toHaveBeenCalled();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test('disables the select when isDisabled prop is true', async () => {
|
|
199
|
+
const initialOptions = [
|
|
200
|
+
{ content: 'Option 1', value: 'option1' },
|
|
201
|
+
{ content: 'Option 2', value: 'option2' },
|
|
202
|
+
{ content: 'Option 3', value: 'option3' }
|
|
203
|
+
];
|
|
204
|
+
|
|
205
|
+
const user = userEvent.setup();
|
|
206
|
+
|
|
207
|
+
render(<CheckboxSelect initialOptions={initialOptions} isDisabled={true} />);
|
|
208
|
+
|
|
209
|
+
const toggleButton = screen.getByRole('button', { name: 'Filter by status' });
|
|
210
|
+
|
|
211
|
+
expect(toggleButton).toBeDisabled();
|
|
212
|
+
|
|
213
|
+
await user.click(toggleButton);
|
|
214
|
+
|
|
215
|
+
expect(screen.queryByRole('menu')).not.toBeInTheDocument();
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
test('passes other SelectOption props to the SelectOption component', async () => {
|
|
219
|
+
const initialOptions = [{ content: 'Option 1', value: 'option1', isDisabled: true }];
|
|
220
|
+
|
|
221
|
+
const user = userEvent.setup();
|
|
222
|
+
|
|
223
|
+
render(<CheckboxSelect initialOptions={initialOptions} />);
|
|
224
|
+
|
|
225
|
+
const toggle = screen.getByRole('button', { name: 'Filter by status' });
|
|
226
|
+
|
|
227
|
+
await user.click(toggle);
|
|
228
|
+
|
|
229
|
+
const option1 = screen.getByRole('checkbox', { name: 'Option 1' });
|
|
230
|
+
|
|
231
|
+
expect(option1).toBeDisabled();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test('displays the badge count when options are selected', async () => {
|
|
235
|
+
const initialOptions = [
|
|
236
|
+
{ content: 'Option 1', value: 'option1' },
|
|
237
|
+
{ content: 'Option 2', value: 'option2' },
|
|
238
|
+
{ content: 'Option 3', value: 'option3' }
|
|
239
|
+
];
|
|
240
|
+
|
|
241
|
+
const user = userEvent.setup();
|
|
242
|
+
|
|
243
|
+
render(<CheckboxSelect initialOptions={initialOptions} />);
|
|
244
|
+
|
|
245
|
+
const toggle = screen.getByRole('button', { name: 'Filter by status' });
|
|
246
|
+
|
|
247
|
+
await user.click(toggle);
|
|
248
|
+
|
|
249
|
+
const option1 = screen.getByRole('checkbox', { name: 'Option 1' });
|
|
250
|
+
|
|
251
|
+
expect(screen.queryByText('1')).not.toBeInTheDocument();
|
|
252
|
+
|
|
253
|
+
await user.click(option1);
|
|
254
|
+
|
|
255
|
+
expect(screen.getByText('1')).toHaveClass(styles.badge, 'pf-m-read');
|
|
256
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Badge,
|
|
4
|
+
MenuToggle,
|
|
5
|
+
MenuToggleElement,
|
|
6
|
+
Select,
|
|
7
|
+
SelectList,
|
|
8
|
+
SelectOption,
|
|
9
|
+
SelectOptionProps
|
|
10
|
+
} from '@patternfly/react-core';
|
|
11
|
+
|
|
12
|
+
export interface CheckboxSelectOption extends Omit<SelectOptionProps, 'content'> {
|
|
13
|
+
/** Content of the select option. */
|
|
14
|
+
content: React.ReactNode;
|
|
15
|
+
/** Value of the select option. */
|
|
16
|
+
value: string | number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface CheckboxSelectProps {
|
|
20
|
+
/** @hide Forwarded ref */
|
|
21
|
+
innerRef?: React.Ref<any>;
|
|
22
|
+
/** Initial options of the select. */
|
|
23
|
+
initialOptions?: CheckboxSelectOption[];
|
|
24
|
+
/** Callback triggered on selection. */
|
|
25
|
+
onSelect?: (_event: React.MouseEvent<Element, MouseEvent>, value?: string | number) => void;
|
|
26
|
+
/** Callback triggered when the select opens or closes. */
|
|
27
|
+
onToggle?: (nextIsOpen: boolean) => void;
|
|
28
|
+
/** Flag indicating the select should be disabled. */
|
|
29
|
+
isDisabled?: boolean;
|
|
30
|
+
/** Content of the toggle. Defaults to the selected option. */
|
|
31
|
+
toggleContent?: React.ReactNode;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const CheckboxSelectBase: React.FunctionComponent<CheckboxSelectProps> = ({
|
|
35
|
+
innerRef,
|
|
36
|
+
initialOptions,
|
|
37
|
+
isDisabled,
|
|
38
|
+
onSelect: passedOnSelect,
|
|
39
|
+
onToggle,
|
|
40
|
+
toggleContent,
|
|
41
|
+
...props
|
|
42
|
+
}: CheckboxSelectProps) => {
|
|
43
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
44
|
+
const [selected, setSelected] = React.useState<string[]>([]);
|
|
45
|
+
|
|
46
|
+
const checkboxSelectOptions = initialOptions?.map((option) => {
|
|
47
|
+
const { content, value, ...props } = option;
|
|
48
|
+
const isSelected = selected.includes(`${value}`);
|
|
49
|
+
return (
|
|
50
|
+
<SelectOption {...props} value={value} key={value} hasCheckbox isSelected={isSelected}>
|
|
51
|
+
{content}
|
|
52
|
+
</SelectOption>
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const onToggleClick = () => {
|
|
57
|
+
onToggle && onToggle(!isOpen);
|
|
58
|
+
setIsOpen(!isOpen);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const onSelect = (event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {
|
|
62
|
+
const valueString = `${value}`;
|
|
63
|
+
if (selected.includes(valueString)) {
|
|
64
|
+
setSelected((prevSelected) => prevSelected.filter((item) => item !== valueString));
|
|
65
|
+
} else {
|
|
66
|
+
setSelected((prevSelected) => [...prevSelected, valueString]);
|
|
67
|
+
}
|
|
68
|
+
passedOnSelect && passedOnSelect(event, value);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const defaultToggleContent = (
|
|
72
|
+
<>
|
|
73
|
+
Filter by status
|
|
74
|
+
{selected.length > 0 && <Badge isRead>{selected.length}</Badge>}
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
|
|
79
|
+
<MenuToggle
|
|
80
|
+
ref={toggleRef}
|
|
81
|
+
onClick={onToggleClick}
|
|
82
|
+
isExpanded={isOpen}
|
|
83
|
+
isDisabled={isDisabled}
|
|
84
|
+
style={
|
|
85
|
+
{
|
|
86
|
+
width: '200px'
|
|
87
|
+
} as React.CSSProperties
|
|
88
|
+
}
|
|
89
|
+
>
|
|
90
|
+
{toggleContent || defaultToggleContent}
|
|
91
|
+
</MenuToggle>
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<Select
|
|
96
|
+
id="checkbox-select"
|
|
97
|
+
isOpen={isOpen}
|
|
98
|
+
selected={selected}
|
|
99
|
+
onSelect={onSelect}
|
|
100
|
+
onOpenChange={(isOpen) => setIsOpen(isOpen)}
|
|
101
|
+
toggle={toggle}
|
|
102
|
+
ref={innerRef}
|
|
103
|
+
role="menu"
|
|
104
|
+
{...props}
|
|
105
|
+
>
|
|
106
|
+
<SelectList>{checkboxSelectOptions}</SelectList>
|
|
107
|
+
</Select>
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const CheckboxSelect = React.forwardRef((props: CheckboxSelectProps, ref: React.Ref<any>) => (
|
|
112
|
+
<CheckboxSelectBase {...props} innerRef={ref} />
|
|
113
|
+
));
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
4
|
+
import { CheckboxSelect } from './CheckboxSelect';
|
|
5
|
+
|
|
6
|
+
jest.mock('@patternfly/react-core/dist/js/helpers/GenerateId/GenerateId', () => ({
|
|
7
|
+
GenerateId: ({ children }) => children('generated-id')
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
test('checkbox select with no props snapshot', () => {
|
|
11
|
+
const { asFragment } = render(<CheckboxSelect />);
|
|
12
|
+
|
|
13
|
+
expect(asFragment()).toMatchSnapshot();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('opened checkbox select snapshot', async () => {
|
|
17
|
+
const initialOptions = [
|
|
18
|
+
{ content: 'Option 1', value: 'option1' },
|
|
19
|
+
{ content: 'Option 2', value: 'option2' },
|
|
20
|
+
{ content: 'Option 3', value: 'option3' }
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const user = userEvent.setup();
|
|
24
|
+
|
|
25
|
+
const { asFragment } = render(<CheckboxSelect initialOptions={initialOptions} />);
|
|
26
|
+
|
|
27
|
+
const toggle = screen.getByRole('button', { name: 'Filter by status' });
|
|
28
|
+
|
|
29
|
+
await user.click(toggle);
|
|
30
|
+
|
|
31
|
+
expect(asFragment()).toMatchSnapshot();
|
|
32
|
+
});
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`checkbox select with no props snapshot 1`] = `
|
|
4
|
+
<DocumentFragment>
|
|
5
|
+
<button
|
|
6
|
+
aria-expanded="false"
|
|
7
|
+
class="pf-v5-c-menu-toggle"
|
|
8
|
+
style="width: 200px;"
|
|
9
|
+
type="button"
|
|
10
|
+
>
|
|
11
|
+
<span
|
|
12
|
+
class="pf-v5-c-menu-toggle__text"
|
|
13
|
+
>
|
|
14
|
+
Filter by status
|
|
15
|
+
</span>
|
|
16
|
+
<span
|
|
17
|
+
class="pf-v5-c-menu-toggle__controls"
|
|
18
|
+
>
|
|
19
|
+
<span
|
|
20
|
+
class="pf-v5-c-menu-toggle__toggle-icon"
|
|
21
|
+
>
|
|
22
|
+
<svg
|
|
23
|
+
aria-hidden="true"
|
|
24
|
+
class="pf-v5-svg"
|
|
25
|
+
fill="currentColor"
|
|
26
|
+
height="1em"
|
|
27
|
+
role="img"
|
|
28
|
+
viewBox="0 0 320 512"
|
|
29
|
+
width="1em"
|
|
30
|
+
>
|
|
31
|
+
<path
|
|
32
|
+
d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"
|
|
33
|
+
/>
|
|
34
|
+
</svg>
|
|
35
|
+
</span>
|
|
36
|
+
</span>
|
|
37
|
+
</button>
|
|
38
|
+
</DocumentFragment>
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
exports[`opened checkbox select snapshot 1`] = `
|
|
42
|
+
<DocumentFragment>
|
|
43
|
+
<button
|
|
44
|
+
aria-expanded="true"
|
|
45
|
+
class="pf-v5-c-menu-toggle pf-m-expanded"
|
|
46
|
+
style="width: 200px;"
|
|
47
|
+
type="button"
|
|
48
|
+
>
|
|
49
|
+
<span
|
|
50
|
+
class="pf-v5-c-menu-toggle__text"
|
|
51
|
+
>
|
|
52
|
+
Filter by status
|
|
53
|
+
</span>
|
|
54
|
+
<span
|
|
55
|
+
class="pf-v5-c-menu-toggle__controls"
|
|
56
|
+
>
|
|
57
|
+
<span
|
|
58
|
+
class="pf-v5-c-menu-toggle__toggle-icon"
|
|
59
|
+
>
|
|
60
|
+
<svg
|
|
61
|
+
aria-hidden="true"
|
|
62
|
+
class="pf-v5-svg"
|
|
63
|
+
fill="currentColor"
|
|
64
|
+
height="1em"
|
|
65
|
+
role="img"
|
|
66
|
+
viewBox="0 0 320 512"
|
|
67
|
+
width="1em"
|
|
68
|
+
>
|
|
69
|
+
<path
|
|
70
|
+
d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"
|
|
71
|
+
/>
|
|
72
|
+
</svg>
|
|
73
|
+
</span>
|
|
74
|
+
</span>
|
|
75
|
+
</button>
|
|
76
|
+
<div
|
|
77
|
+
class="pf-v5-c-menu"
|
|
78
|
+
data-ouia-component-id="OUIA-Generated-Select-3"
|
|
79
|
+
data-ouia-component-type="PF5/Select"
|
|
80
|
+
data-ouia-safe="true"
|
|
81
|
+
data-popper-escaped="true"
|
|
82
|
+
data-popper-placement="bottom-start"
|
|
83
|
+
data-popper-reference-hidden="true"
|
|
84
|
+
id="checkbox-select"
|
|
85
|
+
style="position: absolute; left: 0px; top: 0px; z-index: 9999; opacity: 1; transition: opacity 0ms cubic-bezier(.54, 1.5, .38, 1.11); min-width: 0px; transform: translate(0px, 0px);"
|
|
86
|
+
>
|
|
87
|
+
<div
|
|
88
|
+
class="pf-v5-c-menu__content"
|
|
89
|
+
>
|
|
90
|
+
<ul
|
|
91
|
+
class="pf-v5-c-menu__list"
|
|
92
|
+
role="menu"
|
|
93
|
+
>
|
|
94
|
+
<li
|
|
95
|
+
class="pf-v5-c-menu__list-item"
|
|
96
|
+
role="menuitem"
|
|
97
|
+
>
|
|
98
|
+
<label
|
|
99
|
+
class="pf-v5-c-menu__item"
|
|
100
|
+
for="generated-id"
|
|
101
|
+
tabindex="-1"
|
|
102
|
+
>
|
|
103
|
+
<span
|
|
104
|
+
class="pf-v5-c-menu__item-main"
|
|
105
|
+
>
|
|
106
|
+
<span
|
|
107
|
+
class="pf-v5-c-menu__item-check"
|
|
108
|
+
>
|
|
109
|
+
<span
|
|
110
|
+
class="pf-v5-c-check pf-m-standalone"
|
|
111
|
+
>
|
|
112
|
+
<input
|
|
113
|
+
aria-disabled="false"
|
|
114
|
+
aria-invalid="false"
|
|
115
|
+
class="pf-v5-c-check__input"
|
|
116
|
+
data-ouia-component-id="OUIA-Generated-Checkbox-1"
|
|
117
|
+
data-ouia-component-type="PF5/Checkbox"
|
|
118
|
+
data-ouia-safe="true"
|
|
119
|
+
id="generated-id"
|
|
120
|
+
type="checkbox"
|
|
121
|
+
/>
|
|
122
|
+
</span>
|
|
123
|
+
</span>
|
|
124
|
+
<span
|
|
125
|
+
class="pf-v5-c-menu__item-text"
|
|
126
|
+
>
|
|
127
|
+
Option 1
|
|
128
|
+
</span>
|
|
129
|
+
</span>
|
|
130
|
+
</label>
|
|
131
|
+
</li>
|
|
132
|
+
<li
|
|
133
|
+
class="pf-v5-c-menu__list-item"
|
|
134
|
+
role="menuitem"
|
|
135
|
+
>
|
|
136
|
+
<label
|
|
137
|
+
class="pf-v5-c-menu__item"
|
|
138
|
+
for="generated-id"
|
|
139
|
+
tabindex="-1"
|
|
140
|
+
>
|
|
141
|
+
<span
|
|
142
|
+
class="pf-v5-c-menu__item-main"
|
|
143
|
+
>
|
|
144
|
+
<span
|
|
145
|
+
class="pf-v5-c-menu__item-check"
|
|
146
|
+
>
|
|
147
|
+
<span
|
|
148
|
+
class="pf-v5-c-check pf-m-standalone"
|
|
149
|
+
>
|
|
150
|
+
<input
|
|
151
|
+
aria-disabled="false"
|
|
152
|
+
aria-invalid="false"
|
|
153
|
+
class="pf-v5-c-check__input"
|
|
154
|
+
data-ouia-component-id="OUIA-Generated-Checkbox-2"
|
|
155
|
+
data-ouia-component-type="PF5/Checkbox"
|
|
156
|
+
data-ouia-safe="true"
|
|
157
|
+
id="generated-id"
|
|
158
|
+
type="checkbox"
|
|
159
|
+
/>
|
|
160
|
+
</span>
|
|
161
|
+
</span>
|
|
162
|
+
<span
|
|
163
|
+
class="pf-v5-c-menu__item-text"
|
|
164
|
+
>
|
|
165
|
+
Option 2
|
|
166
|
+
</span>
|
|
167
|
+
</span>
|
|
168
|
+
</label>
|
|
169
|
+
</li>
|
|
170
|
+
<li
|
|
171
|
+
class="pf-v5-c-menu__list-item"
|
|
172
|
+
role="menuitem"
|
|
173
|
+
>
|
|
174
|
+
<label
|
|
175
|
+
class="pf-v5-c-menu__item"
|
|
176
|
+
for="generated-id"
|
|
177
|
+
tabindex="-1"
|
|
178
|
+
>
|
|
179
|
+
<span
|
|
180
|
+
class="pf-v5-c-menu__item-main"
|
|
181
|
+
>
|
|
182
|
+
<span
|
|
183
|
+
class="pf-v5-c-menu__item-check"
|
|
184
|
+
>
|
|
185
|
+
<span
|
|
186
|
+
class="pf-v5-c-check pf-m-standalone"
|
|
187
|
+
>
|
|
188
|
+
<input
|
|
189
|
+
aria-disabled="false"
|
|
190
|
+
aria-invalid="false"
|
|
191
|
+
class="pf-v5-c-check__input"
|
|
192
|
+
data-ouia-component-id="OUIA-Generated-Checkbox-3"
|
|
193
|
+
data-ouia-component-type="PF5/Checkbox"
|
|
194
|
+
data-ouia-safe="true"
|
|
195
|
+
id="generated-id"
|
|
196
|
+
type="checkbox"
|
|
197
|
+
/>
|
|
198
|
+
</span>
|
|
199
|
+
</span>
|
|
200
|
+
<span
|
|
201
|
+
class="pf-v5-c-menu__item-text"
|
|
202
|
+
>
|
|
203
|
+
Option 3
|
|
204
|
+
</span>
|
|
205
|
+
</span>
|
|
206
|
+
</label>
|
|
207
|
+
</li>
|
|
208
|
+
</ul>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
</DocumentFragment>
|
|
212
|
+
`;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { CheckboxSelect, CheckboxSelectOption } from '@patternfly/react-templates';
|
|
3
|
+
|
|
4
|
+
export const SelectBasic: React.FunctionComponent = () => {
|
|
5
|
+
const initialOptions: CheckboxSelectOption[] = [
|
|
6
|
+
{ content: 'Option 1', value: 'option-1' },
|
|
7
|
+
{ content: 'Option 2', value: 'option-2' },
|
|
8
|
+
{ content: 'Option 3', value: 'option-3', isDisabled: true },
|
|
9
|
+
{ content: 'Option 4', value: 'option-4' }
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
return <CheckboxSelect initialOptions={initialOptions} />;
|
|
13
|
+
};
|
|
@@ -4,7 +4,7 @@ section: components
|
|
|
4
4
|
subsection: menus
|
|
5
5
|
template: true
|
|
6
6
|
beta: true
|
|
7
|
-
propComponents: ['
|
|
7
|
+
propComponents: ['SelectSimple', 'CheckboxSelect']
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
Note: Templates live in their own package at [@patternfly/react-templates](https://www.npmjs.com/package/@patternfly/react-templates)!
|
|
@@ -12,7 +12,7 @@ Note: Templates live in their own package at [@patternfly/react-templates](https
|
|
|
12
12
|
For custom use cases, please see the select component suite from [@patternfly/react-core](https://www.npmjs.com/package/@patternfly/react-core).
|
|
13
13
|
|
|
14
14
|
import { SelectOption, Checkbox } from '@patternfly/react-core';
|
|
15
|
-
import { SelectSimple } from '@patternfly/react-templates';
|
|
15
|
+
import { SelectSimple, CheckboxSelect } from '@patternfly/react-templates';
|
|
16
16
|
|
|
17
17
|
## Select template examples
|
|
18
18
|
|
|
@@ -21,3 +21,8 @@ import { SelectSimple } from '@patternfly/react-templates';
|
|
|
21
21
|
```ts file="SelectSimpleDemo.tsx"
|
|
22
22
|
|
|
23
23
|
```
|
|
24
|
+
|
|
25
|
+
### Checkbox
|
|
26
|
+
|
|
27
|
+
```ts file="CheckboxSelectDemo.tsx"
|
|
28
|
+
```
|