@patternfly/react-core 4.222.13 → 4.222.14

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-core",
3
- "version": "4.222.13",
3
+ "version": "4.222.14",
4
4
  "description": "This library provides a set of common React components for use with the PatternFly reference implementation.",
5
5
  "main": "dist/js/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -34,16 +34,16 @@
34
34
  "generate": "node scripts/copyStyles.js"
35
35
  },
36
36
  "dependencies": {
37
- "@patternfly/react-icons": "^4.73.13",
38
- "@patternfly/react-styles": "^4.72.13",
39
- "@patternfly/react-tokens": "^4.74.13",
37
+ "@patternfly/react-icons": "^4.73.14",
38
+ "@patternfly/react-styles": "^4.72.14",
39
+ "@patternfly/react-tokens": "^4.74.14",
40
40
  "focus-trap": "6.9.2",
41
41
  "react-dropzone": "9.0.0",
42
42
  "tippy.js": "5.1.2",
43
43
  "tslib": "^2.0.0"
44
44
  },
45
45
  "devDependencies": {
46
- "@patternfly/patternfly": "4.198.1",
46
+ "@patternfly/patternfly": "4.198.2",
47
47
  "@rollup/plugin-commonjs": "^21.0.0",
48
48
  "@rollup/plugin-node-resolve": "^13.0.0",
49
49
  "@rollup/plugin-replace": "^3.0.0",
@@ -60,5 +60,5 @@
60
60
  "react": "^16.8.0 || ^17.0.0",
61
61
  "react-dom": "^16.8.0 || ^17.0.0"
62
62
  },
63
- "gitHead": "12411175163290e8c6dd598cfb5ce53ba58688b3"
63
+ "gitHead": "0d04c7d4c7970f2be7e485e1f4bd0bda94ee5d46"
64
64
  }
@@ -110,15 +110,15 @@ export const Label: React.FunctionComponent<LabelProps> = ({
110
110
  const editableInputRef = React.useRef<HTMLInputElement>();
111
111
 
112
112
  React.useEffect(() => {
113
- document.addEventListener('click', onDocClick);
113
+ document.addEventListener('mousedown', onDocMouseDown);
114
114
  document.addEventListener('keydown', onKeyDown);
115
115
  return () => {
116
- document.removeEventListener('click', onDocClick);
116
+ document.removeEventListener('mousedown', onDocMouseDown);
117
117
  document.removeEventListener('keydown', onKeyDown);
118
118
  };
119
119
  });
120
120
 
121
- const onDocClick = (event: MouseEvent) => {
121
+ const onDocMouseDown = (event: MouseEvent) => {
122
122
  if (
123
123
  isEditableActive &&
124
124
  editableInputRef &&
@@ -58,6 +58,8 @@ export interface LabelGroupProps extends React.HTMLProps<HTMLUListElement> {
58
58
  hasEditableTextArea?: boolean;
59
59
  /** @beta Additional props passed to the editable textarea. */
60
60
  editableTextAreaProps?: any;
61
+ /** @beta Control for adding new labels */
62
+ addLabelControl?: React.ReactNode;
61
63
  }
62
64
 
63
65
  interface LabelGroupState {
@@ -149,6 +151,7 @@ export class LabelGroup extends React.Component<LabelGroupProps, LabelGroupState
149
151
  isEditable,
150
152
  hasEditableTextArea,
151
153
  editableTextAreaProps,
154
+ addLabelControl,
152
155
  /* eslint-enable @typescript-eslint/no-unused-vars */
153
156
  ...rest
154
157
  } = this.props;
@@ -189,6 +192,7 @@ export class LabelGroup extends React.Component<LabelGroupProps, LabelGroupState
189
192
  </Label>
190
193
  </li>
191
194
  )}
195
+ {addLabelControl && <li className={css(styles.labelGroupListItem)}>{addLabelControl}</li>}
192
196
  {isEditable && hasEditableTextArea && (
193
197
  <li className={css(styles.labelGroupListItem, styles.modifiers.textarea)}>
194
198
  <textarea className={css(styles.labelGroupTextarea)} rows={1} tabIndex={0} {...editableTextAreaProps} />
@@ -228,7 +232,7 @@ export class LabelGroup extends React.Component<LabelGroupProps, LabelGroupState
228
232
  );
229
233
  };
230
234
 
231
- return numChildren === 0 ? null : (
235
+ return numChildren === 0 && addLabelControl === undefined ? null : (
232
236
  <GenerateId>{randomId => renderLabelGroup(this.props.id || randomId)}</GenerateId>
233
237
  );
234
238
  }
@@ -40,3 +40,10 @@ import InfoCircleIcon from '@patternfly/react-icons/dist/esm/icons/info-circle-i
40
40
 
41
41
  ```ts file="LabelGroupEditableLabels.tsx" isBeta
42
42
  ```
43
+
44
+ ### Editable labels with add button
45
+
46
+ For additional documentation that showcases adding a new label, see [label group demos](/components/label-group/react-demos).
47
+
48
+ ```ts file="LabelGroupEditableAdd.tsx"
49
+ ```
@@ -0,0 +1,74 @@
1
+ import React from 'react';
2
+ import { LabelGroup, Label } from '@patternfly/react-core';
3
+
4
+ export const LabelGroupEditableAdd: React.FunctionComponent = () => {
5
+ const [idIndex, setIdIndex] = React.useState<number>(3);
6
+ const [labels, setLabels] = React.useState<any>([
7
+ { name: 'Label 1', id: 0 },
8
+ { name: 'Label 2', id: 1 },
9
+ {
10
+ name: 'Label 3',
11
+ props: {
12
+ isEditable: true,
13
+ editableProps: {
14
+ 'aria-label': 'label editable text'
15
+ }
16
+ },
17
+ id: 2
18
+ }
19
+ ]);
20
+
21
+ const onClose = (labelId: string) => {
22
+ setLabels(labels.filter((l: any) => l.id !== labelId));
23
+ };
24
+
25
+ const onEdit = (nextText: string, index: number) => {
26
+ const copy = [...labels];
27
+ copy[index] = { name: nextText, props: labels[index].props, id: labels[index].id };
28
+ setLabels(copy);
29
+ };
30
+
31
+ const onAdd = () => {
32
+ setLabels([
33
+ {
34
+ name: 'New Label',
35
+ props: {
36
+ isEditable: true,
37
+ editableProps: {
38
+ 'aria-label': 'label editable text'
39
+ }
40
+ },
41
+ id: idIndex
42
+ },
43
+ ...labels
44
+ ]);
45
+ setIdIndex(idIndex + 1);
46
+ };
47
+
48
+ return (
49
+ <LabelGroup
50
+ categoryName="Label group 1"
51
+ numLabels={5}
52
+ isEditable
53
+ addLabelControl={
54
+ <Label color="blue" variant="outline" isOverflowLabel onClick={onAdd}>
55
+ Add label
56
+ </Label>
57
+ }
58
+ >
59
+ {labels.map((label, index) => (
60
+ <Label
61
+ key={`${label.name}-${index}`}
62
+ id={`${label.name}-${index}`}
63
+ color="blue"
64
+ onClose={() => onClose(label.id)}
65
+ onEditCancel={prevText => onEdit(prevText, index)}
66
+ onEditComplete={newText => onEdit(newText, index)}
67
+ {...label.props}
68
+ >
69
+ {label.name}
70
+ </Label>
71
+ ))}
72
+ </LabelGroup>
73
+ );
74
+ };
@@ -0,0 +1,138 @@
1
+ import React from 'react';
2
+ import { LabelGroup, Label, Menu, MenuContent, MenuList, MenuItem, Popper } from '@patternfly/react-core';
3
+
4
+ export const LabelGroupEditableAddDropdown: React.FunctionComponent = () => {
5
+ const toggleRef = React.useRef<HTMLDivElement>();
6
+ const menuRef = React.useRef<HTMLDivElement>();
7
+ const containerRef = React.useRef<HTMLDivElement>();
8
+
9
+ const [idIndex, setIdIndex] = React.useState<number>(3);
10
+ const [isOpen, setIsOpen] = React.useState<boolean>(false);
11
+ const [labels, setLabels] = React.useState<any>([
12
+ { name: 'Label 1', id: 0 },
13
+ { name: 'Label 2', id: 1 },
14
+ {
15
+ name: 'Label 3',
16
+ props: {
17
+ isEditable: true,
18
+ editableProps: {
19
+ 'aria-label': 'label editable text'
20
+ }
21
+ },
22
+ id: 2
23
+ }
24
+ ]);
25
+
26
+ const onClose = (labelId: string) => {
27
+ setLabels(labels.filter((l: any) => l.id !== labelId));
28
+ };
29
+
30
+ const onEdit = (nextText: string, index: number) => {
31
+ const copy = [...labels];
32
+ copy[index] = { name: nextText, props: labels[index].props, id: labels[index].id };
33
+ setLabels(copy);
34
+ };
35
+
36
+ const onAdd = (labelText: string) => {
37
+ setLabels([
38
+ {
39
+ name: labelText,
40
+ id: idIndex
41
+ },
42
+ ...labels
43
+ ]);
44
+ setIdIndex(idIndex + 1);
45
+ setIsOpen(!isOpen);
46
+ };
47
+
48
+ const handleMenuKeys = (event: KeyboardEvent) => {
49
+ if (isOpen && menuRef.current.contains(event.target as Node)) {
50
+ if (event.key === 'Escape' || event.key === 'Tab') {
51
+ setIsOpen(!isOpen);
52
+ toggleRef.current.focus();
53
+ }
54
+ }
55
+ };
56
+
57
+ const handleClickOutside = (event: MouseEvent) => {
58
+ if (
59
+ isOpen &&
60
+ !(menuRef.current.contains(event.target as Node) || toggleRef.current.contains(event.target as Node))
61
+ ) {
62
+ setIsOpen(false);
63
+ }
64
+ };
65
+
66
+ React.useEffect(() => {
67
+ window.addEventListener('keydown', handleMenuKeys);
68
+ window.addEventListener('click', handleClickOutside);
69
+ return () => {
70
+ window.removeEventListener('keydown', handleMenuKeys);
71
+ window.removeEventListener('click', handleClickOutside);
72
+ };
73
+ }, [isOpen, menuRef]);
74
+
75
+ const onToggleClick = () => {
76
+ setTimeout(() => {
77
+ if (menuRef.current) {
78
+ const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');
79
+ firstElement && (firstElement as HTMLElement).focus();
80
+ }
81
+ }, 0);
82
+ setIsOpen(!isOpen);
83
+ };
84
+
85
+ const menu = (
86
+ <Menu ref={menuRef} onSelect={(_ev, itemId) => onAdd(itemId.toString())}>
87
+ <MenuContent>
88
+ <MenuList>
89
+ <MenuItem itemId="Label text 1">Label text 1</MenuItem>
90
+ <MenuItem itemId="Label text 2">Label text 2</MenuItem>
91
+ <MenuItem itemId="Label text 3">Label text 3</MenuItem>
92
+ <MenuItem itemId="Label text 4">Label text 4</MenuItem>
93
+ </MenuList>
94
+ </MenuContent>
95
+ </Menu>
96
+ );
97
+
98
+ const toggle = (
99
+ <div ref={toggleRef}>
100
+ <Label color="blue" variant="outline" isOverflowLabel onClick={onToggleClick}>
101
+ Add label
102
+ </Label>
103
+ </div>
104
+ );
105
+
106
+ return (
107
+ <div ref={containerRef}>
108
+ <LabelGroup
109
+ categoryName="Label group 1"
110
+ numLabels={5}
111
+ isEditable
112
+ addLabelControl={
113
+ <Popper
114
+ trigger={toggle}
115
+ popper={menu}
116
+ appendTo={containerRef.current}
117
+ isVisible={isOpen}
118
+ popperMatchesTriggerWidth={false}
119
+ />
120
+ }
121
+ >
122
+ {labels.map((label, index) => (
123
+ <Label
124
+ key={`${label.name}-${index}`}
125
+ id={`${label.name}-${index}`}
126
+ color="blue"
127
+ onClose={() => onClose(label.id)}
128
+ onEditCancel={prevText => onEdit(prevText, index)}
129
+ onEditComplete={newText => onEdit(newText, index)}
130
+ {...label.props}
131
+ >
132
+ {label.name}
133
+ </Label>
134
+ ))}
135
+ </LabelGroup>
136
+ </div>
137
+ );
138
+ };
@@ -0,0 +1,356 @@
1
+ import React from 'react';
2
+ import {
3
+ LabelGroup,
4
+ Label,
5
+ Modal,
6
+ ModalVariant,
7
+ Button,
8
+ Form,
9
+ FormGroup,
10
+ TextInput,
11
+ Menu,
12
+ MenuContent,
13
+ MenuList,
14
+ MenuItem,
15
+ MenuToggle,
16
+ Radio,
17
+ Popper
18
+ } from '@patternfly/react-core';
19
+ import InfoCircleIcon from '@patternfly/react-icons/dist/esm/icons/info-circle-icon';
20
+
21
+ export const LabelGroupEditableAddModal: React.FunctionComponent = () => {
22
+ const [isModalOpen, setModalOpen] = React.useState<boolean>(false);
23
+ const [idIndex, setIdIndex] = React.useState<number>(3);
24
+ const [labelText, setLabelText] = React.useState<string>('');
25
+ const [color, setColor] = React.useState<string>();
26
+ const [icon, setIcon] = React.useState<any>();
27
+ const [labelType, setLabelType] = React.useState<string>('filled');
28
+ const [isClosable, setIsCloseable] = React.useState<boolean>(false);
29
+ const [isEditable, setIsEditable] = React.useState<boolean>(false);
30
+ const labelInputRef = React.useRef();
31
+
32
+ const [isColorOpen, setIsColorOpen] = React.useState<boolean>(false);
33
+ const colorMenuRef = React.useRef<HTMLDivElement>();
34
+ const colorContainerRef = React.useRef<HTMLDivElement>();
35
+ const colorToggleRef = React.useRef<HTMLButtonElement>();
36
+
37
+ const [isIconOpen, setIsIconOpen] = React.useState<boolean>(false);
38
+ const iconMenuRef = React.useRef<HTMLDivElement>();
39
+ const iconContainerRef = React.useRef<HTMLDivElement>();
40
+ const iconToggleRef = React.useRef<HTMLButtonElement>();
41
+
42
+ const [labels, setLabels] = React.useState<any>([
43
+ { name: 'Label 1', id: 0 },
44
+ { name: 'Label 2', id: 1 },
45
+ {
46
+ name: 'Label 3',
47
+ props: {
48
+ isEditable: true,
49
+ editableProps: {
50
+ 'aria-label': 'label editable text'
51
+ }
52
+ },
53
+ id: 2
54
+ }
55
+ ]);
56
+
57
+ const onClose = (labelId: string) => {
58
+ setLabels(labels.filter((l: any) => l.id !== labelId));
59
+ };
60
+
61
+ const onEdit = (nextText: string, index: number) => {
62
+ const copy = [...labels];
63
+ copy[index] = { name: nextText, props: labels[index].props, id: labels[index].id };
64
+ setLabels(copy);
65
+ };
66
+
67
+ const onAdd = () => {
68
+ let labelIcon = null;
69
+ if (icon === 'Info circle icon') {
70
+ labelIcon = <InfoCircleIcon />;
71
+ }
72
+
73
+ setLabels([
74
+ {
75
+ name: labelText || 'New Label',
76
+ props: {
77
+ color: color ? color.toLowerCase() : 'gray',
78
+ icon: labelIcon,
79
+ variant: labelType || 'filled',
80
+ ...(!isClosable && isClosable !== undefined && { onClose: null }),
81
+ isEditable: isEditable !== undefined ? isEditable : true,
82
+ ...(isEditable && {
83
+ editableProps: {
84
+ 'aria-label': 'label editable text'
85
+ }
86
+ })
87
+ },
88
+ id: idIndex
89
+ },
90
+ ...labels
91
+ ]);
92
+ setModalOpen(!isModalOpen);
93
+ setIdIndex(idIndex + 1);
94
+ setLabelText('');
95
+ setColor(null);
96
+ setIcon(null);
97
+ setLabelType('filled');
98
+ setIsCloseable(false);
99
+ setIsEditable(false);
100
+ };
101
+
102
+ const handleModalToggle = () => {
103
+ setModalOpen(!isModalOpen);
104
+ };
105
+
106
+ React.useEffect(() => {
107
+ if (isModalOpen && labelInputRef && labelInputRef.current) {
108
+ (labelInputRef.current as HTMLInputElement).focus();
109
+ }
110
+ }, [isModalOpen]);
111
+
112
+ const handleMenuKeys = (event: KeyboardEvent) => {
113
+ if (isColorOpen && colorMenuRef.current.contains(event.target as Node)) {
114
+ if (event.key === 'Escape' || event.key === 'Tab') {
115
+ setIsColorOpen(!isColorOpen);
116
+ colorToggleRef.current.focus();
117
+ }
118
+ }
119
+ if (isIconOpen && iconMenuRef.current.contains(event.target as Node)) {
120
+ if (event.key === 'Escape' || event.key === 'Tab') {
121
+ setIsIconOpen(!isIconOpen);
122
+ iconToggleRef.current.focus();
123
+ }
124
+ }
125
+ };
126
+
127
+ const handleClickOutside = (event: MouseEvent) => {
128
+ if (isColorOpen && !colorMenuRef.current.contains(event.target as Node)) {
129
+ setIsColorOpen(false);
130
+ }
131
+ if (isIconOpen && !iconMenuRef.current.contains(event.target as Node)) {
132
+ setIsIconOpen(false);
133
+ }
134
+ };
135
+
136
+ React.useEffect(() => {
137
+ window.addEventListener('keydown', handleMenuKeys);
138
+ window.addEventListener('click', handleClickOutside);
139
+ return () => {
140
+ window.removeEventListener('keydown', handleMenuKeys);
141
+ window.removeEventListener('click', handleClickOutside);
142
+ };
143
+ }, [isColorOpen, isIconOpen, colorMenuRef, iconMenuRef]);
144
+
145
+ const onColorToggleClick = (ev: React.MouseEvent) => {
146
+ ev.stopPropagation(); // Stop handleClickOutside from handling
147
+ setTimeout(() => {
148
+ if (colorMenuRef.current) {
149
+ const firstElement = colorMenuRef.current.querySelector('li > button:not(:disabled)');
150
+ firstElement && (firstElement as HTMLElement).focus();
151
+ }
152
+ }, 0);
153
+ setIsColorOpen(!isColorOpen);
154
+ };
155
+
156
+ const colorToggle = (
157
+ <MenuToggle ref={colorToggleRef} onClick={onColorToggleClick} isExpanded={isColorOpen}>
158
+ {color || 'Select'}
159
+ </MenuToggle>
160
+ );
161
+
162
+ const colorMenu = (
163
+ <Menu
164
+ ref={colorMenuRef}
165
+ activeItemId={color}
166
+ onSelect={(_ev, itemId) => {
167
+ setColor(itemId.toString());
168
+ setIsColorOpen(false);
169
+ }}
170
+ selected={color}
171
+ >
172
+ <MenuContent>
173
+ <MenuList>
174
+ <MenuItem itemId="Gray">Gray</MenuItem>
175
+ <MenuItem itemId="Blue">Blue</MenuItem>
176
+ <MenuItem itemId="Green">Green</MenuItem>
177
+ <MenuItem itemId="Orange">Orange</MenuItem>
178
+ <MenuItem itemId="Red">Red</MenuItem>
179
+ <MenuItem itemId="Purple">Purple</MenuItem>
180
+ <MenuItem itemId="Cyan">Cyan</MenuItem>
181
+ </MenuList>
182
+ </MenuContent>
183
+ </Menu>
184
+ );
185
+
186
+ const onIconToggleClick = (ev: React.MouseEvent) => {
187
+ ev.stopPropagation(); // Stop handleClickOutside from handling
188
+ setTimeout(() => {
189
+ if (iconMenuRef.current) {
190
+ const firstElement = iconMenuRef.current.querySelector('li > button:not(:disabled)');
191
+ firstElement && (firstElement as HTMLElement).focus();
192
+ }
193
+ }, 0);
194
+ setIsIconOpen(!isIconOpen);
195
+ };
196
+
197
+ const iconToggle = (
198
+ <MenuToggle ref={iconToggleRef} onClick={onIconToggleClick} isExpanded={isIconOpen}>
199
+ {icon || 'Select'}
200
+ </MenuToggle>
201
+ );
202
+
203
+ const iconMenu = (
204
+ <Menu
205
+ ref={iconMenuRef}
206
+ activeItemId={icon}
207
+ onSelect={(_ev, itemId) => {
208
+ setIcon(itemId.toString());
209
+ setIsIconOpen(false);
210
+ }}
211
+ selected={icon}
212
+ >
213
+ <MenuContent>
214
+ <MenuList>
215
+ <MenuItem itemId="No icon">No icon</MenuItem>
216
+ <MenuItem itemId="Info circle icon">
217
+ <InfoCircleIcon />
218
+ Info circle icon
219
+ </MenuItem>
220
+ </MenuList>
221
+ </MenuContent>
222
+ </Menu>
223
+ );
224
+
225
+ return (
226
+ <div>
227
+ <LabelGroup
228
+ categoryName="Label group 1"
229
+ numLabels={5}
230
+ isEditable
231
+ addLabelControl={
232
+ <Label color="blue" variant="outline" isOverflowLabel onClick={handleModalToggle}>
233
+ Add label
234
+ </Label>
235
+ }
236
+ >
237
+ {labels.map((label, index) => (
238
+ <Label
239
+ key={`${label.name}-${index}`}
240
+ id={`${label.name}-${index}`}
241
+ color="blue"
242
+ onClose={() => onClose(label.id)}
243
+ onEditCancel={prevText => onEdit(prevText, index)}
244
+ onEditComplete={newText => onEdit(newText, index)}
245
+ {...label.props}
246
+ >
247
+ {label.name}
248
+ </Label>
249
+ ))}
250
+ </LabelGroup>
251
+ <Modal
252
+ variant={ModalVariant.small}
253
+ title="Add Label"
254
+ isOpen={isModalOpen}
255
+ onClose={handleModalToggle}
256
+ actions={[
257
+ <Button key="create" variant="primary" form="create-label-form" onClick={onAdd}>
258
+ Save
259
+ </Button>,
260
+ <Button key="cancel" variant="link" onClick={handleModalToggle}>
261
+ Cancel
262
+ </Button>
263
+ ]}
264
+ >
265
+ <Form id="create-label-form">
266
+ <FormGroup label="Label text" fieldId="create-label-form-label-text">
267
+ <TextInput
268
+ type="text"
269
+ id="create-label-form-label-text"
270
+ name="create-label-form-label-text"
271
+ value={labelText}
272
+ onChange={setLabelText}
273
+ ref={labelInputRef}
274
+ />
275
+ </FormGroup>
276
+ <FormGroup label="Color" fieldId="create-label-form-color">
277
+ <div ref={colorContainerRef}>
278
+ <Popper
279
+ trigger={colorToggle}
280
+ popper={colorMenu}
281
+ appendTo={colorContainerRef.current}
282
+ isVisible={isColorOpen}
283
+ popperMatchesTriggerWidth={false}
284
+ />
285
+ </div>
286
+ </FormGroup>
287
+ <FormGroup label="Icon" fieldId="create-label-form-icon">
288
+ <div ref={iconContainerRef}>
289
+ <Popper
290
+ trigger={iconToggle}
291
+ popper={iconMenu}
292
+ appendTo={iconContainerRef.current}
293
+ isVisible={isIconOpen}
294
+ popperMatchesTriggerWidth={false}
295
+ />
296
+ </div>
297
+ </FormGroup>
298
+ <FormGroup label="Label type" fieldId="create-label-form-label-type">
299
+ <Radio
300
+ isChecked={labelType === 'filled'}
301
+ name="filled-label"
302
+ onChange={() => setLabelType('filled')}
303
+ label="Filled"
304
+ id="radio-filled"
305
+ value="check1"
306
+ />
307
+ <Radio
308
+ isChecked={labelType === 'outline'}
309
+ name="outline-label"
310
+ onChange={() => setLabelType('outline')}
311
+ label="Outlined"
312
+ id="radio-outline"
313
+ value="check2"
314
+ />
315
+ </FormGroup>
316
+ <FormGroup label="Dismissable" fieldId="create-label-form-dismissable">
317
+ <Radio
318
+ isChecked={isClosable === true}
319
+ name="closeable-label"
320
+ onChange={() => setIsCloseable(true)}
321
+ label="Yes"
322
+ id="radio-closable"
323
+ value="check1"
324
+ />
325
+ <Radio
326
+ isChecked={isClosable === false}
327
+ name="not-closeable-label"
328
+ onChange={() => setIsCloseable(false)}
329
+ label="No"
330
+ id="radio-not-closable"
331
+ value="check2"
332
+ />
333
+ </FormGroup>
334
+ <FormGroup label="Editable" fieldId="create-label-form-editable">
335
+ <Radio
336
+ isChecked={isEditable === true}
337
+ name="editable-label"
338
+ onChange={() => setIsEditable(true)}
339
+ label="Yes"
340
+ id="radio-editable"
341
+ value="check3"
342
+ />
343
+ <Radio
344
+ isChecked={isEditable === false}
345
+ name="not-editable-label"
346
+ onChange={() => setIsEditable(false)}
347
+ label="No"
348
+ id="radio-not-editable"
349
+ value="check4"
350
+ />
351
+ </FormGroup>
352
+ </Form>
353
+ </Modal>
354
+ </div>
355
+ );
356
+ };
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: Label group
3
+ section: components
4
+ ---
5
+
6
+ import InfoCircleIcon from '@patternfly/react-icons/dist/esm/icons/info-circle-icon';
7
+
8
+ ## Demos
9
+
10
+ ### Editable labels with add dropdown
11
+
12
+ ```ts file="../components/LabelGroup/examples/LabelGroupEditableAddDropdown.tsx"
13
+ ```
14
+
15
+ ### Editable labels with add modal
16
+
17
+ ```ts file="../components/LabelGroup/examples/LabelGroupEditableAddModal.tsx"
18
+ ```