diff --git a/packages/ibm-products-styles/src/components/PageHeader/_page-header.scss b/packages/ibm-products-styles/src/components/PageHeader/_page-header.scss index ae349bd8f4..aef30002f2 100644 --- a/packages/ibm-products-styles/src/components/PageHeader/_page-header.scss +++ b/packages/ibm-products-styles/src/components/PageHeader/_page-header.scss @@ -564,11 +564,6 @@ $right-section-alt-width: 100% - $left-section-alt-width; } .#{$block-class}__subtitle-text { - display: block; - white-space: nowrap; - } - - .#{$block-class}__subtitle-text--long { display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; diff --git a/packages/ibm-products/src/components/PageHeader/PageHeader.stories.jsx b/packages/ibm-products/src/components/PageHeader/PageHeader.stories.jsx index 22e6b8fd6b..74ac52968c 100644 --- a/packages/ibm-products/src/components/PageHeader/PageHeader.stories.jsx +++ b/packages/ibm-products/src/components/PageHeader/PageHeader.stories.jsx @@ -486,7 +486,7 @@ const pageActionsOverflowLabel = 'Page actions...'; const subtitle = 'Optional subtitle if necessary'; const longSubtitle = - 'Optional subtitle if necessary, which is very long in this case, but will need to be handled somehow. It just keeps going on and on and on and on and on.'; + 'Optional subtitle if necessary, which is very long in this case, but will need to be handled somehow. It just keeps going on and on and on and on and on and on and on and on and on and on and on.'; const demoSubtitle = 'This report details the monthly authentication failures'; const dummyPageContent = ( diff --git a/packages/ibm-products/src/components/PageHeader/PageHeader.tsx b/packages/ibm-products/src/components/PageHeader/PageHeader.tsx index f00152987e..4bc077e8d9 100644 --- a/packages/ibm-products/src/components/PageHeader/PageHeader.tsx +++ b/packages/ibm-products/src/components/PageHeader/PageHeader.tsx @@ -52,7 +52,7 @@ import cx from 'classnames'; import { getDevtoolsProps } from '../../global/js/utils/devtools'; import { pkg } from '../../settings'; import { useResizeObserver } from '../../global/js/hooks/useResizeObserver'; -import useOverflow from './hooks/useOverflow'; +import { replaceOverflowHeight } from '../../global/js/utils/replaceWithOverflow'; const componentName = 'PageHeader'; @@ -903,13 +903,11 @@ export let PageHeader = React.forwardRef( const displayedBreadcrumbs = getBreadcrumbs(); - const longTitleRef = useRef(null); - const titleRef = useRef(null); - - const isEllipsisApplied = useOverflow({ - longRef: longTitleRef, - shortRef: titleRef, - text: subtitle, + const subtitleRef = useRef(null); + const overflowSubtitleRef = useRef(null); + const isOverflowing = replaceOverflowHeight({ + overflowRef: overflowSubtitleRef, + ref: subtitleRef, }); return ( @@ -1049,21 +1047,21 @@ export let PageHeader = React.forwardRef( {subtitle && ( - {isEllipsisApplied ? ( + {isOverflowing ? ( {subtitle} ) : ( {subtitle} diff --git a/packages/ibm-products/src/components/PageHeader/PageHeaderTitle.js b/packages/ibm-products/src/components/PageHeader/PageHeaderTitle.js index 59026cd8ae..b263e620ac 100644 --- a/packages/ibm-products/src/components/PageHeader/PageHeaderTitle.js +++ b/packages/ibm-products/src/components/PageHeader/PageHeaderTitle.js @@ -10,7 +10,7 @@ import PropTypes from 'prop-types'; import cx from 'classnames'; import { DefinitionTooltip, SkeletonText } from '@carbon/react'; import { EditInPlace } from '../EditInPlace'; -import useOverflow from './hooks/useOverflow'; +import { replaceOverflowWidth } from '../../global/js/utils/replaceWithOverflow'; /** * @@ -42,11 +42,9 @@ export const PageHeaderTitle = ({ blockClass, hasBreadcrumbRow, title }) => { const longTitleRef = useRef(undefined); const titleRef = useRef(undefined); - - const isEllipsisApplied = useOverflow({ - longRef: longTitleRef, - shortRef: titleRef, - text, + const isEllipsisApplied = replaceOverflowWidth({ + overflowRef: longTitleRef, + ref: titleRef, }); if (text || !content) { diff --git a/packages/ibm-products/src/components/PageHeader/hooks/useOverflow.ts b/packages/ibm-products/src/components/PageHeader/hooks/useOverflow.ts deleted file mode 100644 index 9094b53799..0000000000 --- a/packages/ibm-products/src/components/PageHeader/hooks/useOverflow.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright IBM Corp. 2024 - * - * This source code is licensed under the Apache-2.0 license found in the - * LICENSE file in the root directory of this source tree. - */ - -import { useLayoutEffect, useState, RefObject, ReactNode } from 'react'; - -interface Props { - longRef: RefObject; - shortRef: RefObject; - text: string | ReactNode; -} - -const useOverflow = (props: Props): boolean => { - const { longRef, shortRef, text } = props; - const [isEllipsisApplied, setIsEllipsisApplied] = useState(false); - - useLayoutEffect(() => { - const isEllipsisActive = () => { - if (longRef?.current) { - return longRef.current?.offsetWidth < longRef.current?.scrollWidth; - } else if (shortRef.current) { - return shortRef.current?.offsetWidth < shortRef.current?.scrollWidth; - } - - return false; - }; - setIsEllipsisApplied(isEllipsisActive()); - }, [longRef, shortRef, text]); - - return isEllipsisApplied; -}; - -export default useOverflow; diff --git a/packages/ibm-products/src/global/js/utils/replaceWithOverflow.ts b/packages/ibm-products/src/global/js/utils/replaceWithOverflow.ts new file mode 100644 index 0000000000..5ad4217030 --- /dev/null +++ b/packages/ibm-products/src/global/js/utils/replaceWithOverflow.ts @@ -0,0 +1,47 @@ +// +// Copyright IBM Corp. 2024, 2024 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +import { RefObject } from 'react'; + +/** + * These functions are used to calculate if the content of an area is overflowing it's parent. + * Ideally used to replace an element with another if it's overflowing and vice versa. + * Check PageHeader.tsx and PageHeaderTitle.js for example usage. + */ + +type Props = { + /** + * the ref for the element not overflowing + */ + ref: RefObject; + /** + * the ref for the element that is overflowing + */ + overflowRef: RefObject; +}; + +export const replaceOverflowWidth = ({ ref, overflowRef }: Props): boolean => { + if (ref.current) { + return ref.current?.offsetWidth < ref.current?.scrollWidth; + } + if (overflowRef.current) { + return overflowRef.current?.offsetWidth < overflowRef.current?.scrollWidth; + } + return false; +}; + +export const replaceOverflowHeight = ({ ref, overflowRef }: Props): boolean => { + if (ref.current) { + return ref.current?.offsetHeight < ref.current?.scrollHeight; + } + if (overflowRef.current) { + return ( + overflowRef.current?.offsetHeight < overflowRef.current?.scrollHeight + ); + } + return false; +};