diff --git a/packages/main/src/components/Page/Page.jss.ts b/packages/main/src/components/Page/Page.jss.ts index 44cfddf794c..4cc919722a9 100644 --- a/packages/main/src/components/Page/Page.jss.ts +++ b/packages/main/src/components/Page/Page.jss.ts @@ -137,11 +137,6 @@ const styles = { top: CssSizeVariables.sapWcrBarHeight } }, - pageWithFooter: { - '& $contentSection': { - bottom: CssSizeVariables.sapWcrBarHeight - } - }, pageFooter: { position: 'absolute', bottom: '0', diff --git a/packages/main/src/components/Page/Page.stories.mdx b/packages/main/src/components/Page/Page.stories.mdx new file mode 100644 index 00000000000..2bdcee6fcb0 --- /dev/null +++ b/packages/main/src/components/Page/Page.stories.mdx @@ -0,0 +1,194 @@ +import { ArgsTable, Canvas, Meta, Story } from '@storybook/addon-docs/blocks'; +import { Page } from '@ui5/webcomponents-react/lib/Page'; +import { FlexBox } from '@ui5/webcomponents-react/lib/FlexBox'; +import { FlexBoxDirection } from '@ui5/webcomponents-react/lib/FlexBoxDirection'; +import { FlexBoxJustifyContent } from '@ui5/webcomponents-react/lib/FlexBoxJustifyContent'; +import { Text } from '@ui5/webcomponents-react/lib/Text'; +import { Button } from '@ui5/webcomponents-react/lib/Button'; +import { PageBackgroundDesign } from '@ui5/webcomponents-react/lib/PageBackgroundDesign'; +import { createSelectArgTypes } from '@shared/stories/createSelectArgTypes'; +import { DocsHeader } from '@shared/stories/DocsHeader'; +import { DocsCommonProps } from '@shared/stories/DocsCommonProps'; +import { sapUiContentPadding } from '@ui5/webcomponents-react-base/lib/spacing'; +import { ThemingParameters } from '@ui5/webcomponents-react-base'; +import { useState } from 'react'; + + + + + +
+ +## Example + + + + {(args) => { + return ; + }} + + + +## Properties + + + +
+ +# More Examples + +## Page with custom footer and header + + + + {(args) => { + const [footerHeight, setFooterHeight] = useState('200px'); + const [headerHeight, setHeaderHeight] = useState('44px'); + const handleFooterHeightToggle = () => { + setFooterHeight((prev) => { + if (prev === '200px') { + return '44px'; + } + return '200px'; + }); + }; + const handleHeaderHeightToggle = () => { + setHeaderHeight((prev) => { + if (prev === '200px') { + return '44px'; + } + return '200px'; + }); + }; + return ( + + + The content of your custom footer. + + + } + customHeader={ + + Custom Header Content + + } + > + + + If the content area exceeds the Page's height, it becomes scrollable. +
+ +
+ +
+ If the content area exceeds the Page's height, it becomes scrollable. +
+
+ ); + }} +
+
+ +### Code + +```jsx +const PageComponent = () => { + const [footerHeight, setFooterHeight] = useState('200px'); + const [headerHeight, setHeaderHeight] = useState('44px'); + const handleFooterHeightToggle = () => { + setFooterHeight((prev) => { + if (prev === '200px') { + return '44px'; + } + return '200px'; + }); + }; + const handleHeaderHeightToggle = () => { + setHeaderHeight((prev) => { + if (prev === '200px') { + return '44px'; + } + return '200px'; + }); + }; + return ( + + + The content of your custom footer. + + + } + customHeader={ + + Custom Header Content + + } + > + + + If the content area exceeds the Page's height, it becomes scrollable. +
+ +
+ +
+ If the content area exceeds the Page's height, it becomes scrollable. +
+
+ ); +}; +``` diff --git a/packages/main/src/components/Page/__snapshots__/Page.test.tsx.snap b/packages/main/src/components/Page/__snapshots__/Page.test.tsx.snap index eaecbd5bd64..4d837de7491 100644 --- a/packages/main/src/components/Page/__snapshots__/Page.test.tsx.snap +++ b/packages/main/src/components/Page/__snapshots__/Page.test.tsx.snap @@ -6,7 +6,7 @@ exports[`Page Basic Page 1`] = ` style="height: 100vh; width: 100vw;" >
Page Content
@@ -65,7 +66,7 @@ exports[`Page Basic Page w/o back button 1`] = ` style="height: 100vh; width: 100vw;" >
Page Content
@@ -119,6 +121,7 @@ exports[`Page Without footer and Header 1`] = ` >
Page Content
diff --git a/packages/main/src/components/Page/demo.stories.tsx b/packages/main/src/components/Page/demo.stories.tsx deleted file mode 100644 index ed7eabd735c..00000000000 --- a/packages/main/src/components/Page/demo.stories.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { Bar } from '@ui5/webcomponents-react/lib/Bar'; -import { Button } from '@ui5/webcomponents-react/lib/Button'; -import { Label } from '@ui5/webcomponents-react/lib/Label'; -import { Page } from '@ui5/webcomponents-react/lib/Page'; -import { PageBackgroundDesign } from '@ui5/webcomponents-react/lib/PageBackgroundDesign'; -import React from 'react'; -import { createSelectArgTypes } from '@shared/stories/createSelectArgTypes'; - -export const renderPage = (props) => ( -
- Button} />} - customHeader={null} - onNavButtonPress={props.onNavButtonPress} - > - - -
-); -renderPage.storyName = 'Default'; - -export default { - title: 'Layouts & Floorplans / Page', - component: Page, - argTypes: { - ...createSelectArgTypes({ backgroundDesign: PageBackgroundDesign }), - customHeader: { - type: null - }, - customFooter: { - type: null - }, - ref: { - type: null - } - }, - args: { - title: 'Page Demo', - showFooter: true, - showHeader: true, - showBackButton: true, - backgroundDesign: PageBackgroundDesign.Standard - } -}; diff --git a/packages/main/src/components/Page/index.tsx b/packages/main/src/components/Page/index.tsx index f57d148b0f8..13066c68c85 100644 --- a/packages/main/src/components/Page/index.tsx +++ b/packages/main/src/components/Page/index.tsx @@ -9,7 +9,18 @@ import { ButtonDesign } from '@ui5/webcomponents-react/lib/ButtonDesign'; import { PageBackgroundDesign } from '@ui5/webcomponents-react/lib/PageBackgroundDesign'; import { Title } from '@ui5/webcomponents-react/lib/Title'; import { TitleLevel } from '@ui5/webcomponents-react/lib/TitleLevel'; -import React, { FC, forwardRef, ReactElement, ReactNode, Ref, useCallback, useMemo } from 'react'; +import React, { + FC, + forwardRef, + ReactElement, + ReactNode, + Ref, + useCallback, + useEffect, + useMemo, + useRef, + useState +} from 'react'; import { CommonProps } from '../../interfaces/CommonProps'; import styles from './Page.jss'; @@ -33,6 +44,8 @@ export interface PagePropTypes extends CommonProps { customFooter?: ReactNode; /** * A back button will be rendered on the left area of header bar if this property is set to true. + * + * __Note__: If a custom header is used, `showBackButton` has no effect. */ showBackButton?: boolean; /** @@ -41,6 +54,8 @@ export interface PagePropTypes extends CommonProps { showFooter?: boolean; /** * Whether this page shall have a header. + * + * __Note:__ If the `customHeader` prop is not defined, `showHeader` has no effect. */ showHeader?: boolean; /** @@ -77,6 +92,11 @@ const Page: FC = forwardRef((props: PagePropTypes, ref: Ref(null); + const headerRef = useRef(null); + const [footerHeight, setFooterHeight] = useState(0); + const [headerStyles, setHeaderStyles] = useState({}); + const classes = useStyles(); const handleNavBackButtonPress = useCallback( @@ -108,27 +128,51 @@ const Page: FC = forwardRef((props: PagePropTypes, ref: Ref { + if (customHeader && showHeader) { + setHeaderStyles(headerRef.current?.offsetHeight ? { top: headerRef.current.offsetHeight } : {}); + } + if (!showHeader) { + setHeaderStyles({}); + } + }, [headerRef.current, customHeader, showHeader]); if (className) { pageContainer.put(className); } + useEffect(() => { + if (customFooter && showFooter) { + setFooterHeight(footerRef.current?.offsetHeight ?? 0); + } + if (!showFooter) { + setFooterHeight(0); + } + }, [footerRef.current, customFooter, showFooter]); + pageContainer.put(classes[`background${backgroundDesign}`]); const passThroughProps = usePassThroughHtmlProps(props, ['onNavButtonPress']); return (
- {showHeader &&
{header}
} -
{children}
- {showFooter &&
{customFooter}
} + {showHeader && ( +
+ {header} +
+ )} +
+ {children} +
+ {showFooter && ( + + )}
); });