@patternfly/react-core 6.6.1-prerelease.7 → 6.6.1-prerelease.9
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 +12 -0
- package/components/package.json +1 -1
- package/deprecated/package.json +1 -1
- package/dist/dynamic/components/AboutModal/package.json +1 -1
- package/dist/dynamic/components/Accordion/package.json +1 -1
- package/dist/dynamic/components/ActionList/package.json +1 -1
- package/dist/dynamic/components/Alert/package.json +1 -1
- package/dist/dynamic/components/Avatar/package.json +1 -1
- package/dist/dynamic/components/BackToTop/package.json +1 -1
- package/dist/dynamic/components/Backdrop/package.json +1 -1
- package/dist/dynamic/components/BackgroundImage/package.json +1 -1
- package/dist/dynamic/components/Badge/package.json +1 -1
- package/dist/dynamic/components/Banner/package.json +1 -1
- package/dist/dynamic/components/Brand/package.json +1 -1
- package/dist/dynamic/components/Breadcrumb/package.json +1 -1
- package/dist/dynamic/components/Button/package.json +1 -1
- package/dist/dynamic/components/CalendarMonth/package.json +1 -1
- package/dist/dynamic/components/Card/package.json +1 -1
- package/dist/dynamic/components/Checkbox/package.json +1 -1
- package/dist/dynamic/components/ClipboardCopy/package.json +1 -1
- package/dist/dynamic/components/CodeBlock/package.json +1 -1
- package/dist/dynamic/components/Compass/package.json +1 -1
- package/dist/dynamic/components/Content/package.json +1 -1
- package/dist/dynamic/components/DataList/package.json +1 -1
- package/dist/dynamic/components/DatePicker/package.json +1 -1
- package/dist/dynamic/components/DescriptionList/package.json +1 -1
- package/dist/dynamic/components/Divider/package.json +1 -1
- package/dist/dynamic/components/Drawer/package.json +1 -1
- package/dist/dynamic/components/Dropdown/package.json +1 -1
- package/dist/dynamic/components/DualListSelector/package.json +1 -1
- package/dist/dynamic/components/EmptyState/package.json +1 -1
- package/dist/dynamic/components/ExpandableSection/package.json +1 -1
- package/dist/dynamic/components/FileUpload/package.json +1 -1
- package/dist/dynamic/components/Form/package.json +1 -1
- package/dist/dynamic/components/FormSelect/package.json +1 -1
- package/dist/dynamic/components/HelperText/package.json +1 -1
- package/dist/dynamic/components/Hero/package.json +1 -1
- package/dist/dynamic/components/Hint/package.json +1 -1
- package/dist/dynamic/components/Icon/package.json +1 -1
- package/dist/dynamic/components/InputGroup/package.json +1 -1
- package/dist/dynamic/components/JumpLinks/package.json +1 -1
- package/dist/dynamic/components/Label/package.json +1 -1
- package/dist/dynamic/components/List/package.json +1 -1
- package/dist/dynamic/components/LoginPage/package.json +1 -1
- package/dist/dynamic/components/Masthead/package.json +1 -1
- package/dist/dynamic/components/Menu/package.json +1 -1
- package/dist/dynamic/components/MenuToggle/package.json +1 -1
- package/dist/dynamic/components/Modal/package.json +1 -1
- package/dist/dynamic/components/MultipleFileUpload/package.json +1 -1
- package/dist/dynamic/components/Nav/package.json +1 -1
- package/dist/dynamic/components/NotificationBadge/package.json +1 -1
- package/dist/dynamic/components/NotificationDrawer/package.json +1 -1
- package/dist/dynamic/components/NumberInput/package.json +1 -1
- package/dist/dynamic/components/OverflowMenu/package.json +1 -1
- package/dist/dynamic/components/Page/package.json +1 -1
- package/dist/dynamic/components/Pagination/package.json +1 -1
- package/dist/dynamic/components/Panel/package.json +1 -1
- package/dist/dynamic/components/Popover/package.json +1 -1
- package/dist/dynamic/components/Progress/package.json +1 -1
- package/dist/dynamic/components/ProgressStepper/package.json +1 -1
- package/dist/dynamic/components/Radio/package.json +1 -1
- package/dist/dynamic/components/SearchInput/package.json +1 -1
- package/dist/dynamic/components/Select/package.json +1 -1
- package/dist/dynamic/components/Sidebar/package.json +1 -1
- package/dist/dynamic/components/SimpleList/package.json +1 -1
- package/dist/dynamic/components/Skeleton/package.json +1 -1
- package/dist/dynamic/components/SkipToContent/package.json +1 -1
- package/dist/dynamic/components/Slider/package.json +1 -1
- package/dist/dynamic/components/Spinner/package.json +1 -1
- package/dist/dynamic/components/Switch/package.json +1 -1
- package/dist/dynamic/components/Tabs/package.json +1 -1
- package/dist/dynamic/components/TextArea/package.json +1 -1
- package/dist/dynamic/components/TextInput/package.json +1 -1
- package/dist/dynamic/components/TextInputGroup/package.json +1 -1
- package/dist/dynamic/components/TimePicker/package.json +1 -1
- package/dist/dynamic/components/Timestamp/package.json +1 -1
- package/dist/dynamic/components/Title/package.json +1 -1
- package/dist/dynamic/components/ToggleGroup/package.json +1 -1
- package/dist/dynamic/components/Toolbar/package.json +1 -1
- package/dist/dynamic/components/Tooltip/package.json +1 -1
- package/dist/dynamic/components/TreeView/package.json +1 -1
- package/dist/dynamic/components/Truncate/package.json +1 -1
- package/dist/dynamic/components/Wizard/hooks/package.json +1 -1
- package/dist/dynamic/components/Wizard/package.json +1 -1
- package/dist/dynamic/deprecated/components/Chip/package.json +1 -1
- package/dist/dynamic/deprecated/components/DragDrop/package.json +1 -1
- package/dist/dynamic/deprecated/components/DualListSelector/package.json +1 -1
- package/dist/dynamic/deprecated/components/Modal/package.json +1 -1
- package/dist/dynamic/deprecated/components/Tile/package.json +1 -1
- package/dist/dynamic/deprecated/components/Wizard/package.json +1 -1
- package/dist/dynamic/deprecated/components/package.json +1 -1
- package/dist/dynamic/helpers/AnimationsProvider/AnimationsProvider/package.json +1 -1
- package/dist/dynamic/helpers/AnimationsProvider/package.json +1 -1
- package/dist/dynamic/helpers/FocusTrap/FocusTrap/package.json +1 -1
- package/dist/dynamic/helpers/GenerateId/GenerateId/package.json +1 -1
- package/dist/dynamic/helpers/KeyboardHandler/package.json +1 -1
- package/dist/dynamic/helpers/OUIA/ouia/package.json +1 -1
- package/dist/dynamic/helpers/Popper/Popper/package.json +1 -1
- package/dist/dynamic/helpers/SSRSafeIds/SSRSafeIds/package.json +1 -1
- package/dist/dynamic/helpers/constants/package.json +1 -1
- package/dist/dynamic/helpers/datetimeUtils/package.json +1 -1
- package/dist/dynamic/helpers/fileUtils/package.json +1 -1
- package/dist/dynamic/helpers/htmlConstants/package.json +1 -1
- package/dist/dynamic/helpers/inert/package.json +1 -1
- package/dist/dynamic/helpers/package.json +1 -1
- package/dist/dynamic/helpers/resizeObserver/package.json +1 -1
- package/dist/dynamic/helpers/typeUtils/package.json +1 -1
- package/dist/dynamic/helpers/useInterval/package.json +1 -1
- package/dist/dynamic/helpers/useIsomorphicLayout/package.json +1 -1
- package/dist/dynamic/helpers/useSSRSafeId/package.json +1 -1
- package/dist/dynamic/helpers/useUnmountEffect/package.json +1 -1
- package/dist/dynamic/helpers/util/package.json +1 -1
- package/dist/dynamic/layouts/Bullseye/package.json +1 -1
- package/dist/dynamic/layouts/Flex/package.json +1 -1
- package/dist/dynamic/layouts/Gallery/package.json +1 -1
- package/dist/dynamic/layouts/Grid/package.json +1 -1
- package/dist/dynamic/layouts/Level/package.json +1 -1
- package/dist/dynamic/layouts/Split/package.json +1 -1
- package/dist/dynamic/layouts/Stack/package.json +1 -1
- package/dist/dynamic/styles/package.json +1 -1
- package/dist/dynamic-modules.json +2 -0
- package/dist/esm/components/Drawer/Drawer.d.ts +3 -0
- package/dist/esm/components/Drawer/Drawer.d.ts.map +1 -1
- package/dist/esm/components/Drawer/Drawer.js +4 -3
- package/dist/esm/components/Drawer/Drawer.js.map +1 -1
- package/dist/esm/components/Drawer/DrawerContent.d.ts +1 -1
- package/dist/esm/components/Drawer/DrawerContent.d.ts.map +1 -1
- package/dist/esm/components/Drawer/DrawerPanelContent.js +22 -25
- package/dist/esm/components/Drawer/DrawerPanelContent.js.map +1 -1
- package/dist/esm/components/Page/Page.d.ts +4 -0
- package/dist/esm/components/Page/Page.d.ts.map +1 -1
- package/dist/esm/components/Page/Page.js +4 -3
- package/dist/esm/components/Page/Page.js.map +1 -1
- package/dist/esm/components/Page/PageFooter.d.ts +11 -0
- package/dist/esm/components/Page/PageFooter.d.ts.map +1 -0
- package/dist/esm/components/Page/PageFooter.js +11 -0
- package/dist/esm/components/Page/PageFooter.js.map +1 -0
- package/dist/esm/components/Page/index.d.ts +1 -0
- package/dist/esm/components/Page/index.d.ts.map +1 -1
- package/dist/esm/components/Page/index.js +1 -0
- package/dist/esm/components/Page/index.js.map +1 -1
- package/dist/js/components/Drawer/Drawer.d.ts +3 -0
- package/dist/js/components/Drawer/Drawer.d.ts.map +1 -1
- package/dist/js/components/Drawer/Drawer.js +4 -3
- package/dist/js/components/Drawer/Drawer.js.map +1 -1
- package/dist/js/components/Drawer/DrawerContent.d.ts +1 -1
- package/dist/js/components/Drawer/DrawerContent.d.ts.map +1 -1
- package/dist/js/components/Drawer/DrawerPanelContent.js +22 -25
- package/dist/js/components/Drawer/DrawerPanelContent.js.map +1 -1
- package/dist/js/components/Page/Page.d.ts +4 -0
- package/dist/js/components/Page/Page.d.ts.map +1 -1
- package/dist/js/components/Page/Page.js +4 -3
- package/dist/js/components/Page/Page.js.map +1 -1
- package/dist/js/components/Page/PageFooter.d.ts +11 -0
- package/dist/js/components/Page/PageFooter.d.ts.map +1 -0
- package/dist/js/components/Page/PageFooter.js +15 -0
- package/dist/js/components/Page/PageFooter.js.map +1 -0
- package/dist/js/components/Page/index.d.ts +1 -0
- package/dist/js/components/Page/index.d.ts.map +1 -1
- package/dist/js/components/Page/index.js +1 -0
- package/dist/js/components/Page/index.js.map +1 -1
- package/dist/umd/assets/{output-BGwwN1RO.css → output-B35Oc6dG.css} +15784 -15727
- package/dist/umd/react-core.min.js +1 -1
- package/helpers/package.json +1 -1
- package/layouts/package.json +1 -1
- package/next/package.json +1 -1
- package/package.json +6 -6
- package/src/components/Drawer/Drawer.tsx +10 -2
- package/src/components/Drawer/DrawerContent.tsx +1 -1
- package/src/components/Drawer/DrawerPanelContent.tsx +25 -25
- package/src/components/Drawer/__tests__/Drawer.test.tsx +53 -0
- package/src/components/Drawer/examples/Drawer.md +1 -1
- package/src/components/Page/Page.tsx +10 -1
- package/src/components/Page/PageFooter.tsx +28 -0
- package/src/components/Page/__tests__/Page.test.tsx +46 -0
- package/src/components/Page/__tests__/PageFooter.test.tsx +38 -0
- package/src/components/Page/examples/Page.md +24 -8
- package/src/components/Page/examples/PageCustomFooter.tsx +59 -0
- package/src/components/Page/examples/PageCustomHeader.tsx +17 -0
- package/src/components/Page/examples/PagePlain.tsx +9 -0
- package/src/components/Page/index.ts +1 -0
- package/src/demos/CardView/CardView.md +1 -1
- package/src/demos/CardView/examples/CardView.tsx +1 -1
- package/src/demos/Drawer/Drawer.md +16 -0
- package/src/demos/Drawer/examples/DrawerViewport.tsx +112 -0
- package/src/demos/Page.md +24 -11
- package/src/demos/examples/Page/PagePlain.tsx +342 -0
- package/src/components/Page/examples/PageHeaderContent.tsx +0 -19
- package/src/demos/examples/Page/PageStickySectionGroupUsingPageHeader.tsx +0 -0
package/helpers/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"6.6.1-prerelease.
|
|
1
|
+
{"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"6.6.1-prerelease.8","private":true}
|
package/layouts/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"6.6.1-prerelease.
|
|
1
|
+
{"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"6.6.1-prerelease.8","private":true}
|
package/next/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"6.6.1-prerelease.
|
|
1
|
+
{"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"6.6.1-prerelease.8","private":true}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternfly/react-core",
|
|
3
|
-
"version": "6.6.1-prerelease.
|
|
3
|
+
"version": "6.6.1-prerelease.9",
|
|
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",
|
|
@@ -46,15 +46,15 @@
|
|
|
46
46
|
"subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@patternfly/react-icons": "^6.6.1-prerelease.
|
|
50
|
-
"@patternfly/react-styles": "^6.6.1-prerelease.
|
|
51
|
-
"@patternfly/react-tokens": "^6.6.1-prerelease.
|
|
49
|
+
"@patternfly/react-icons": "^6.6.1-prerelease.4",
|
|
50
|
+
"@patternfly/react-styles": "^6.6.1-prerelease.3",
|
|
51
|
+
"@patternfly/react-tokens": "^6.6.1-prerelease.3",
|
|
52
52
|
"focus-trap": "7.6.6",
|
|
53
53
|
"react-dropzone": "^14.3.5",
|
|
54
54
|
"tslib": "^2.8.1"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@patternfly/patternfly": "6.6.0-prerelease.
|
|
57
|
+
"@patternfly/patternfly": "6.6.0-prerelease.41",
|
|
58
58
|
"case-anything": "^3.1.2",
|
|
59
59
|
"css": "^3.0.0",
|
|
60
60
|
"fs-extra": "^11.3.3"
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"react": "^17 || ^18 || ^19",
|
|
64
64
|
"react-dom": "^17 || ^18 || ^19"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "103c595fefeee9e6cf6209cc94154b0551702f18"
|
|
67
67
|
}
|
|
@@ -23,6 +23,8 @@ export interface DrawerProps extends React.HTMLProps<HTMLDivElement>, OUIAProps
|
|
|
23
23
|
isInline?: boolean;
|
|
24
24
|
/** @beta Indicates if the drawer will have pill styles */
|
|
25
25
|
isPill?: boolean;
|
|
26
|
+
/** @beta Positions the drawer as fixed to fill the viewport. Place the drawer after Page as a sibling. */
|
|
27
|
+
isViewport?: boolean;
|
|
26
28
|
/** Indicates if the drawer will always show both content and panel. */
|
|
27
29
|
isStatic?: boolean;
|
|
28
30
|
/** Position of the drawer panel. left and right are deprecated, use start and end instead. */
|
|
@@ -43,6 +45,7 @@ export interface DrawerContextProps {
|
|
|
43
45
|
drawerRef?: React.RefObject<HTMLDivElement | null>;
|
|
44
46
|
drawerContentRef?: React.RefObject<HTMLDivElement | null>;
|
|
45
47
|
isInline: boolean;
|
|
48
|
+
isViewport: boolean;
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
export const DrawerContext = createContext<Partial<DrawerContextProps>>({
|
|
@@ -52,7 +55,8 @@ export const DrawerContext = createContext<Partial<DrawerContextProps>>({
|
|
|
52
55
|
position: 'end',
|
|
53
56
|
drawerRef: null,
|
|
54
57
|
drawerContentRef: null,
|
|
55
|
-
isInline: false
|
|
58
|
+
isInline: false,
|
|
59
|
+
isViewport: false
|
|
56
60
|
});
|
|
57
61
|
|
|
58
62
|
export const Drawer: React.FunctionComponent<DrawerProps> = ({
|
|
@@ -61,6 +65,7 @@ export const Drawer: React.FunctionComponent<DrawerProps> = ({
|
|
|
61
65
|
isExpanded = false,
|
|
62
66
|
isInline = false,
|
|
63
67
|
isPill = false,
|
|
68
|
+
isViewport = false,
|
|
64
69
|
isStatic = false,
|
|
65
70
|
position = 'end',
|
|
66
71
|
onExpand = () => {},
|
|
@@ -73,13 +78,16 @@ export const Drawer: React.FunctionComponent<DrawerProps> = ({
|
|
|
73
78
|
const drawerContentRef = useRef<HTMLDivElement>(undefined);
|
|
74
79
|
|
|
75
80
|
return (
|
|
76
|
-
<DrawerContext.Provider
|
|
81
|
+
<DrawerContext.Provider
|
|
82
|
+
value={{ isExpanded, isStatic, onExpand, position, drawerRef, drawerContentRef, isInline, isViewport }}
|
|
83
|
+
>
|
|
77
84
|
<div
|
|
78
85
|
className={css(
|
|
79
86
|
styles.drawer,
|
|
80
87
|
isExpanded && styles.modifiers.expanded,
|
|
81
88
|
isInline && styles.modifiers.inline,
|
|
82
89
|
isPill && styles.modifiers.pill,
|
|
90
|
+
isViewport && styles.modifiers.viewport,
|
|
83
91
|
isStatic && styles.modifiers.static,
|
|
84
92
|
(position === 'left' || position === 'start') && styles.modifiers.panelLeft,
|
|
85
93
|
position === 'bottom' && styles.modifiers.panelBottom,
|
|
@@ -13,7 +13,7 @@ export enum DrawerContentColorVariant {
|
|
|
13
13
|
export interface DrawerContentProps extends React.HTMLProps<HTMLDivElement> {
|
|
14
14
|
/** Additional classes added to the Drawer. */
|
|
15
15
|
className?: string;
|
|
16
|
-
/** Content to be rendered in the drawer. */
|
|
16
|
+
/** Content to be rendered in the drawer. Can be omitted to leave the content container empty. */
|
|
17
17
|
children?: React.ReactNode;
|
|
18
18
|
/** Content rendered in the drawer panel. */
|
|
19
19
|
panelContent: React.ReactNode;
|
|
@@ -100,7 +100,8 @@ export const DrawerPanelContent: React.FunctionComponent<DrawerPanelContentProps
|
|
|
100
100
|
const panel = useRef<HTMLDivElement>(undefined);
|
|
101
101
|
const splitterRef = useRef<HTMLDivElement>(undefined);
|
|
102
102
|
const [separatorValue, setSeparatorValue] = useState(0);
|
|
103
|
-
const { position, isExpanded, isStatic, onExpand, drawerRef, drawerContentRef, isInline } =
|
|
103
|
+
const { position, isExpanded, isStatic, onExpand, drawerRef, drawerContentRef, isInline, isViewport } =
|
|
104
|
+
useContext(DrawerContext);
|
|
104
105
|
const hidden = isStatic ? false : !isExpanded;
|
|
105
106
|
const [isExpandedInternal, setIsExpandedInternal] = useState(!hidden);
|
|
106
107
|
const [isFocusTrapActive, setIsFocusTrapActive] = useState(false);
|
|
@@ -126,9 +127,22 @@ export const DrawerPanelContent: React.FunctionComponent<DrawerPanelContentProps
|
|
|
126
127
|
}
|
|
127
128
|
}, [isStatic, isExpanded]);
|
|
128
129
|
|
|
130
|
+
const getSizeElement = () => {
|
|
131
|
+
if (isViewport) {
|
|
132
|
+
return drawerRef?.current ?? drawerContentRef?.current;
|
|
133
|
+
}
|
|
134
|
+
return drawerContentRef?.current ?? drawerRef?.current;
|
|
135
|
+
};
|
|
136
|
+
|
|
129
137
|
const calcValueNow = () => {
|
|
130
138
|
let splitterPos;
|
|
131
139
|
let drawerSize;
|
|
140
|
+
const sizeEl = getSizeElement();
|
|
141
|
+
|
|
142
|
+
if (!sizeEl || !panel.current || !splitterRef.current || !drawerRef?.current) {
|
|
143
|
+
return 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
132
146
|
const isRTL = getLanguageDirection(panel.current) === 'rtl';
|
|
133
147
|
|
|
134
148
|
if (isInline && (position === 'end' || position === 'right')) {
|
|
@@ -149,37 +163,23 @@ export const DrawerPanelContent: React.FunctionComponent<DrawerPanelContentProps
|
|
|
149
163
|
}
|
|
150
164
|
} else if (position === 'end' || position === 'right') {
|
|
151
165
|
if (isRTL) {
|
|
152
|
-
splitterPos =
|
|
153
|
-
|
|
154
|
-
drawerSize =
|
|
155
|
-
drawerContentRef.current.getBoundingClientRect().left -
|
|
156
|
-
drawerContentRef.current.getBoundingClientRect().right;
|
|
166
|
+
splitterPos = sizeEl.getBoundingClientRect().left - splitterRef.current.getBoundingClientRect().right;
|
|
167
|
+
drawerSize = sizeEl.getBoundingClientRect().left - sizeEl.getBoundingClientRect().right;
|
|
157
168
|
} else {
|
|
158
|
-
splitterPos =
|
|
159
|
-
|
|
160
|
-
drawerSize =
|
|
161
|
-
drawerContentRef.current.getBoundingClientRect().right -
|
|
162
|
-
drawerContentRef.current.getBoundingClientRect().left;
|
|
169
|
+
splitterPos = sizeEl.getBoundingClientRect().right - splitterRef.current.getBoundingClientRect().left;
|
|
170
|
+
drawerSize = sizeEl.getBoundingClientRect().right - sizeEl.getBoundingClientRect().left;
|
|
163
171
|
}
|
|
164
172
|
} else if (position === 'start' || position === 'left') {
|
|
165
173
|
if (isRTL) {
|
|
166
|
-
splitterPos =
|
|
167
|
-
|
|
168
|
-
drawerSize =
|
|
169
|
-
drawerContentRef.current.getBoundingClientRect().left -
|
|
170
|
-
drawerContentRef.current.getBoundingClientRect().right;
|
|
174
|
+
splitterPos = splitterRef.current.getBoundingClientRect().left - sizeEl.getBoundingClientRect().right;
|
|
175
|
+
drawerSize = sizeEl.getBoundingClientRect().left - sizeEl.getBoundingClientRect().right;
|
|
171
176
|
} else {
|
|
172
|
-
splitterPos =
|
|
173
|
-
|
|
174
|
-
drawerSize =
|
|
175
|
-
drawerContentRef.current.getBoundingClientRect().right -
|
|
176
|
-
drawerContentRef.current.getBoundingClientRect().left;
|
|
177
|
+
splitterPos = splitterRef.current.getBoundingClientRect().right - sizeEl.getBoundingClientRect().left;
|
|
178
|
+
drawerSize = sizeEl.getBoundingClientRect().right - sizeEl.getBoundingClientRect().left;
|
|
177
179
|
}
|
|
178
180
|
} else if (position === 'bottom') {
|
|
179
|
-
splitterPos =
|
|
180
|
-
|
|
181
|
-
drawerSize =
|
|
182
|
-
drawerContentRef.current.getBoundingClientRect().bottom - drawerContentRef.current.getBoundingClientRect().top;
|
|
181
|
+
splitterPos = sizeEl.getBoundingClientRect().bottom - splitterRef.current.getBoundingClientRect().top;
|
|
182
|
+
drawerSize = sizeEl.getBoundingClientRect().bottom - sizeEl.getBoundingClientRect().top;
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
const newSplitterPos = (splitterPos / drawerSize) * 100;
|
|
@@ -231,3 +231,56 @@ test('Renders with ouiaSafe=false when specified', () => {
|
|
|
231
231
|
);
|
|
232
232
|
expect(screen.getByTestId('drawer')).toHaveAttribute('data-ouia-safe', 'false');
|
|
233
233
|
});
|
|
234
|
+
|
|
235
|
+
test(`Does not render with ${styles.modifiers.viewport} class by default`, () => {
|
|
236
|
+
render(
|
|
237
|
+
<Drawer data-testid="drawer">
|
|
238
|
+
<DrawerContent panelContent={<DrawerPanelContent>panel</DrawerPanelContent>}>
|
|
239
|
+
<DrawerContentBody>content</DrawerContentBody>
|
|
240
|
+
</DrawerContent>
|
|
241
|
+
</Drawer>
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
expect(screen.getByTestId('drawer')).not.toHaveClass(styles.modifiers.viewport);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test(`Renders with ${styles.modifiers.viewport} when isViewport is specified`, () => {
|
|
248
|
+
render(
|
|
249
|
+
<Drawer data-testid="drawer" isViewport>
|
|
250
|
+
<DrawerContent panelContent={<DrawerPanelContent>panel</DrawerPanelContent>}>
|
|
251
|
+
<DrawerContentBody>content</DrawerContentBody>
|
|
252
|
+
</DrawerContent>
|
|
253
|
+
</Drawer>
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
expect(screen.getByTestId('drawer')).toHaveClass(styles.modifiers.viewport);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test('Resizeable DrawerPanelContent without drawer content does not throw', async () => {
|
|
260
|
+
const consoleError = jest.spyOn(console, 'error').mockImplementation();
|
|
261
|
+
|
|
262
|
+
const panelContent = (
|
|
263
|
+
<DrawerPanelContent isResizable>
|
|
264
|
+
<DrawerHead>
|
|
265
|
+
<span>drawer-panel</span>
|
|
266
|
+
<DrawerActions>
|
|
267
|
+
<DrawerCloseButton />
|
|
268
|
+
</DrawerActions>
|
|
269
|
+
</DrawerHead>
|
|
270
|
+
</DrawerPanelContent>
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
const user = userEvent.setup();
|
|
274
|
+
|
|
275
|
+
render(
|
|
276
|
+
<Drawer isExpanded isViewport>
|
|
277
|
+
<DrawerContent panelContent={panelContent} />
|
|
278
|
+
</Drawer>
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
await user.tab();
|
|
282
|
+
await user.keyboard(`{${KeyTypes.ArrowLeft}}`);
|
|
283
|
+
|
|
284
|
+
expect(consoleError).not.toHaveBeenCalled();
|
|
285
|
+
consoleError.mockRestore();
|
|
286
|
+
});
|
|
@@ -118,6 +118,10 @@ export interface PageProps extends React.HTMLProps<HTMLDivElement> {
|
|
|
118
118
|
breadcrumbProps?: PageBreadcrumbProps;
|
|
119
119
|
/** Enables children to fill the available vertical space. Child page sections or groups that should fill should be passed the isFilled property. */
|
|
120
120
|
isContentFilled?: boolean;
|
|
121
|
+
/** Flag indicating the page should render without the content area background and overflow scroll. */
|
|
122
|
+
isPlain?: boolean;
|
|
123
|
+
/** Content rendered inside the page footer */
|
|
124
|
+
footer?: React.ReactNode;
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
export interface PageState {
|
|
@@ -141,7 +145,8 @@ class Page extends Component<PageProps, PageState> {
|
|
|
141
145
|
mainComponent: 'main',
|
|
142
146
|
getBreakpoint,
|
|
143
147
|
getVerticalBreakpoint,
|
|
144
|
-
mainRef: undefined
|
|
148
|
+
mainRef: undefined,
|
|
149
|
+
isPlain: false
|
|
145
150
|
};
|
|
146
151
|
mainRef = this.props?.mainRef ? this.props.mainRef : createRef<HTMLDivElement>();
|
|
147
152
|
pageRef = createRef<HTMLDivElement>();
|
|
@@ -284,6 +289,8 @@ class Page extends Component<PageProps, PageState> {
|
|
|
284
289
|
isContentFilled,
|
|
285
290
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
286
291
|
mainRef,
|
|
292
|
+
isPlain,
|
|
293
|
+
footer,
|
|
287
294
|
...rest
|
|
288
295
|
} = this.props;
|
|
289
296
|
const { mobileView, mobileIsSidebarOpen, desktopIsSidebarOpen, width, height } = this.state;
|
|
@@ -367,6 +374,7 @@ class Page extends Component<PageProps, PageState> {
|
|
|
367
374
|
width !== null && `pf-m-breakpoint-${getBreakpoint(width)}`,
|
|
368
375
|
height !== null && `pf-m-height-breakpoint-${getVerticalBreakpoint(height)}`,
|
|
369
376
|
sidebar === null && styles.modifiers.noSidebar,
|
|
377
|
+
isPlain && styles.modifiers.plain,
|
|
370
378
|
className
|
|
371
379
|
)}
|
|
372
380
|
>
|
|
@@ -397,6 +405,7 @@ class Page extends Component<PageProps, PageState> {
|
|
|
397
405
|
</div>
|
|
398
406
|
)}
|
|
399
407
|
{!notificationDrawer && main}
|
|
408
|
+
{footer && footer}
|
|
400
409
|
</div>
|
|
401
410
|
</PageContextProvider>
|
|
402
411
|
);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import styles from '@patternfly/react-styles/css/components/Page/page';
|
|
2
|
+
import { css } from '@patternfly/react-styles';
|
|
3
|
+
|
|
4
|
+
export interface PageFooterProps extends React.HTMLProps<HTMLElement> {
|
|
5
|
+
/** Content rendered inside the footer */
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
/** Additional classes added to the footer */
|
|
8
|
+
className?: string;
|
|
9
|
+
/** Sets the base component to render. Defaults to footer */
|
|
10
|
+
component?: keyof React.JSX.IntrinsicElements;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const PageFooter: React.FunctionComponent<PageFooterProps> = ({
|
|
14
|
+
className,
|
|
15
|
+
children,
|
|
16
|
+
component = 'footer',
|
|
17
|
+
...props
|
|
18
|
+
}: PageFooterProps) => {
|
|
19
|
+
const Component = component as any;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Component {...props} className={css(styles.pageFooter, className)}>
|
|
23
|
+
{children}
|
|
24
|
+
</Component>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
PageFooter.displayName = 'PageFooter';
|
|
@@ -13,6 +13,7 @@ import { PageHeader } from '../PageHeader';
|
|
|
13
13
|
import { Masthead } from '../../Masthead';
|
|
14
14
|
|
|
15
15
|
import styles from '@patternfly/react-styles/css/components/Page/page';
|
|
16
|
+
import { PageFooter } from '../PageFooter';
|
|
16
17
|
|
|
17
18
|
const props = {
|
|
18
19
|
'aria-label': 'Page layout',
|
|
@@ -520,4 +521,49 @@ describe('Page docked variant', () => {
|
|
|
520
521
|
expect(header).toHaveClass(styles.pageHeader);
|
|
521
522
|
expect(header.parentElement).toHaveClass(styles.page);
|
|
522
523
|
});
|
|
524
|
+
|
|
525
|
+
test('Renders PageFooter when passed to the footer prop', () => {
|
|
526
|
+
render(
|
|
527
|
+
<Page {...props} footer={<PageFooter>Custom footer</PageFooter>}>
|
|
528
|
+
<PageSection>Custom content</PageSection>
|
|
529
|
+
</Page>
|
|
530
|
+
);
|
|
531
|
+
|
|
532
|
+
const footer = screen.getByRole('contentinfo');
|
|
533
|
+
expect(footer).toHaveClass(styles.pageFooter);
|
|
534
|
+
expect(footer.parentElement).toHaveClass(styles.page);
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
test(`Renders with ${styles.modifiers.plain} when isPlain is true`, () => {
|
|
538
|
+
render(
|
|
539
|
+
<Page {...props} isPlain data-testid="page">
|
|
540
|
+
<PageSection>Custom content</PageSection>
|
|
541
|
+
</Page>
|
|
542
|
+
);
|
|
543
|
+
|
|
544
|
+
const page = screen.getByTestId('page');
|
|
545
|
+
expect(page).toHaveClass(styles.modifiers.plain);
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
test(`Does not render with ${styles.modifiers.plain} when isPlain is false`, () => {
|
|
549
|
+
render(
|
|
550
|
+
<Page {...props} isPlain={false} data-testid="page">
|
|
551
|
+
<PageSection>Custom content</PageSection>
|
|
552
|
+
</Page>
|
|
553
|
+
);
|
|
554
|
+
|
|
555
|
+
const page = screen.getByTestId('page');
|
|
556
|
+
expect(page).not.toHaveClass(styles.modifiers.plain);
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
test(`Does not render with ${styles.modifiers.plain} when isPlain is not passed`, () => {
|
|
560
|
+
render(
|
|
561
|
+
<Page {...props} data-testid="page">
|
|
562
|
+
<PageSection>Custom content</PageSection>
|
|
563
|
+
</Page>
|
|
564
|
+
);
|
|
565
|
+
|
|
566
|
+
const page = screen.getByTestId('page');
|
|
567
|
+
expect(page).not.toHaveClass(styles.modifiers.plain);
|
|
568
|
+
});
|
|
523
569
|
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import styles from '@patternfly/react-styles/css/components/Page/page';
|
|
3
|
+
import { PageFooter } from '../PageFooter';
|
|
4
|
+
|
|
5
|
+
test('Renders children', () => {
|
|
6
|
+
render(<PageFooter>Footer content</PageFooter>);
|
|
7
|
+
expect(screen.getByRole('contentinfo')).toBeVisible();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test('Renders without children', () => {
|
|
11
|
+
render(<PageFooter data-testid="footer" />);
|
|
12
|
+
expect(screen.getByTestId('footer')).toBeVisible();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test(`Renders with class ${styles.pageFooter} by default`, () => {
|
|
16
|
+
render(<PageFooter>Footer content</PageFooter>);
|
|
17
|
+
expect(screen.getByRole('contentinfo')).toHaveClass(styles.pageFooter, { exact: true });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('Renders as a footer by default', () => {
|
|
21
|
+
render(<PageFooter>Footer content</PageFooter>);
|
|
22
|
+
expect(screen.getByRole('contentinfo').tagName).toBe('FOOTER');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('Renders as a custom component when component is passed', () => {
|
|
26
|
+
render(<PageFooter component="div">Footer content</PageFooter>);
|
|
27
|
+
expect(screen.getByText('Footer content').tagName).toBe('DIV');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('Renders with custom classes when className is passed', () => {
|
|
31
|
+
render(<PageFooter className="custom-class">Footer content</PageFooter>);
|
|
32
|
+
expect(screen.getByRole('contentinfo')).toHaveClass('custom-class');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('Renders with spread props', () => {
|
|
36
|
+
render(<PageFooter id="custom-id">Footer content</PageFooter>);
|
|
37
|
+
expect(screen.getByRole('contentinfo')).toHaveAttribute('id', 'custom-id');
|
|
38
|
+
});
|
|
@@ -33,14 +33,6 @@ The `<MastheadMain>` component includes the smaller area that typically contains
|
|
|
33
33
|
- 1 or more `<PageSidebarBody>` components inside `<PageSidebar>` for vertical navigation or other sidebar content
|
|
34
34
|
- 1 or more `<PageSection>` components
|
|
35
35
|
|
|
36
|
-
### Page header
|
|
37
|
-
|
|
38
|
-
To use a page header instead of passing a [masthead](/components/masthead) directly, pass a `<PageHeader>` to the `masthead` property. `<PageHeader>` should only be used to wrap custom header content.
|
|
39
|
-
|
|
40
|
-
```ts file="./PageHeaderContent.tsx"
|
|
41
|
-
|
|
42
|
-
```
|
|
43
|
-
|
|
44
36
|
### Vertical navigation
|
|
45
37
|
|
|
46
38
|
To add a vertical sidebar to a `<Page>`, pass a `<PageSidebar>` component into the `sidebar` property. To render navigation in the sidebar, pass a `<PageSidebarBody>` component to `<PageSidebar>`.
|
|
@@ -158,3 +150,27 @@ In this example, a scroll event listener on the scroll parent container toggles
|
|
|
158
150
|
```ts file="./PageDynamicStickySection.tsx"
|
|
159
151
|
|
|
160
152
|
```
|
|
153
|
+
|
|
154
|
+
### Custom header
|
|
155
|
+
|
|
156
|
+
To use a page header instead of passing a [masthead](/components/masthead) directly, pass a `<PageHeader>` to the `masthead` property. `<PageHeader>` should only be used to wrap custom header content.
|
|
157
|
+
|
|
158
|
+
```ts isBeta file="./PageCustomHeader.tsx"
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Footer
|
|
163
|
+
|
|
164
|
+
`<PageFooter>` can be passed to the `footer` property, and should be used to wrap custom footer content.
|
|
165
|
+
|
|
166
|
+
```ts isBeta file="./PageCustomFooter.tsx"
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Plain
|
|
171
|
+
|
|
172
|
+
When a page should not have the default content area background or overflow scrolling, pass the `isPlain` property to `<Page>`.
|
|
173
|
+
|
|
174
|
+
```ts isBeta file="./PagePlain.tsx"
|
|
175
|
+
|
|
176
|
+
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Masthead,
|
|
4
|
+
MastheadMain,
|
|
5
|
+
MastheadToggle,
|
|
6
|
+
MastheadBrand,
|
|
7
|
+
MastheadLogo,
|
|
8
|
+
MastheadContent,
|
|
9
|
+
Page,
|
|
10
|
+
PageFooter,
|
|
11
|
+
PageSection,
|
|
12
|
+
PageSidebar,
|
|
13
|
+
PageSidebarBody,
|
|
14
|
+
PageToggleButton
|
|
15
|
+
} from '@patternfly/react-core';
|
|
16
|
+
|
|
17
|
+
export const PageCustomFooter: React.FunctionComponent = () => {
|
|
18
|
+
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
|
19
|
+
|
|
20
|
+
const onSidebarToggle = () => {
|
|
21
|
+
setIsSidebarOpen(!isSidebarOpen);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const masthead = (
|
|
25
|
+
<Masthead>
|
|
26
|
+
<MastheadMain>
|
|
27
|
+
<MastheadToggle>
|
|
28
|
+
<PageToggleButton
|
|
29
|
+
aria-label="Global navigation"
|
|
30
|
+
isSidebarOpen={isSidebarOpen}
|
|
31
|
+
onSidebarToggle={onSidebarToggle}
|
|
32
|
+
id="custom-footer-body-nav-toggle"
|
|
33
|
+
isHamburgerButton
|
|
34
|
+
/>
|
|
35
|
+
</MastheadToggle>
|
|
36
|
+
<MastheadBrand>
|
|
37
|
+
<MastheadLogo href="https://patternfly.org" target="_blank">
|
|
38
|
+
Logo
|
|
39
|
+
</MastheadLogo>
|
|
40
|
+
</MastheadBrand>
|
|
41
|
+
</MastheadMain>
|
|
42
|
+
<MastheadContent>Content</MastheadContent>
|
|
43
|
+
</Masthead>
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const sidebar = (
|
|
47
|
+
<PageSidebar isSidebarOpen={isSidebarOpen} id="custom-footer-vertical-sidebar">
|
|
48
|
+
<PageSidebarBody>Navigation</PageSidebarBody>
|
|
49
|
+
</PageSidebar>
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<Page footer={<PageFooter>Page footer</PageFooter>} masthead={masthead} sidebar={sidebar}>
|
|
54
|
+
<PageSection aria-labelledby="custom-footer-section">
|
|
55
|
+
<h2 id="custom-footer-section">Page content</h2>
|
|
56
|
+
</PageSection>
|
|
57
|
+
</Page>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Page, PageHeader, PageSection, PageSidebar, PageSidebarBody } from '@patternfly/react-core';
|
|
2
|
+
|
|
3
|
+
export const PageCustomHeader: React.FunctionComponent = () => {
|
|
4
|
+
const sidebar = (
|
|
5
|
+
<PageSidebar isSidebarOpen id="custom-header-vertical-sidebar">
|
|
6
|
+
<PageSidebarBody>Navigation</PageSidebarBody>
|
|
7
|
+
</PageSidebar>
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<Page masthead={<PageHeader>Custom page header</PageHeader>} sidebar={sidebar}>
|
|
12
|
+
<PageSection aria-labelledby="custom-header-section">
|
|
13
|
+
<h2 id="custom-header-section">Page content</h2>
|
|
14
|
+
</PageSection>
|
|
15
|
+
</Page>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Page, PageHeader, PageSection } from '@patternfly/react-core';
|
|
2
|
+
|
|
3
|
+
export const PagePlain: React.FunctionComponent = () => (
|
|
4
|
+
<Page isPlain masthead={<PageHeader>Custom header</PageHeader>} sidebar={null}>
|
|
5
|
+
<PageSection aria-labelledby="plain-page-section">
|
|
6
|
+
<h2 id="plain-page-section">Page content</h2>
|
|
7
|
+
</PageSection>
|
|
8
|
+
</Page>
|
|
9
|
+
);
|
|
@@ -6,7 +6,7 @@ section: patterns
|
|
|
6
6
|
import { Fragment, useState } from 'react';
|
|
7
7
|
import RhUiTrashFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-trash-fill-icon';
|
|
8
8
|
import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon';
|
|
9
|
-
import pfIcon from '
|
|
9
|
+
import pfIcon from '@patternfly/react-core/src/demos/assets/PF-IconLogo.svg';
|
|
10
10
|
import activeMQIcon from '../assets/activemq-core_200x150.png';
|
|
11
11
|
import avroIcon from '../assets/camel-avro_200x150.png';
|
|
12
12
|
import dropBoxIcon from '../assets/camel-dropbox_200x150.png';
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
} from '@patternfly/react-core';
|
|
37
37
|
import RhUiTrashFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-trash-fill-icon';
|
|
38
38
|
import RhUiAddCircleFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-add-circle-fill-icon';
|
|
39
|
-
import pfIcon from '
|
|
39
|
+
import pfIcon from '@patternfly/react-core/src/demos/assets/PF-IconLogo.svg';
|
|
40
40
|
import activeMQIcon from './assets/activemq-core_200x150.png';
|
|
41
41
|
import avroIcon from './assets/camel-avro_200x150.png';
|
|
42
42
|
import dropBoxIcon from './assets/camel-dropbox_200x150.png';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: Drawer
|
|
3
|
+
section: components
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import { Fragment, useRef, useState } from 'react';
|
|
7
|
+
|
|
8
|
+
## Demos
|
|
9
|
+
|
|
10
|
+
### Expanded resizable viewport drawer
|
|
11
|
+
|
|
12
|
+
Use `isViewport` to position the drawer as `fixed` so it fills the viewport. Place the drawer after `<Page>` as a sibling. Omit children of `<DrawerContent>` so the content container stays empty; the empty container is still required so the panel can overlay the page.
|
|
13
|
+
|
|
14
|
+
```ts file="./examples/DrawerViewport.tsx" isFullscreen isBeta
|
|
15
|
+
|
|
16
|
+
```
|