Skip to content

Commit 66fef93

Browse files
committed
docs(CodeEditor): add configuration example from OCP
1 parent 263c485 commit 66fef93

2 files changed

Lines changed: 174 additions & 0 deletions

File tree

packages/react-code-editor/src/components/CodeEditor/examples/CodeEditor.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ Note: Code editor lives in its own package at [@patternfly/react-code-editor](ht
99

1010
import { Fragment, useState } from 'react';
1111
import { CodeEditor, CodeEditorControl, Language } from '@patternfly/react-code-editor';
12+
import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon';
13+
import HashtagIcon from '@patternfly/react-icons/dist/esm/icons/hashtag-icon';
14+
import MapIcon from '@patternfly/react-icons/dist/esm/icons/map-icon';
15+
import MoonIcon from '@patternfly/react-icons/dist/esm/icons/moon-icon';
1216
import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon';
1317

1418
## Examples
@@ -50,3 +54,9 @@ These examples below are the shortcuts that we recommend describing in the popov
5054
```ts file="CodeEditorCustomControl.tsx"
5155

5256
```
57+
58+
### With configuration modal
59+
60+
```ts file="CodeEditorConfigurationModal.tsx"
61+
62+
```
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon';
2+
import MapIcon from '@patternfly/react-icons/dist/esm/icons/map-icon';
3+
import MoonIcon from '@patternfly/react-icons/dist/esm/icons/moon-icon';
4+
import HashtagIcon from '@patternfly/react-icons/dist/esm/icons/hashtag-icon';
5+
import { CodeEditor, CodeEditorControl } from '@patternfly/react-code-editor';
6+
import {
7+
Content,
8+
Flex,
9+
FlexItem,
10+
Modal,
11+
ModalBody,
12+
ModalHeader,
13+
Split,
14+
SplitItem,
15+
Switch,
16+
SwitchProps
17+
} from '@patternfly/react-core';
18+
import { useState } from 'react';
19+
20+
interface ConfigModalItemProps {
21+
/** Icon rendered inside the configuration modal. */
22+
icon?: React.ReactNode;
23+
/** Description of the configuration option. */
24+
description: string;
25+
/** Flag indicating whether the option is enabled or disabled. */
26+
isChecked?: SwitchProps['isChecked'];
27+
/** onChange handler for the switch. */
28+
onChange?: SwitchProps['onChange'];
29+
/** Title of the configuration option. */
30+
title: string;
31+
/** Labels for the enabled and disabled states of the switch. */
32+
labels?: {
33+
enabled: string;
34+
disabled: string;
35+
};
36+
}
37+
38+
const ConfigModalItem: React.FunctionComponent<ConfigModalItemProps> = ({
39+
icon = <CogIcon />,
40+
description,
41+
isChecked = false,
42+
labels = { enabled: 'Enabled', disabled: 'Disabled' },
43+
onChange,
44+
title
45+
}) => (
46+
<Split hasGutter>
47+
<SplitItem isFilled>
48+
<Flex alignItems={{ default: 'alignItemsCenter' }} spaceItems={{ default: 'spaceItemsMd' }}>
49+
<FlexItem>{icon}</FlexItem>
50+
<FlexItem>
51+
<strong className="pf-v6-u-font-weight-bold">{title}</strong>
52+
<Content component="p">{description}</Content>
53+
</FlexItem>
54+
</Flex>
55+
</SplitItem>
56+
<SplitItem>
57+
<Switch
58+
aria-label={title}
59+
id={title}
60+
isChecked={isChecked}
61+
isReversed
62+
label={isChecked ? labels.enabled : labels.disabled}
63+
onChange={onChange}
64+
/>
65+
</SplitItem>
66+
</Split>
67+
);
68+
69+
interface ConfigModalControlProps {
70+
/** Array of configuration controls to be rendered inside the modal. */
71+
controls: ConfigModalItemProps[];
72+
/** Title of the configuration modal. */
73+
modalTitle?: string;
74+
/** Optional OUIA ID of the configuration modal. Also used as a prefix for the ids of inner elements. */
75+
ouiaId?: string;
76+
}
77+
78+
const ConfigModalControl: React.FunctionComponent<ConfigModalControlProps> = ({
79+
controls,
80+
modalTitle = 'Editor settings',
81+
ouiaId = 'CodeEditorConfigurationModal'
82+
}) => {
83+
const [isModalOpen, setIsModalOpen] = useState(false);
84+
85+
return (
86+
<>
87+
<Modal
88+
aria-describedby={`${ouiaId}-body`}
89+
aria-labelledby={`${ouiaId}-title`}
90+
isOpen={isModalOpen}
91+
onClose={() => setIsModalOpen(!isModalOpen)}
92+
ouiaId={ouiaId}
93+
variant="small"
94+
>
95+
<ModalHeader title={modalTitle} labelId={`${ouiaId}-title`} />
96+
<ModalBody id={`${ouiaId}-body`}>
97+
<Flex direction={{ default: 'column' }} spaceItems={{ default: 'spaceItemsMd' }}>
98+
{controls.map((control) => (
99+
<ConfigModalItem key={control.title} {...control} />
100+
))}
101+
</Flex>
102+
</ModalBody>
103+
</Modal>
104+
<CodeEditorControl
105+
aria-label={modalTitle}
106+
icon={<CogIcon />}
107+
onClick={() => setIsModalOpen(true)}
108+
tooltipProps={{ content: modalTitle }}
109+
/>
110+
</>
111+
);
112+
};
113+
114+
export const CodeEditorConfigurationModal: React.FunctionComponent = () => {
115+
const [code, setCode] = useState('Some example content');
116+
117+
const [isMinimapVisible, setIsMinimapVisible] = useState(true);
118+
const [isDarkTheme, setIsDarkTheme] = useState(false);
119+
const [isLineNumbersVisible, setIsLineNumbersVisible] = useState(true);
120+
121+
const onChange = (code: string) => {
122+
setCode(code);
123+
};
124+
125+
const customControl = (
126+
<ConfigModalControl
127+
controls={[
128+
{
129+
title: 'Minimap',
130+
description: 'Show a preview of the full code on the side of the editor',
131+
isChecked: isMinimapVisible,
132+
onChange: (_e, checked) => setIsMinimapVisible(checked),
133+
icon: <MapIcon />
134+
},
135+
{
136+
title: 'Dark theme',
137+
description: 'Switch the editor to a dark color theme',
138+
isChecked: isDarkTheme,
139+
onChange: (_e, checked) => setIsDarkTheme(checked),
140+
icon: <MoonIcon />
141+
},
142+
{
143+
title: 'Line numbers',
144+
description: 'Show line numbers to the left of each line of code',
145+
isChecked: isLineNumbersVisible,
146+
onChange: (_e, checked) => setIsLineNumbersVisible(checked),
147+
icon: <HashtagIcon />
148+
}
149+
]}
150+
/>
151+
);
152+
153+
return (
154+
<CodeEditor
155+
code={code}
156+
customControls={customControl}
157+
height="400px"
158+
isDarkTheme={isDarkTheme}
159+
isLineNumbersVisible={isLineNumbersVisible}
160+
isMinimapVisible={isMinimapVisible}
161+
onChange={onChange}
162+
/>
163+
);
164+
};

0 commit comments

Comments
 (0)