Skip to content

Commit

Permalink
fix: hide actions dropdown when empty (#456)
Browse files Browse the repository at this point in the history
  • Loading branch information
fhlavac authored Nov 22, 2024
1 parent d8af989 commit 29d6185
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 17 deletions.
7 changes: 7 additions & 0 deletions config/setupTests.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/* eslint-disable no-undef */
import 'whatwg-fetch';
import 'babel-polyfill';
import '@testing-library/jest-dom';

global.ResizeObserver = jest.fn().mockImplementation(() => ({
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn(),
}));
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { ResponsiveAction } from '@patternfly/react-component-groups/dist/dynami
import { ResponsiveActions } from '@patternfly/react-component-groups/dist/dynamic/ResponsiveActions';

export const TagCountDisabledExample: React.FunctionComponent = () => (
<ResponsiveActions breakpoint="lg">
<ResponsiveActions breakpoint="md">
<ResponsiveAction isPersistent>
Persistent Action
Persistent Action
</ResponsiveAction>
<ResponsiveAction isPinned variant='secondary'>
Pinned Action
Pinned Action
</ResponsiveAction>
<ResponsiveAction>
Overflow Action
Overflow Action
</ResponsiveAction>
</ResponsiveActions>
);
69 changes: 56 additions & 13 deletions packages/module/src/ResponsiveActions/ResponsiveActions.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import React, { useState } from 'react';
import { Button, Dropdown, DropdownList, MenuToggle, OverflowMenu, OverflowMenuContent, OverflowMenuControl, OverflowMenuDropdownItem, OverflowMenuGroup, OverflowMenuItem, OverflowMenuProps } from '@patternfly/react-core';
import React, { useState, useEffect } from 'react';
import {
Button, Dropdown, DropdownList, MenuToggle,
OverflowMenu, OverflowMenuContent, OverflowMenuControl,
OverflowMenuDropdownItem, OverflowMenuGroup, OverflowMenuItem,
OverflowMenuProps,
} from '@patternfly/react-core';
import { EllipsisVIcon } from '@patternfly/react-icons';
import { ResponsiveActionProps } from '../ResponsiveAction';

Expand All @@ -10,12 +15,51 @@ export interface ResponsiveActionsProps extends Omit<OverflowMenuProps, 'ref' |
ouiaId?: string;
/** Child actions to be displayed */
children: React.ReactNode;
/** Reference element for breakpoint calculations */
breakpointReference?: React.RefObject<HTMLElement>;
}

export const ResponsiveActions: React.FunctionComponent<ResponsiveActionsProps> = ({ ouiaId = 'ResponsiveActions', breakpoint = 'lg', children, ...props }: ResponsiveActionsProps) => {
const breakpoints = {
sm: 576,
md: 768,
lg: 992,
xl: 1200,
'2xl': 1450,
};

export const ResponsiveActions: React.FunctionComponent<ResponsiveActionsProps> = ({
ouiaId = 'ResponsiveActions',
breakpoint = 'lg',
children,
breakpointReference,
...props
}: ResponsiveActionsProps) => {
const [ isOpen, setIsOpen ] = useState(false);
const [ isBelowBreakpoint, setIsBelowBreakpoint ] = useState(false);
const currentBreakpoint = breakpoints[breakpoint];

useEffect(() => {
const referenceElement = breakpointReference?.current;
const observeSize = () => {
const elementWidth = referenceElement?.offsetWidth || window.innerWidth;
setIsBelowBreakpoint(elementWidth < currentBreakpoint);
};

const observer = new ResizeObserver(observeSize);

if (referenceElement) {
observer.observe(referenceElement);
} else {
window.addEventListener('resize', observeSize);
observeSize();
}

return () => {
observer.disconnect();
window.removeEventListener('resize', observeSize);
};
}, [ breakpointReference, currentBreakpoint ]);

// separate persistent, pinned and collapsed actions
const persistentActions: React.ReactNode[] = [];
const pinnedActions: React.ReactNode[] = [];
const dropdownItems: React.ReactNode[] = [];
Expand All @@ -24,18 +68,17 @@ export const ResponsiveActions: React.FunctionComponent<ResponsiveActionsProps>
if (React.isValidElement<ResponsiveActionProps>(child)) {
const { isPersistent, isPinned, key = index, children, onClick, ...actionProps } = child.props;

if (isPersistent || isPinned) {
if (isPersistent || (isPinned && !isBelowBreakpoint)) {
(isPersistent ? persistentActions : pinnedActions).push(
<OverflowMenuItem key={key} isPersistent={isPersistent}>
<Button onClick={onClick} ouiaId={`${ouiaId}-action-${key}`} {...actionProps}>
{children}
</Button>
</OverflowMenuItem>
);
}
if (!isPersistent) {
} else {
dropdownItems.push(
<OverflowMenuDropdownItem key={key} onClick={onClick} isShared={isPinned} ouiaId={`${ouiaId}-action-${key}`}>
<OverflowMenuDropdownItem key={key} onClick={onClick} ouiaId={`${ouiaId}-action-${key}`}>
{children}
</OverflowMenuDropdownItem>
);
Expand All @@ -45,20 +88,20 @@ export const ResponsiveActions: React.FunctionComponent<ResponsiveActionsProps>

return (
<OverflowMenu breakpoint={breakpoint} data-ouia-component-id={`${ouiaId}-menu`} {...props}>
{persistentActions.length > 0 ? (
{persistentActions.length > 0 && (
<OverflowMenuContent isPersistent data-ouia-component-id={`${ouiaId}-menu-persistent-content`}>
<OverflowMenuGroup groupType="button" data-ouia-component-id={`${ouiaId}-menu-persistent-group`} isPersistent>
{persistentActions}
</OverflowMenuGroup>
</OverflowMenuContent>
) : null}
{pinnedActions.length > 0 ? (
)}
{pinnedActions.length > 0 && (
<OverflowMenuContent data-ouia-component-id={`${ouiaId}-menu-pinned-content`}>
<OverflowMenuGroup groupType="button" data-ouia-component-id={`${ouiaId}-menu-pinned-group`}>
{pinnedActions}
</OverflowMenuGroup>
</OverflowMenuContent>
) : null}
)}
{dropdownItems.length > 0 && (
<OverflowMenuControl hasAdditionalOptions data-ouia-component-id={`${ouiaId}-menu-control`}>
<Dropdown
Expand Down Expand Up @@ -89,4 +132,4 @@ export const ResponsiveActions: React.FunctionComponent<ResponsiveActionsProps>
);
};

export default ResponsiveActions;
export default ResponsiveActions;

0 comments on commit 29d6185

Please sign in to comment.