diff --git a/packages/react-core/src/components/Toolbar/ToolbarContent.tsx b/packages/react-core/src/components/Toolbar/ToolbarContent.tsx index f510296e3e2..c2c269fe6c9 100644 --- a/packages/react-core/src/components/Toolbar/ToolbarContent.tsx +++ b/packages/react-core/src/components/Toolbar/ToolbarContent.tsx @@ -5,6 +5,7 @@ import { ToolbarContentContext, ToolbarContext } from './ToolbarUtils'; import { formatBreakpointMods } from '../../helpers/util'; import { ToolbarExpandableContent } from './ToolbarExpandableContent'; import { PageContext } from '../Page/PageContext'; +import { debounce, canUseDOM } from '../../helpers/util'; export interface ToolbarContentProps extends React.HTMLProps { /** Classes applied to root element of the data toolbar content row */ @@ -34,11 +35,17 @@ export interface ToolbarContentProps extends React.HTMLProps { /** Id of the parent Toolbar component */ toolbarId?: string; } - +// TODO: do i have any toggle groups? do any of them lack a breakpoint prop? I need have ordered references to them. +// I need to know how wide the toggle groups are when they are not collapsed +// How wide are my children collectively? are they wider than me? +// Collapse toggle groups in priority order, expand toggles in reverse priority order +// ToolbarContents tells toggle groups which state they are in and toggle group needs pf-m-show if it's not collapsed. +// BONUS: ToolbarGroups with visibility breakpoint mods could also have a priority order and be hidden when running out of space export class ToolbarContent extends React.Component { static displayName = 'ToolbarContent'; private expandableContentRef = React.createRef(); private chipContainerRef = React.createRef(); + private contentRef = React.createRef(); private static currentId = 0; static defaultProps: ToolbarContentProps = { @@ -46,6 +53,23 @@ export class ToolbarContent extends React.Component { showClearFiltersButton: false }; + componentDidMount() { + // Initial check if should be shown + this.resize(); + } + + resize = () => { + if (this.contentRef?.current) { + const currentWidth = this.contentRef.current.clientWidth; + + if (this.state.width !== currentWidth) { + this.setState({ width: currentWidth }); + } + } + }; + + handleResize = debounce(this.resize, 250); + render() { const { className, @@ -70,13 +94,11 @@ export class ToolbarContent extends React.Component { formatBreakpointMods(visibility, styles, '', getBreakpoint(width)), className )} + ref={this.contentRef} {...props} > {({ - clearAllFilters: clearAllFiltersContext, - clearFiltersButtonText: clearFiltersButtonContext, - showClearFiltersButton: showClearFiltersButtonContext, toolbarId: toolbarIdContext }) => { const expandableContentId = `${ @@ -85,9 +107,8 @@ export class ToolbarContent extends React.Component { return (
{ > {children}
-
); }} diff --git a/packages/react-core/src/components/Toolbar/ToolbarExpandableContent.tsx b/packages/react-core/src/components/Toolbar/ToolbarExpandableContent.tsx index 1bef7ee02ac..3001a3f91cc 100644 --- a/packages/react-core/src/components/Toolbar/ToolbarExpandableContent.tsx +++ b/packages/react-core/src/components/Toolbar/ToolbarExpandableContent.tsx @@ -10,6 +10,8 @@ import { ToolbarContext } from './ToolbarUtils'; import { PickOptional } from '../../helpers/typeUtils'; export interface ToolbarExpandableContentProps extends React.HTMLProps { + /** Content displayed in the expandable content */ + children?: React.ReactNode; /** Classes added to the root element of the data toolbar expandable content */ className?: string; /** Flag indicating the expandable content is expanded */ @@ -37,6 +39,7 @@ export class ToolbarExpandableContent extends React.Component - +
+ {children} {numberOfFilters > 0 && ( diff --git a/packages/react-core/src/components/Toolbar/ToolbarToggleGroup.tsx b/packages/react-core/src/components/Toolbar/ToolbarToggleGroup.tsx index e5040aad334..c50c91f9926 100644 --- a/packages/react-core/src/components/Toolbar/ToolbarToggleGroup.tsx +++ b/packages/react-core/src/components/Toolbar/ToolbarToggleGroup.tsx @@ -8,8 +8,10 @@ import { Button } from '../Button'; import globalBreakpointLg from '@patternfly/react-tokens/dist/esm/global_breakpoint_lg'; import { formatBreakpointMods, toCamel, canUseDOM } from '../../helpers/util'; import { PageContext } from '../Page/PageContext'; +import { ToolbarExpandableContent } from './ToolbarExpandableContent'; +import { Popper } from '../../helpers'; -export interface ToolbarToggleGroupProps extends ToolbarGroupProps { +export interface ToolbarToggleGroupProps extends ToolbarGroupProps{ /** An icon to be rendered when the toggle group has collapsed down */ toggleIcon: React.ReactNode; /** Controls when filters are shown and when the toggle button is hidden. */ @@ -48,98 +50,102 @@ export interface ToolbarToggleGroupProps extends ToolbarGroupProps { }; } -export class ToolbarToggleGroup extends React.Component { - static displayName = 'ToolbarToggleGroup'; - isContentPopup = () => { +export const ToolbarToggleGroup: React.FunctionComponent = ({ + toggleIcon, + variant, + visibility, + visiblity, + breakpoint, + alignment, + spacer, + spaceItems, + className, + children, + ...props + }: ToolbarToggleGroupProps +) => { + const { width, getBreakpoint } = React.useContext(PageContext); + const { isExpanded, toggleIsExpanded } = React.useContext(ToolbarContext); + const { contentRef } = React.useContext(ToolbarContentContext); + + const isContentPopup = () => { const viewportSize = canUseDOM ? window.innerWidth : 1200; const lgBreakpointValue = parseInt(globalBreakpointLg.value); return viewportSize < lgBreakpointValue; }; - render() { - const { - toggleIcon, - variant, - visibility, - breakpoint, - alignment, - spacer, - spaceItems, - className, - children, - ...props - } = this.props; - + React.useEffect(() => { if (!breakpoint && !toggleIcon) { // eslint-disable-next-line no-console console.error('ToolbarToggleGroup will not be visible without a breakpoint or toggleIcon.'); } - return ( - - {({ width, getBreakpoint }) => ( - - {({ isExpanded, toggleIsExpanded }) => ( - - {({ expandableContentRef, expandableContentId }) => { - if (expandableContentRef.current && expandableContentRef.current.classList) { - if (isExpanded) { - expandableContentRef.current.classList.add(styles.modifiers.expanded); - } else { - expandableContentRef.current.classList.remove(styles.modifiers.expanded); - } - } + if (visiblity !== undefined) { + // eslint-disable-next-line no-console + console.warn( + 'The ToolbarToggleGroup visiblity prop has been deprecated. ' + + 'Please use the correctly spelled visibility prop instead.' + ); + } + }, [breakpoint, toggleIcon, visiblity]); - const breakpointMod: { - md?: 'show'; - lg?: 'show'; - xl?: 'show'; - '2xl'?: 'show'; - } = {}; - breakpointMod[breakpoint] = 'show'; + const breakpointMod: { + md?: 'show'; + lg?: 'show'; + xl?: 'show'; + '2xl'?: 'show'; + } = {}; + breakpointMod[breakpoint] = 'show'; - return ( -
-
- -
- {isExpanded - ? (ReactDOM.createPortal( - children, - expandableContentRef.current.firstElementChild - ) as React.ReactElement) - : children} -
- ); - }} -
- )} -
- )} -
- ); + const expandableContent = () => { + console.log(children); + return ( + + {children} + + ); } + + const popper = ( +
+ +
+ ); + + return ( +
+ + { !isExpanded && children } +
+ ); } +ToolbarToggleGroup.displayName = 'ToolbarToggleGroup'; diff --git a/packages/react-core/src/components/Toolbar/ToolbarUtils.tsx b/packages/react-core/src/components/Toolbar/ToolbarUtils.tsx index 9ee37c99f85..be18ff7ef5d 100644 --- a/packages/react-core/src/components/Toolbar/ToolbarUtils.tsx +++ b/packages/react-core/src/components/Toolbar/ToolbarUtils.tsx @@ -28,15 +28,13 @@ export const ToolbarContext = React.createContext({ }); interface ToolbarContentContextProps { - expandableContentRef: RefObject; - expandableContentId: string; chipContainerRef: RefObject; + contentRef: RefObject; } export const ToolbarContentContext = React.createContext({ - expandableContentRef: null, - expandableContentId: '', - chipContainerRef: null + chipContainerRef: null, + contentRef: null }); export const globalBreakpoints = {