Skip to content

Commit d4b4ba3

Browse files
feat: allow full-page example utils to change position (#4896)
* feat: allow full-page example utils to change position * chore: checkin * chore: update icons * chore: remember utils position * chore: add tooltips * chore: fix localStorage in build * chore: updates * Update packages/documentation-framework/components/example/example.js Co-authored-by: Eric Olkowski <70952936+thatblindgeye@users.noreply.github.com> --------- Co-authored-by: Eric Olkowski <70952936+thatblindgeye@users.noreply.github.com>
1 parent ad3b543 commit d4b4ba3

File tree

5 files changed

+134
-14
lines changed

5 files changed

+134
-14
lines changed

packages/documentation-framework/components/example/example.css

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,48 @@
7272

7373
.ws-full-page-utils {
7474
position: fixed;
75-
inset-inline-start: 0;
7675
inset-block-end: 0;
77-
padding: var(--pf-t--global--spacer--lg);
76+
padding: var(--pf-t--global--spacer--xl);
7877
z-index: var(--pf-t--global--z-index--2xl);
7978
}
8079

80+
.ws-full-page-utils-position-btn {
81+
--ws-full-page-utils-btn--inset: var(--pf-t--global--spacer--xs);
82+
position: absolute;
83+
}
84+
85+
:is(.ws-full-page-utils, .ws-full-page-utils-position-btn).pf-m-top-right {
86+
top: var(--ws-full-page-utils-btn--inset, 0);
87+
right: var(--ws-full-page-utils-btn--inset, 0);
88+
bottom: auto;
89+
left: auto;
90+
}
91+
92+
:is(.ws-full-page-utils, .ws-full-page-utils-position-btn).pf-m-bottom-right {
93+
top: auto;
94+
right: var(--ws-full-page-utils-btn--inset, 0);
95+
bottom: var(--ws-full-page-utils-btn--inset, 0);
96+
left: auto;
97+
}
98+
99+
:is(.ws-full-page-utils, .ws-full-page-utils-position-btn).pf-m-bottom-left {
100+
top: auto;
101+
right: auto;
102+
bottom: var(--ws-full-page-utils-btn--inset, 0);
103+
left: var(--ws-full-page-utils-btn--inset, 0);
104+
}
105+
106+
:is(.ws-full-page-utils, .ws-full-page-utils-position-btn).pf-m-top-left {
107+
top: var(--ws-full-page-utils-btn--inset, 0);
108+
right: auto;
109+
bottom: auto;
110+
left: var(--ws-full-page-utils-btn--inset, 0);
111+
}
112+
113+
.ws-full-page-utils-position-btn.pf-m-clicked {
114+
--pf-v6-c-button__icon--Color: var(--pf-t--global--text--color--regular);
115+
}
116+
81117
.ws-full-page-utils::before {
82118
position: absolute;
83119
inset: 0;

packages/documentation-framework/components/example/example.js

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ import missingThumbnail from './missing-thumbnail.jpg';
3434
import { RtlContext } from '../../layouts';
3535
import { ThemeSelector } from '../themeSelector/themeSelector';
3636

37+
import RhUiArrowCircleDownRightIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-arrow-circle-down-right-icon';
38+
import RhUiArrowCircleDownLeftIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-arrow-circle-down-left-icon';
39+
import RhUiArrowCircleUpRightIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-arrow-circle-up-right-icon';
40+
import RhUiArrowCircleUpLeftIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-arrow-circle-up-left-icon';
41+
import RhUiArrowCircleDownRightFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-arrow-circle-down-right-fill-icon';
42+
import RhUiArrowCircleDownLeftFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-arrow-circle-down-left-fill-icon';
43+
import RhUiArrowCircleUpRightFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-arrow-circle-up-right-fill-icon';
44+
import RhUiArrowCircleUpLeftFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-arrow-circle-up-left-fill-icon';
45+
3746
const errorComponent = (err) => <pre>{err.toString()}</pre>;
3847

3948
class ErrorBoundary extends React.Component {
@@ -137,8 +146,22 @@ export const Example = ({
137146
}
138147

139148
const [editorCode, setEditorCode] = React.useState(code);
149+
const isBrowser = typeof window !== 'undefined' && window.localStorage;
150+
const [fullPageUtilsPosition, setFullPageUtilsPosition] = React.useState(() => {
151+
if (isBrowser) {
152+
return localStorage.getItem('fullPageUtilsPosition') || 'pf-m-bottom-left';
153+
}
154+
return 'pf-m-bottom-left';
155+
});
140156
const loc = useLocation();
141157
const isRTL = useContext(RtlContext);
158+
159+
// Save fullPageUtilsPosition to localStorage when it changes
160+
useEffect(() => {
161+
if (isBrowser) {
162+
localStorage.setItem('fullPageUtilsPosition', fullPageUtilsPosition);
163+
}
164+
}, [fullPageUtilsPosition]);
142165
const scope = {
143166
...liveContext,
144167
// These 2 are in the bundle anyways for the site since we dogfood
@@ -186,15 +209,51 @@ export const Example = ({
186209
const previewId = getExampleId(source, section[0], id, title);
187210
const className = getExampleClassName(source, section[0], id);
188211

212+
// Four corner position button props
213+
const fullPageUtilsPositionProps = {
214+
topLeft: {
215+
className: 'pf-m-top-left',
216+
label: 'Move to the top left corner',
217+
tooltipPosition: 'bottom-start',
218+
icon: <RhUiArrowCircleUpLeftIcon />,
219+
iconClicked: <RhUiArrowCircleUpLeftFillIcon />
220+
},
221+
topRight: {
222+
className: 'pf-m-top-right',
223+
label: 'Move to the top right corner',
224+
tooltipPosition: 'bottom-end',
225+
icon: <RhUiArrowCircleUpRightIcon />,
226+
iconClicked: <RhUiArrowCircleUpRightFillIcon />
227+
},
228+
bottomLeft: {
229+
className: 'pf-m-bottom-left',
230+
label: 'Move to the bottom left corner',
231+
tooltipPosition: 'top-start',
232+
icon: <RhUiArrowCircleDownLeftIcon />,
233+
iconClicked: <RhUiArrowCircleDownLeftFillIcon />
234+
},
235+
bottomRight: {
236+
className: 'pf-m-bottom-right',
237+
label: 'Move to the bottom right corner',
238+
tooltipPosition: 'top-end',
239+
icon: <RhUiArrowCircleDownRightIcon />,
240+
iconClicked: <RhUiArrowCircleDownRightFillIcon />
241+
}
242+
};
243+
189244
if (isFullscreenPreview) {
245+
const activeFullPageUtilsTooltipPosition = Object.values(fullPageUtilsPositionProps).find(
246+
(props) => props.className === fullPageUtilsPosition
247+
)?.tooltipPosition;
248+
190249
return (
191250
<div id={previewId} className={css(className, 'pf-v6-u-h-100')}>
192251
{livePreview}
193252
{(hasThemeSwitcher || hasRTLSwitcher) && (
194253
<Flex
195254
direction={{ default: 'column' }}
196-
gap={{ default: 'gapMd' }}
197-
className="ws-full-page-utils pf-v6-m-dir-ltr"
255+
gap={{ default: 'gapSm' }}
256+
className={css('ws-full-page-utils', 'pf-v6-m-dir-ltr', fullPageUtilsPosition)}
198257
>
199258
{hasThemeSwitcher && <ThemeSelector id="ws-example-theme-select" />}
200259
{hasRTLSwitcher && (
@@ -209,6 +268,27 @@ export const Example = ({
209268
}}
210269
/>
211270
)}
271+
{/* Four corner position buttons */}
272+
{Object.entries(fullPageUtilsPositionProps).map(([key, utilsProps]) => (
273+
<Tooltip
274+
key={key}
275+
content={utilsProps.label}
276+
position={activeFullPageUtilsTooltipPosition || utilsProps.tooltipPosition}
277+
enableFlip={false}
278+
aria="none"
279+
aria-live="off"
280+
>
281+
<Button
282+
variant="plain"
283+
size="sm"
284+
className={css('ws-full-page-utils-position-btn', utilsProps.className)}
285+
isClicked={fullPageUtilsPosition === utilsProps.className}
286+
onClick={() => setFullPageUtilsPosition(utilsProps.className)}
287+
aria-label={`${utilsProps.label}${fullPageUtilsPosition === utilsProps.className ? ', selected' : ''}`}
288+
icon={fullPageUtilsPosition === utilsProps.className ? utilsProps.iconClicked : utilsProps.icon}
289+
/>
290+
</Tooltip>
291+
))}
212292
</Flex>
213293
)}
214294
</div>

packages/documentation-framework/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"@patternfly/patternfly": "^6.5.0-prerelease.33",
7272
"@patternfly/react-code-editor": "^6.5.0-prerelease.26",
7373
"@patternfly/react-core": "^6.5.0-prerelease.24",
74+
"@patternfly/react-icons": "^6.5.0-prerelease.11",
7475
"@patternfly/react-table": "^6.5.0-prerelease.24",
7576
"react": "^17.0.0 || ^18.0.0",
7677
"react-dom": "^17.0.0 || ^18.0.0"

packages/documentation-site/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"@patternfly/react-console": "6.1.0",
2929
"@patternfly/react-data-view": "6.4.0-prerelease.8",
3030
"@patternfly/react-docs": "7.5.0-prerelease.26",
31+
"@patternfly/react-icons": "6.5.0-prerelease.11",
3132
"@patternfly/react-log-viewer": "6.3.0",
3233
"@patternfly/react-topology": "6.5.0-prerelease.3",
3334
"@patternfly/react-user-feedback": "6.2.0",

yarn.lock

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4792,6 +4792,7 @@ __metadata:
47924792
"@patternfly/patternfly": ^6.5.0-prerelease.33
47934793
"@patternfly/react-code-editor": ^6.5.0-prerelease.26
47944794
"@patternfly/react-core": ^6.5.0-prerelease.24
4795+
"@patternfly/react-icons": ^6.5.0-prerelease.11
47954796
"@patternfly/react-table": ^6.5.0-prerelease.24
47964797
react: ^17.0.0 || ^18.0.0
47974798
react-dom: ^17.0.0 || ^18.0.0
@@ -5142,6 +5143,16 @@ __metadata:
51425143
languageName: node
51435144
linkType: hard
51445145

5146+
"@patternfly/react-icons@npm:6.5.0-prerelease.11, @patternfly/react-icons@npm:^6.5.0-prerelease.11":
5147+
version: 6.5.0-prerelease.11
5148+
resolution: "@patternfly/react-icons@npm:6.5.0-prerelease.11"
5149+
peerDependencies:
5150+
react: ^17 || ^18 || ^19
5151+
react-dom: ^17 || ^18 || ^19
5152+
checksum: 10c0/d0d91d9e011747dde34a0d3521cd92d58ff29281f6fb1e442c72cf0ea1ca8b3a69e270497e0644ffa499601484394bc9fdf12b070f8568114a7fcfed0428a8c8
5153+
languageName: node
5154+
linkType: hard
5155+
51455156
"@patternfly/react-icons@npm:^6.0.0, @patternfly/react-icons@npm:^6.0.0-prerelease.7, @patternfly/react-icons@npm:^6.3.1":
51465157
version: 6.3.1
51475158
resolution: "@patternfly/react-icons@npm:6.3.1"
@@ -5162,16 +5173,6 @@ __metadata:
51625173
languageName: node
51635174
linkType: hard
51645175

5165-
"@patternfly/react-icons@npm:^6.5.0-prerelease.11":
5166-
version: 6.5.0-prerelease.11
5167-
resolution: "@patternfly/react-icons@npm:6.5.0-prerelease.11"
5168-
peerDependencies:
5169-
react: ^17 || ^18 || ^19
5170-
react-dom: ^17 || ^18 || ^19
5171-
checksum: 10c0/d0d91d9e011747dde34a0d3521cd92d58ff29281f6fb1e442c72cf0ea1ca8b3a69e270497e0644ffa499601484394bc9fdf12b070f8568114a7fcfed0428a8c8
5172-
languageName: node
5173-
linkType: hard
5174-
51755176
"@patternfly/react-log-viewer@npm:6.3.0":
51765177
version: 6.3.0
51775178
resolution: "@patternfly/react-log-viewer@npm:6.3.0"
@@ -18961,6 +18962,7 @@ __metadata:
1896118962
"@patternfly/react-console": "npm:6.1.0"
1896218963
"@patternfly/react-data-view": "npm:6.4.0-prerelease.8"
1896318964
"@patternfly/react-docs": "npm:7.5.0-prerelease.26"
18965+
"@patternfly/react-icons": "npm:6.5.0-prerelease.11"
1896418966
"@patternfly/react-log-viewer": "npm:6.3.0"
1896518967
"@patternfly/react-topology": "npm:6.5.0-prerelease.3"
1896618968
"@patternfly/react-user-feedback": "npm:6.2.0"

0 commit comments

Comments
 (0)