From 4477eccef7071bb7ac0ddf28b78d7b0556e2dd2d Mon Sep 17 00:00:00 2001 From: Katie McFaul Date: Mon, 20 Feb 2023 16:22:04 -0500 Subject: [PATCH] feat(Popper): add width props, remove popperMatchesTriggerWidth --- .../__snapshots__/DatePicker.test.tsx.snap | 2 +- .../Dropdown/DropdownWithContext.tsx | 4 +- .../LabelGroupEditableAddDropdown.tsx | 2 +- .../examples/LabelGroupEditableAddModal.tsx | 4 +- .../__tests__/__snapshots__/Nav.test.tsx.snap | 2 +- .../Pagination/PaginationOptionsMenu.tsx | 8 +-- .../src/components/Popover/Popover.tsx | 2 +- .../__snapshots__/SearchInput.test.tsx.snap | 2 +- .../src/components/Tabs/OverflowTab.tsx | 10 +-- .../Tabs/__tests__/OverflowTab.test.tsx | 32 ++++----- .../__snapshots__/OverflowTab.test.tsx.snap | 6 -- .../src/components/Tooltip/Tooltip.tsx | 4 +- .../examples/ComposableActionsMenu.tsx | 4 +- .../ComposableApplicationLauncher.tsx | 28 ++++---- .../examples/ComposableContextSelector.tsx | 4 +- .../examples/ComposableDateSelect.tsx | 2 +- .../examples/ComposableDrilldownMenu.tsx | 2 +- .../examples/ComposableDropdwnVariants.tsx | 12 ++-- .../examples/ComposableFlyout.tsx | 4 +- .../examples/ComposableTreeViewMenu.tsx | 24 ++++--- .../examples/FilterAttributeSearch.tsx | 12 ++-- .../Filters/examples/FilterCheckboxSelect.tsx | 14 ++-- .../demos/Filters/examples/FilterFaceted.tsx | 18 ++--- .../examples/FilterMixedSelectGroup.tsx | 12 ++-- .../examples/FilterSameSelectGroup.tsx | 10 +-- .../Filters/examples/FilterSearchInput.tsx | 10 +-- .../Filters/examples/FilterSingleSelect.tsx | 10 +-- .../react-core/src/helpers/Popper/Popper.tsx | 70 ++++++++++++++----- .../src/next/components/Select/Select.tsx | 6 +- .../src/components/Table/ActionsColumn.tsx | 14 ++-- 30 files changed, 180 insertions(+), 154 deletions(-) diff --git a/packages/react-core/src/components/DatePicker/__tests__/__snapshots__/DatePicker.test.tsx.snap b/packages/react-core/src/components/DatePicker/__tests__/__snapshots__/DatePicker.test.tsx.snap index b62da17668e..7c9026d9fd1 100644 --- a/packages/react-core/src/components/DatePicker/__tests__/__snapshots__/DatePicker.test.tsx.snap +++ b/packages/react-core/src/components/DatePicker/__tests__/__snapshots__/DatePicker.test.tsx.snap @@ -57,7 +57,7 @@ exports[`With popover opened 1`] = ` aria-modal="true" class="pf-c-popover pf-m-no-padding pf-m-width-auto pf-m-top" role="dialog" - style="opacity: 1; transition: opacity 300ms cubic-bezier(.54, 1.5, .38, 1.11); position: absolute; left: 0px; top: 0px; z-index: 9999;" + style="opacity: 1; transition: opacity 300ms cubic-bezier(.54, 1.5, .38, 1.11); position: absolute; left: 0px; top: 0px; z-index: 9999; min-width: auto;" >
- {React.Children.map(toggle, oneToggle => + {React.Children.map(toggle, (oneToggle) => React.cloneElement(oneToggle, { parentRef: this.baseComponentRef, getMenuRef: this.getMenuComponentRef, @@ -175,7 +175,7 @@ export class DropdownWithContext extends React.Component ); }} diff --git a/packages/react-core/src/components/LabelGroup/examples/LabelGroupEditableAddDropdown.tsx b/packages/react-core/src/components/LabelGroup/examples/LabelGroupEditableAddDropdown.tsx index 64650693ac9..4bf4d859ed1 100644 --- a/packages/react-core/src/components/LabelGroup/examples/LabelGroupEditableAddDropdown.tsx +++ b/packages/react-core/src/components/LabelGroup/examples/LabelGroupEditableAddDropdown.tsx @@ -114,7 +114,7 @@ export const LabelGroupEditableAddDropdown: React.FunctionComponent = () => { categoryName="Label group 1" numLabels={5} isEditable - addLabelControl={} + addLabelControl={} > {labels.map((label, index) => (
@@ -298,7 +298,7 @@ export const LabelGroupEditableAddModal: React.FunctionComponent = () => { popper={iconMenu} appendTo={iconContainerRef.current as HTMLElement} isVisible={isIconOpen} - popperMatchesTriggerWidth={false} + minWidth="auto" /> diff --git a/packages/react-core/src/components/Nav/__tests__/__snapshots__/Nav.test.tsx.snap b/packages/react-core/src/components/Nav/__tests__/__snapshots__/Nav.test.tsx.snap index 8267e38ea9c..5bb8bea6e23 100644 --- a/packages/react-core/src/components/Nav/__tests__/__snapshots__/Nav.test.tsx.snap +++ b/packages/react-core/src/components/Nav/__tests__/__snapshots__/Nav.test.tsx.snap @@ -1082,7 +1082,7 @@ exports[`Nav Nav List with flyout 1`] = ` data-popper-escaped="true" data-popper-placement="right-start" data-popper-reference-hidden="true" - style="position: absolute; left: 0px; top: 0px; z-index: 9999; width: 0px; transform: translate(0px, 0px);" + style="position: absolute; left: 0px; top: 0px; z-index: 9999; min-width: 0px; transform: translate(0px, 0px);" >
Flyout test diff --git a/packages/react-core/src/components/Pagination/PaginationOptionsMenu.tsx b/packages/react-core/src/components/Pagination/PaginationOptionsMenu.tsx index 2426d6d8218..dd622b1180f 100644 --- a/packages/react-core/src/components/Pagination/PaginationOptionsMenu.tsx +++ b/packages/react-core/src/components/Pagination/PaginationOptionsMenu.tsx @@ -79,11 +79,11 @@ export const PaginationOptionsMenu: React.FunctionComponent(null); const onToggle = () => { - setIsOpen(prevState => !prevState); + setIsOpen((prevState) => !prevState); }; const onSelect = () => { - setIsOpen(prevState => !prevState); + setIsOpen((prevState) => !prevState); toggleRef.current?.focus(); }; @@ -156,7 +156,7 @@ export const PaginationOptionsMenu: React.FunctionComponent handleNewPerPage(event, value)} + onClick={(event) => handleNewPerPage(event, value)} > {title} {` ${perPageSuffix}`} @@ -204,7 +204,7 @@ export const PaginationOptionsMenu: React.FunctionComponent
); diff --git a/packages/react-core/src/components/Popover/Popover.tsx b/packages/react-core/src/components/Popover/Popover.tsx index d0de00b5d7a..3273fdad22d 100644 --- a/packages/react-core/src/components/Popover/Popover.tsx +++ b/packages/react-core/src/components/Popover/Popover.tsx @@ -460,7 +460,7 @@ export const Popover: React.FunctionComponent = ({ trigger={children} reference={reference} popper={content} - popperMatchesTriggerWidth={false} + minWidth="auto" appendTo={appendTo} isVisible={visible} positionModifiers={positionModifiers} diff --git a/packages/react-core/src/components/SearchInput/__tests__/__snapshots__/SearchInput.test.tsx.snap b/packages/react-core/src/components/SearchInput/__tests__/__snapshots__/SearchInput.test.tsx.snap index 7e7a837fe54..e917f3523bf 100644 --- a/packages/react-core/src/components/SearchInput/__tests__/__snapshots__/SearchInput.test.tsx.snap +++ b/packages/react-core/src/components/SearchInput/__tests__/__snapshots__/SearchInput.test.tsx.snap @@ -257,7 +257,7 @@ exports[`SearchInput advanced search with custom attributes 1`] = ` data-popper-escaped="true" data-popper-placement="bottom-start" data-popper-reference-hidden="true" - style="position: absolute; top: 0px; left: 0px; transform: translate(0px, 0px); width: 0px; z-index: 9999;" + style="position: absolute; top: 0px; left: 0px; transform: translate(0px, 0px); min-width: 0px; z-index: 9999;" >
= ({ }; }, [isExpanded, menuRef, overflowTabRef]); - const selectedTab = overflowingTabs.find(tab => tab.eventKey === localActiveKey); + const selectedTab = overflowingTabs.find((tab) => tab.eventKey === localActiveKey); const tabTitle = selectedTab?.title ? selectedTab.title : defaultTitleText; const toggleMenu = () => { - setIsExpanded(prevIsExpanded => !prevIsExpanded); + setIsExpanded((prevIsExpanded) => !prevIsExpanded); setTimeout(() => { if (menuRef?.current) { const firstElement = menuRef.current.querySelector('li > button,input:not(:disabled)'); @@ -111,7 +111,7 @@ export const OverflowTab: React.FunctionComponent = ({ ); - const tabs = overflowingTabs.map(tab => ( + const tabs = overflowingTabs.map((tab) => ( {tab.title} @@ -119,7 +119,7 @@ export const OverflowTab: React.FunctionComponent = ({ const onTabSelect = (event: React.MouseEvent, key: number | string) => { closeMenu(); - const selectedTabRef = overflowingTabs.find(tab => tab.eventKey === key).tabContentRef; + const selectedTabRef = overflowingTabs.find((tab) => tab.eventKey === key).tabContentRef; handleTabClick(event, key, selectedTabRef); }; @@ -139,7 +139,7 @@ export const OverflowTab: React.FunctionComponent = ({ popper={overflowMenu} popperRef={menuRef} isVisible={isExpanded} - popperMatchesTriggerWidth={false} + minWidth="auto" appendTo={overflowLIRef.current} zIndex={zIndex} /> diff --git a/packages/react-core/src/components/Tabs/__tests__/OverflowTab.test.tsx b/packages/react-core/src/components/Tabs/__tests__/OverflowTab.test.tsx index 5b3f748cb68..da4c39bcf47 100644 --- a/packages/react-core/src/components/Tabs/__tests__/OverflowTab.test.tsx +++ b/packages/react-core/src/components/Tabs/__tests__/OverflowTab.test.tsx @@ -6,11 +6,10 @@ import { OverflowTab } from '../OverflowTab'; import { TabsContext } from '../TabsContext'; jest.mock('../../../helpers', () => ({ - Popper: ({ trigger, popper, isVisible, popperMatchesTriggerWidth, appendTo }) => ( + Popper: ({ trigger, popper, isVisible, appendTo }) => (
{trigger}
{isVisible && popper}
-

Popper matches trigger width: {`${popperMatchesTriggerWidth}`}

Append to class name: {appendTo && `${appendTo.className}`}

) @@ -206,8 +205,8 @@ test('Closes the overflowing tabs menu when a tab is selected', async () => { }, - { title: 'Tab two', eventKey: 2, tabContentRef: ('fakeRef' as unknown) as React.RefObject } + { title: 'Tab one', eventKey: 1, tabContentRef: 'fakeRef' as unknown as React.RefObject }, + { title: 'Tab two', eventKey: 2, tabContentRef: 'fakeRef' as unknown as React.RefObject } ]} /> @@ -228,8 +227,8 @@ test('Closes the overflowing tabs menu when the user clicks outside of the menu' }, - { title: 'Tab two', eventKey: 2, tabContentRef: ('fakeRef' as unknown) as React.RefObject } + { title: 'Tab one', eventKey: 1, tabContentRef: 'fakeRef' as unknown as React.RefObject }, + { title: 'Tab two', eventKey: 2, tabContentRef: 'fakeRef' as unknown as React.RefObject } ]} /> @@ -250,7 +249,7 @@ test('Calls the onTabClick callback provided via context when a tab is clicked', } + { title: 'Tab one', eventKey: 1, tabContentRef: 'fakeRef' as unknown as React.RefObject } ]} /> @@ -303,7 +302,7 @@ test('Uses the selected tab title as the overflow tab title rather than the defa } + { title: 'Tab one', eventKey: 1, tabContentRef: 'fakeRef' as unknown as React.RefObject } ]} /> @@ -323,7 +322,7 @@ test('Uses the selected tab title as the overflow tab title rather than the defa } + { title: 'Tab one', eventKey: 1, tabContentRef: 'fakeRef' as unknown as React.RefObject } ]} defaultTitleText="Test" /> @@ -369,13 +368,6 @@ test('Renders the tab with aria-expanded set to true when the menu is opened', a expect(overflowTab).toHaveAttribute('aria-expanded', 'true'); }); -test('Passes Popper popperMatchesTriggerWidth set to false', () => { - render(); - - // This assertion relies on the structure of the Popper mock to verify the correct props are being sent to Popper - expect(screen.getByText('Popper matches trigger width: false')).toBeVisible(); -}); - test('Passes Popper an appendTo value of the presentation element', async () => { const user = userEvent.setup(); @@ -394,7 +386,7 @@ test('Does not render an overflowing tab as a selected menu item by default', as } + { title: 'Tab one', eventKey: 1, tabContentRef: 'fakeRef' as unknown as React.RefObject } ]} /> @@ -413,7 +405,7 @@ test('Renders an overflowing tab as a selected menu item when its key matches th } + { title: 'Tab one', eventKey: 1, tabContentRef: 'fakeRef' as unknown as React.RefObject } ]} /> @@ -432,8 +424,8 @@ test('Matches snapshot when expanded', async () => { }, - { title: 'Tab two', eventKey: 2, tabContentRef: ('fakeRef' as unknown) as React.RefObject } + { title: 'Tab one', eventKey: 1, tabContentRef: 'fakeRef' as unknown as React.RefObject }, + { title: 'Tab two', eventKey: 2, tabContentRef: 'fakeRef' as unknown as React.RefObject } ]} /> diff --git a/packages/react-core/src/components/Tabs/__tests__/__snapshots__/OverflowTab.test.tsx.snap b/packages/react-core/src/components/Tabs/__tests__/__snapshots__/OverflowTab.test.tsx.snap index c5c13b9e85e..33f4d7e26cb 100644 --- a/packages/react-core/src/components/Tabs/__tests__/__snapshots__/OverflowTab.test.tsx.snap +++ b/packages/react-core/src/components/Tabs/__tests__/__snapshots__/OverflowTab.test.tsx.snap @@ -78,9 +78,6 @@ exports[`Matches snapshot when expanded 1`] = `
-

- Popper matches trigger width: false -

Append to class name: pf-c-tabs__item pf-m-overflow pf-m-current

@@ -166,9 +163,6 @@ exports[`Renders tabs passed via overflowingTabs when expanded in strict mode 1` -

- Popper matches trigger width: false -

Append to class name: pf-c-tabs__item pf-m-overflow

diff --git a/packages/react-core/src/components/Tooltip/Tooltip.tsx b/packages/react-core/src/components/Tooltip/Tooltip.tsx index 816bf24a63c..ab3b75b231d 100644 --- a/packages/react-core/src/components/Tooltip/Tooltip.tsx +++ b/packages/react-core/src/components/Tooltip/Tooltip.tsx @@ -178,7 +178,7 @@ export const Tooltip: React.FunctionComponent = ({ const prevExitDelayRef = React.useRef(); const clearTimeouts = (timeoutRefs: React.RefObject[]) => { - timeoutRefs.forEach(ref => { + timeoutRefs.forEach((ref) => { if (ref.current) { clearTimeout(ref.current); } @@ -317,7 +317,7 @@ export const Tooltip: React.FunctionComponent = ({ trigger={aria !== 'none' && visible ? addAriaToTrigger() : children} reference={reference} popper={content} - popperMatchesTriggerWidth={false} + minWidth="auto" appendTo={appendTo} isVisible={visible} positionModifiers={positionModifiers} diff --git a/packages/react-core/src/demos/ComposableMenu/examples/ComposableActionsMenu.tsx b/packages/react-core/src/demos/ComposableMenu/examples/ComposableActionsMenu.tsx index fe4c445ec5f..2c64b07aa1d 100644 --- a/packages/react-core/src/demos/ComposableMenu/examples/ComposableActionsMenu.tsx +++ b/packages/react-core/src/demos/ComposableMenu/examples/ComposableActionsMenu.tsx @@ -41,7 +41,7 @@ export const ComposableActionsMenu: React.FunctionComponent = () => { } if (selectedItems.includes(itemId)) { - setSelectedItems(selectedItems.filter(id => id !== itemId)); + setSelectedItems(selectedItems.filter((id) => id !== itemId)); } else { setSelectedItems([...selectedItems, itemId]); } @@ -122,5 +122,5 @@ export const ComposableActionsMenu: React.FunctionComponent = () => { ); - return ; + return ; }; diff --git a/packages/react-core/src/demos/ComposableMenu/examples/ComposableApplicationLauncher.tsx b/packages/react-core/src/demos/ComposableMenu/examples/ComposableApplicationLauncher.tsx index 0143bf83ffa..8bfba9bd0fa 100644 --- a/packages/react-core/src/demos/ComposableMenu/examples/ComposableApplicationLauncher.tsx +++ b/packages/react-core/src/demos/ComposableMenu/examples/ComposableApplicationLauncher.tsx @@ -90,7 +90,7 @@ export const ComposableApplicationLauncher: React.FunctionComponent = () => { id="1" isFavorited={favorites.includes('1')} to="#default-link2" - onClick={ev => ev.preventDefault()} + onClick={(ev) => ev.preventDefault()} > Application 2 @@ -103,7 +103,7 @@ export const ComposableApplicationLauncher: React.FunctionComponent = () => { itemId="2" id="2" isFavorited={favorites.includes('2')} - component={props => } + component={(props) => } > @reach/router Link @@ -113,7 +113,7 @@ export const ComposableApplicationLauncher: React.FunctionComponent = () => { isFavorited={favorites.includes('3')} isExternalLink icon={} - component={props => } + component={(props) => } > @reach/router Link with icon @@ -135,15 +135,15 @@ export const ComposableApplicationLauncher: React.FunctionComponent = () => { const createFavorites = (favIds: string[]) => { const favorites: unknown[] = []; - menuItems.forEach(item => { + menuItems.forEach((item) => { if (item.type === MenuList) { - item.props.children.filter(child => { + item.props.children.filter((child) => { if (favIds.includes(child.props.itemId)) { favorites.push(child); } }); } else if (item.type === MenuGroup) { - item.props.children.props.children.filter(child => { + item.props.children.props.children.filter((child) => { if (favIds.includes(child.props.itemId)) { favorites.push(child); } @@ -164,11 +164,11 @@ export const ComposableApplicationLauncher: React.FunctionComponent = () => { } let keepDivider = false; const filteredCopy = items - .map(group => { + .map((group) => { if (group.type === MenuGroup) { const filteredGroup = React.cloneElement(group, { children: React.cloneElement(group.props.children, { - children: group.props.children.props.children.filter(child => { + children: group.props.children.props.children.filter((child) => { if (filteredIds.includes(child.props.itemId)) { return child; } @@ -184,7 +184,7 @@ export const ComposableApplicationLauncher: React.FunctionComponent = () => { } } else if (group.type === MenuList) { const filteredGroup = React.cloneElement(group, { - children: group.props.children.filter(child => { + children: group.props.children.filter((child) => { if (filteredIds.includes(child.props.itemId)) { return child; } @@ -202,7 +202,7 @@ export const ComposableApplicationLauncher: React.FunctionComponent = () => { } } }) - .filter(newGroup => newGroup); + .filter((newGroup) => newGroup); if (filteredCopy.length > 0) { const lastGroup = filteredCopy.pop(); @@ -222,8 +222,8 @@ export const ComposableApplicationLauncher: React.FunctionComponent = () => { const filteredIds = refFullOptions - ?.filter(item => (item as HTMLElement).innerText.toLowerCase().includes(textValue.toString().toLowerCase())) - .map(item => item.id) || []; + ?.filter((item) => (item as HTMLElement).innerText.toLowerCase().includes(textValue.toString().toLowerCase())) + .map((item) => item.id) || []; setFilteredIds(filteredIds); }; @@ -232,7 +232,7 @@ export const ComposableApplicationLauncher: React.FunctionComponent = () => { if (actionId === 'fav') { const isFavorite = favorites.includes(itemId); if (isFavorite) { - setFavorites(favorites.filter(fav => fav !== itemId)); + setFavorites(favorites.filter((fav) => fav !== itemId)); } else { setFavorites([...favorites, itemId]); } @@ -265,5 +265,5 @@ export const ComposableApplicationLauncher: React.FunctionComponent = () => { ); - return ; + return ; }; diff --git a/packages/react-core/src/demos/ComposableMenu/examples/ComposableContextSelector.tsx b/packages/react-core/src/demos/ComposableMenu/examples/ComposableContextSelector.tsx index 6cc7fb43e08..3f30eb393a2 100644 --- a/packages/react-core/src/demos/ComposableMenu/examples/ComposableContextSelector.tsx +++ b/packages/react-core/src/demos/ComposableMenu/examples/ComposableContextSelector.tsx @@ -130,7 +130,7 @@ export const ComposableContextSelector: React.FunctionComponent = () => { const filtered = searchInputValue === '' ? items - : items.filter(item => { + : items.filter((item) => { const str = typeof item === 'string' ? item : item.text; return str.toLowerCase().indexOf(searchInputValue.toLowerCase()) !== -1; }); @@ -198,5 +198,5 @@ export const ComposableContextSelector: React.FunctionComponent = () => { ); - return ; + return ; }; diff --git a/packages/react-core/src/demos/ComposableMenu/examples/ComposableDateSelect.tsx b/packages/react-core/src/demos/ComposableMenu/examples/ComposableDateSelect.tsx index 9db2f817fc1..38044f0660a 100644 --- a/packages/react-core/src/demos/ComposableMenu/examples/ComposableDateSelect.tsx +++ b/packages/react-core/src/demos/ComposableMenu/examples/ComposableDateSelect.tsx @@ -109,5 +109,5 @@ export const ComposableSimpleDropdown: React.FunctionComponent = () => { ); - return ; + return ; }; diff --git a/packages/react-core/src/demos/ComposableMenu/examples/ComposableDrilldownMenu.tsx b/packages/react-core/src/demos/ComposableMenu/examples/ComposableDrilldownMenu.tsx index 4213f0e8259..0432d032609 100644 --- a/packages/react-core/src/demos/ComposableMenu/examples/ComposableDrilldownMenu.tsx +++ b/packages/react-core/src/demos/ComposableMenu/examples/ComposableDrilldownMenu.tsx @@ -247,5 +247,5 @@ export const ComposableDrilldownMenu: React.FunctionComponent = () => { ); - return ; + return ; }; diff --git a/packages/react-core/src/demos/ComposableMenu/examples/ComposableDropdwnVariants.tsx b/packages/react-core/src/demos/ComposableMenu/examples/ComposableDropdwnVariants.tsx index cf82356e55d..28e923f4e87 100644 --- a/packages/react-core/src/demos/ComposableMenu/examples/ComposableDropdwnVariants.tsx +++ b/packages/react-core/src/demos/ComposableMenu/examples/ComposableDropdwnVariants.tsx @@ -133,7 +133,7 @@ export const ComposableDropdwnVariants: React.FunctionComponent = () => { itemId={0} to="#default-link0" // just for demo so that navigation is not triggered - onClick={event => event.preventDefault()} + onClick={(event) => event.preventDefault()} > My profile @@ -141,7 +141,7 @@ export const ComposableDropdwnVariants: React.FunctionComponent = () => { itemId={1} to="#default-link1" // just for demo so that navigation is not triggered - onClick={event => event.preventDefault()} + onClick={(event) => event.preventDefault()} > User management @@ -149,7 +149,7 @@ export const ComposableDropdwnVariants: React.FunctionComponent = () => { itemId={2} to="#default-link2" // just for demo so that navigation is not triggered - onClick={event => event.preventDefault()} + onClick={(event) => event.preventDefault()} > Logout @@ -163,7 +163,7 @@ export const ComposableDropdwnVariants: React.FunctionComponent = () => { itemId={0} to="#default-link0" // just for demo so that navigation is not triggered - onClick={event => event.preventDefault()} + onClick={(event) => event.preventDefault()} > Link @@ -173,7 +173,7 @@ export const ComposableDropdwnVariants: React.FunctionComponent = () => { isDisabled to="#default-link2" // just for demo so that navigation is not triggered - onClick={event => event.preventDefault()} + onClick={(event) => event.preventDefault()} > Disabled link @@ -230,7 +230,7 @@ export const ComposableDropdwnVariants: React.FunctionComponent = () => { trigger={buildToggle()} popper={menu} isVisible={isOpen} - popperMatchesTriggerWidth={['image', 'checkbox'].includes(toggleSelected)} + {...(['image', 'checkbox'].includes(toggleSelected) && { minWidth: 'auto' })} /> ); diff --git a/packages/react-core/src/demos/ComposableMenu/examples/ComposableFlyout.tsx b/packages/react-core/src/demos/ComposableMenu/examples/ComposableFlyout.tsx index 4884f81bbd3..cfaf1af2824 100644 --- a/packages/react-core/src/demos/ComposableMenu/examples/ComposableFlyout.tsx +++ b/packages/react-core/src/demos/ComposableMenu/examples/ComposableFlyout.tsx @@ -17,7 +17,7 @@ const FlyoutMenu: React.FunctionComponent = ({ depth, children Next menu - {Array.from(new Array(15 - depth), (x, i) => i + 1).map(j => ( + {Array.from(new Array(15 - depth), (x, i) => i + 1).map((j) => ( Menu {depth} item {j} @@ -100,5 +100,5 @@ export const ComposableFlyout: React.FunctionComponent = () => { ); - return ; + return ; }; diff --git a/packages/react-core/src/demos/ComposableMenu/examples/ComposableTreeViewMenu.tsx b/packages/react-core/src/demos/ComposableMenu/examples/ComposableTreeViewMenu.tsx index 2bee235a3be..90d3a756426 100644 --- a/packages/react-core/src/demos/ComposableMenu/examples/ComposableTreeViewMenu.tsx +++ b/packages/react-core/src/demos/ComposableMenu/examples/ComposableTreeViewMenu.tsx @@ -86,14 +86,14 @@ export const ComposableTreeViewMenu: React.FunctionComponent = () => { } ]; // Helper functions for tree - const isChecked = (dataItem: TreeViewDataItem) => checkedItems.some(item => item.id === dataItem.id); + const isChecked = (dataItem: TreeViewDataItem) => checkedItems.some((item) => item.id === dataItem.id); const areAllDescendantsChecked = (dataItem: TreeViewDataItem) => - dataItem.children ? dataItem.children.every(child => areAllDescendantsChecked(child)) : isChecked(dataItem); + dataItem.children ? dataItem.children.every((child) => areAllDescendantsChecked(child)) : isChecked(dataItem); const areSomeDescendantsChecked = (dataItem: TreeViewDataItem) => - dataItem.children ? dataItem.children.some(child => areSomeDescendantsChecked(child)) : isChecked(dataItem); + dataItem.children ? dataItem.children.some((child) => areSomeDescendantsChecked(child)) : isChecked(dataItem); const flattenTree = (tree: TreeViewDataItem[]) => { let result: TreeViewDataItem[] = []; - tree.forEach(item => { + tree.forEach((item) => { result.push(item); if (item.children) { result = result.concat(flattenTree(item.children)); @@ -134,8 +134,8 @@ export const ComposableTreeViewMenu: React.FunctionComponent = () => { if (item.children) { return ( (item.children = item.children - .map(opt => Object.assign({}, opt)) - .filter(child => filterItems(child, checkedItem))).length > 0 + .map((opt) => Object.assign({}, opt)) + .filter((child) => filterItems(child, checkedItem))).length > 0 ); } }; @@ -155,12 +155,14 @@ export const ComposableTreeViewMenu: React.FunctionComponent = () => { break; } - const checkedItemTree = options.map(opt => Object.assign({}, opt)).filter(item => filterItems(item, treeViewItem)); + const checkedItemTree = options + .map((opt) => Object.assign({}, opt)) + .filter((item) => filterItems(item, treeViewItem)); const flatCheckedItems = flattenTree(checkedItemTree); - setCheckedItems(prevCheckedItems => + setCheckedItems((prevCheckedItems) => checked - ? prevCheckedItems.concat(flatCheckedItems.filter(item => !prevCheckedItems.some(i => i.id === item.id))) - : prevCheckedItems.filter(item => !flatCheckedItems.some(i => i.id === item.id)) + ? prevCheckedItems.concat(flatCheckedItems.filter((item) => !prevCheckedItems.some((i) => i.id === item.id))) + : prevCheckedItems.filter((item) => !flatCheckedItems.some((i) => i.id === item.id)) ); }; @@ -265,5 +267,5 @@ export const ComposableTreeViewMenu: React.FunctionComponent = () => { ); - return ; + return ; }; diff --git a/packages/react-core/src/demos/Filters/examples/FilterAttributeSearch.tsx b/packages/react-core/src/demos/Filters/examples/FilterAttributeSearch.tsx index 92ab52fd74a..01b2a44b133 100644 --- a/packages/react-core/src/demos/Filters/examples/FilterAttributeSearch.tsx +++ b/packages/react-core/src/demos/Filters/examples/FilterAttributeSearch.tsx @@ -101,12 +101,12 @@ export const FilterAttributeSearch: React.FunctionComponent = () => { const isRepoSelectable = (repo: Repository) => repo.name !== 'a'; // Arbitrary logic for this example const [selectedRepoNames, setSelectedRepoNames] = React.useState([]); const setRepoSelected = (repo: Repository, isSelecting = true) => - setSelectedRepoNames(prevSelected => { - const otherSelectedRepoNames = prevSelected.filter(r => r !== repo.name); + setSelectedRepoNames((prevSelected) => { + const otherSelectedRepoNames = prevSelected.filter((r) => r !== repo.name); return isSelecting && isRepoSelectable(repo) ? [...otherSelectedRepoNames, repo.name] : otherSelectedRepoNames; }); const selectAllRepos = (isSelecting = true) => - setSelectedRepoNames(isSelecting ? filteredRepos.map(r => r.name) : []); // Selecting all should only select all currently filtered rows + setSelectedRepoNames(isSelecting ? filteredRepos.map((r) => r.name) : []); // Selecting all should only select all currently filtered rows const areAllReposSelected = selectedRepoNames.length === filteredRepos.length && filteredRepos.length > 0; const areSomeReposSelected = selectedRepoNames.length > 0; const isRepoSelected = (repo: Repository) => selectedRepoNames.includes(repo.name); @@ -123,7 +123,7 @@ export const FilterAttributeSearch: React.FunctionComponent = () => { numberSelected > 0 ? Array.from(new Array(numberSelected + 1), (_x, i) => i + recentSelectedRowIndex) : Array.from(new Array(Math.abs(numberSelected) + 1), (_x, i) => i + rowIndex); - intermediateIndexes.forEach(index => setRepoSelected(repositories[index], isSelecting)); + intermediateIndexes.forEach((index) => setRepoSelected(repositories[index], isSelecting)); } else { setRepoSelected(repo, isSelecting); } @@ -253,7 +253,7 @@ export const FilterAttributeSearch: React.FunctionComponent = () => { popper={bulkSelectMenu} appendTo={bulkSelectContainerRef.current || undefined} isVisible={isBulkSelectOpen} - popperMatchesTriggerWidth={false} + minWidth="auto" /> ); @@ -408,7 +408,7 @@ export const FilterAttributeSearch: React.FunctionComponent = () => { setLocationSelections( locationSelections.includes(itemStr) - ? locationSelections.filter(selection => selection !== itemStr) + ? locationSelections.filter((selection) => selection !== itemStr) : [itemStr, ...locationSelections] ); } diff --git a/packages/react-core/src/demos/Filters/examples/FilterCheckboxSelect.tsx b/packages/react-core/src/demos/Filters/examples/FilterCheckboxSelect.tsx index be766d0aebb..d00914fe61c 100644 --- a/packages/react-core/src/demos/Filters/examples/FilterCheckboxSelect.tsx +++ b/packages/react-core/src/demos/Filters/examples/FilterCheckboxSelect.tsx @@ -59,7 +59,7 @@ export const FilterCheckboxSelect: React.FunctionComponent = () => { return true; } - return selections.some(searchValue => { + return selections.some((searchValue) => { let input: RegExp; try { input = new RegExp(searchValue, 'i'); @@ -78,12 +78,12 @@ export const FilterCheckboxSelect: React.FunctionComponent = () => { const isRepoSelectable = (repo: Repository) => repo.name !== 'a'; // Arbitrary logic for this example const [selectedRepoNames, setSelectedRepoNames] = React.useState([]); const setRepoSelected = (repo: Repository, isSelecting = true) => - setSelectedRepoNames(prevSelected => { - const otherSelectedRepoNames = prevSelected.filter(r => r !== repo.name); + setSelectedRepoNames((prevSelected) => { + const otherSelectedRepoNames = prevSelected.filter((r) => r !== repo.name); return isSelecting && isRepoSelectable(repo) ? [...otherSelectedRepoNames, repo.name] : otherSelectedRepoNames; }); const selectAllRepos = (isSelecting = true) => - setSelectedRepoNames(isSelecting ? filteredRepos.map(r => r.name) : []); + setSelectedRepoNames(isSelecting ? filteredRepos.map((r) => r.name) : []); const areAllReposSelected = selectedRepoNames.length === filteredRepos.length && filteredRepos.length > 0; const areSomeReposSelected = selectedRepoNames.length > 0; const isRepoSelected = (repo: Repository) => selectedRepoNames.includes(repo.name); @@ -100,7 +100,7 @@ export const FilterCheckboxSelect: React.FunctionComponent = () => { numberSelected > 0 ? Array.from(new Array(numberSelected + 1), (_x, i) => i + recentSelectedRowIndex) : Array.from(new Array(Math.abs(numberSelected) + 1), (_x, i) => i + rowIndex); - intermediateIndexes.forEach(index => setRepoSelected(repositories[index], isSelecting)); + intermediateIndexes.forEach((index) => setRepoSelected(repositories[index], isSelecting)); } else { setRepoSelected(repo, isSelecting); } @@ -229,7 +229,7 @@ export const FilterCheckboxSelect: React.FunctionComponent = () => { popper={bulkSelectMenu} appendTo={bulkSelectContainerRef.current || undefined} isVisible={isBulkSelectOpen} - popperMatchesTriggerWidth={false} + minWidth="auto" /> ); @@ -282,7 +282,7 @@ export const FilterCheckboxSelect: React.FunctionComponent = () => { const itemStr = itemId.toString(); setSelections( - selections.includes(itemStr) ? selections.filter(selection => selection !== itemStr) : [itemStr, ...selections] + selections.includes(itemStr) ? selections.filter((selection) => selection !== itemStr) : [itemStr, ...selections] ); } diff --git a/packages/react-core/src/demos/Filters/examples/FilterFaceted.tsx b/packages/react-core/src/demos/Filters/examples/FilterFaceted.tsx index ba9dc20b0d3..651b3696ba4 100644 --- a/packages/react-core/src/demos/Filters/examples/FilterFaceted.tsx +++ b/packages/react-core/src/demos/Filters/examples/FilterFaceted.tsx @@ -84,12 +84,12 @@ export const FilterFaceted: React.FunctionComponent = () => { const isRepoSelectable = (repo: Repository) => repo.name !== 'a'; // Arbitrary logic for this example const [selectedRepoNames, setSelectedRepoNames] = React.useState([]); const setRepoSelected = (repo: Repository, isSelecting = true) => - setSelectedRepoNames(prevSelected => { - const otherSelectedRepoNames = prevSelected.filter(r => r !== repo.name); + setSelectedRepoNames((prevSelected) => { + const otherSelectedRepoNames = prevSelected.filter((r) => r !== repo.name); return isSelecting && isRepoSelectable(repo) ? [...otherSelectedRepoNames, repo.name] : otherSelectedRepoNames; }); const selectAllRepos = (isSelecting = true) => - setSelectedRepoNames(isSelecting ? filteredRepos.map(r => r.name) : []); // Selecting all should only select all currently filtered rows + setSelectedRepoNames(isSelecting ? filteredRepos.map((r) => r.name) : []); // Selecting all should only select all currently filtered rows const areAllReposSelected = selectedRepoNames.length === filteredRepos.length && filteredRepos.length > 0; const areSomeReposSelected = selectedRepoNames.length > 0; const isRepoSelected = (repo: Repository) => selectedRepoNames.includes(repo.name); @@ -106,7 +106,7 @@ export const FilterFaceted: React.FunctionComponent = () => { numberSelected > 0 ? Array.from(new Array(numberSelected + 1), (_x, i) => i + recentSelectedRowIndex) : Array.from(new Array(Math.abs(numberSelected) + 1), (_x, i) => i + rowIndex); - intermediateIndexes.forEach(index => setRepoSelected(repositories[index], isSelecting)); + intermediateIndexes.forEach((index) => setRepoSelected(repositories[index], isSelecting)); } else { setRepoSelected(repo, isSelecting); } @@ -236,7 +236,7 @@ export const FilterFaceted: React.FunctionComponent = () => { popper={bulkSelectMenu} appendTo={bulkSelectContainerRef.current || undefined} isVisible={isBulkSelectOpen} - popperMatchesTriggerWidth={false} + minWidth="auto" /> ); @@ -293,13 +293,13 @@ export const FilterFaceted: React.FunctionComponent = () => { if (category === 'status') { setStatusSelections( statusSelections.includes(itemStr) - ? statusSelections.filter(selection => selection !== itemStr) + ? statusSelections.filter((selection) => selection !== itemStr) : [itemStr, ...statusSelections] ); } else { setLocationSelections( locationSelections.includes(itemStr) - ? locationSelections.filter(selection => selection !== itemStr) + ? locationSelections.filter((selection) => selection !== itemStr) : [itemStr, ...locationSelections] ); } @@ -307,9 +307,9 @@ export const FilterFaceted: React.FunctionComponent = () => { const onChipDelete = (category: string, chip: string) => { if (category === 'status') { - setStatusSelections(statusSelections.filter(selection => selection !== chip)); + setStatusSelections(statusSelections.filter((selection) => selection !== chip)); } else { - setLocationSelections(locationSelections.filter(selection => selection !== chip)); + setLocationSelections(locationSelections.filter((selection) => selection !== chip)); } }; diff --git a/packages/react-core/src/demos/Filters/examples/FilterMixedSelectGroup.tsx b/packages/react-core/src/demos/Filters/examples/FilterMixedSelectGroup.tsx index 77402e59ce3..107192f23ed 100644 --- a/packages/react-core/src/demos/Filters/examples/FilterMixedSelectGroup.tsx +++ b/packages/react-core/src/demos/Filters/examples/FilterMixedSelectGroup.tsx @@ -81,12 +81,12 @@ export const FilterMixedSelectGroup: React.FunctionComponent = () => { const isRepoSelectable = (repo: Repository) => repo.name !== 'a'; // Arbitrary logic for this example const [selectedRepoNames, setSelectedRepoNames] = React.useState([]); const setRepoSelected = (repo: Repository, isSelecting = true) => - setSelectedRepoNames(prevSelected => { - const otherSelectedRepoNames = prevSelected.filter(r => r !== repo.name); + setSelectedRepoNames((prevSelected) => { + const otherSelectedRepoNames = prevSelected.filter((r) => r !== repo.name); return isSelecting && isRepoSelectable(repo) ? [...otherSelectedRepoNames, repo.name] : otherSelectedRepoNames; }); const selectAllRepos = (isSelecting = true) => - setSelectedRepoNames(isSelecting ? filteredRepos.map(r => r.name) : []); // Selecting all should only select all currently filtered rows + setSelectedRepoNames(isSelecting ? filteredRepos.map((r) => r.name) : []); // Selecting all should only select all currently filtered rows const areAllReposSelected = selectedRepoNames.length === filteredRepos.length && filteredRepos.length > 0; const areSomeReposSelected = selectedRepoNames.length > 0; const isRepoSelected = (repo: Repository) => selectedRepoNames.includes(repo.name); @@ -103,7 +103,7 @@ export const FilterMixedSelectGroup: React.FunctionComponent = () => { numberSelected > 0 ? Array.from(new Array(numberSelected + 1), (_x, i) => i + recentSelectedRowIndex) : Array.from(new Array(Math.abs(numberSelected) + 1), (_x, i) => i + rowIndex); - intermediateIndexes.forEach(index => setRepoSelected(repositories[index], isSelecting)); + intermediateIndexes.forEach((index) => setRepoSelected(repositories[index], isSelecting)); } else { setRepoSelected(repo, isSelecting); } @@ -233,7 +233,7 @@ export const FilterMixedSelectGroup: React.FunctionComponent = () => { popper={bulkSelectMenu} appendTo={bulkSelectContainerRef.current || undefined} isVisible={isBulkSelectOpen} - popperMatchesTriggerWidth={false} + minWidth="auto" /> ); @@ -379,7 +379,7 @@ export const FilterMixedSelectGroup: React.FunctionComponent = () => { setLocationSelections( locationSelections.includes(itemStr) - ? locationSelections.filter(selection => selection !== itemStr) + ? locationSelections.filter((selection) => selection !== itemStr) : [itemStr, ...locationSelections] ); } diff --git a/packages/react-core/src/demos/Filters/examples/FilterSameSelectGroup.tsx b/packages/react-core/src/demos/Filters/examples/FilterSameSelectGroup.tsx index 99b92a829ed..816fdb0395f 100644 --- a/packages/react-core/src/demos/Filters/examples/FilterSameSelectGroup.tsx +++ b/packages/react-core/src/demos/Filters/examples/FilterSameSelectGroup.tsx @@ -82,12 +82,12 @@ export const FilterSameSelectGroup: React.FunctionComponent = () => { const isRepoSelectable = (repo: Repository) => repo.name !== 'a'; // Arbitrary logic for this example const [selectedRepoNames, setSelectedRepoNames] = React.useState([]); const setRepoSelected = (repo: Repository, isSelecting = true) => - setSelectedRepoNames(prevSelected => { - const otherSelectedRepoNames = prevSelected.filter(r => r !== repo.name); + setSelectedRepoNames((prevSelected) => { + const otherSelectedRepoNames = prevSelected.filter((r) => r !== repo.name); return isSelecting && isRepoSelectable(repo) ? [...otherSelectedRepoNames, repo.name] : otherSelectedRepoNames; }); const selectAllRepos = (isSelecting = true) => - setSelectedRepoNames(isSelecting ? filteredRepos.map(r => r.name) : []); // Selecting all should only select all currently filtered rows + setSelectedRepoNames(isSelecting ? filteredRepos.map((r) => r.name) : []); // Selecting all should only select all currently filtered rows const areAllReposSelected = selectedRepoNames.length === filteredRepos.length && filteredRepos.length > 0; const areSomeReposSelected = selectedRepoNames.length > 0; const isRepoSelected = (repo: Repository) => selectedRepoNames.includes(repo.name); @@ -104,7 +104,7 @@ export const FilterSameSelectGroup: React.FunctionComponent = () => { numberSelected > 0 ? Array.from(new Array(numberSelected + 1), (_x, i) => i + recentSelectedRowIndex) : Array.from(new Array(Math.abs(numberSelected) + 1), (_x, i) => i + rowIndex); - intermediateIndexes.forEach(index => setRepoSelected(repositories[index], isSelecting)); + intermediateIndexes.forEach((index) => setRepoSelected(repositories[index], isSelecting)); } else { setRepoSelected(repo, isSelecting); } @@ -234,7 +234,7 @@ export const FilterSameSelectGroup: React.FunctionComponent = () => { popper={bulkSelectMenu} appendTo={bulkSelectContainerRef.current || undefined} isVisible={isBulkSelectOpen} - popperMatchesTriggerWidth={false} + minWidth="auto" /> ); diff --git a/packages/react-core/src/demos/Filters/examples/FilterSearchInput.tsx b/packages/react-core/src/demos/Filters/examples/FilterSearchInput.tsx index 71a47672489..eac8e96576b 100644 --- a/packages/react-core/src/demos/Filters/examples/FilterSearchInput.tsx +++ b/packages/react-core/src/demos/Filters/examples/FilterSearchInput.tsx @@ -85,12 +85,12 @@ export const FilterSearchInput: React.FunctionComponent = () => { const isRepoSelectable = (repo: Repository) => repo.name !== 'a'; // Arbitrary logic for this example const [selectedRepoNames, setSelectedRepoNames] = React.useState([]); const setRepoSelected = (repo: Repository, isSelecting = true) => - setSelectedRepoNames(prevSelected => { - const otherSelectedRepoNames = prevSelected.filter(r => r !== repo.name); + setSelectedRepoNames((prevSelected) => { + const otherSelectedRepoNames = prevSelected.filter((r) => r !== repo.name); return isSelecting && isRepoSelectable(repo) ? [...otherSelectedRepoNames, repo.name] : otherSelectedRepoNames; }); const selectAllRepos = (isSelecting = true) => - setSelectedRepoNames(isSelecting ? filteredRepos.map(r => r.name) : []); // Selecting all should only select all currently filtered rows + setSelectedRepoNames(isSelecting ? filteredRepos.map((r) => r.name) : []); // Selecting all should only select all currently filtered rows const areAllReposSelected = selectedRepoNames.length === filteredRepos.length && filteredRepos.length > 0; const areSomeReposSelected = selectedRepoNames.length > 0; const isRepoSelected = (repo: Repository) => selectedRepoNames.includes(repo.name); @@ -107,7 +107,7 @@ export const FilterSearchInput: React.FunctionComponent = () => { numberSelected > 0 ? Array.from(new Array(numberSelected + 1), (_x, i) => i + recentSelectedRowIndex) : Array.from(new Array(Math.abs(numberSelected) + 1), (_x, i) => i + rowIndex); - intermediateIndexes.forEach(index => setRepoSelected(repositories[index], isSelecting)); + intermediateIndexes.forEach((index) => setRepoSelected(repositories[index], isSelecting)); } else { setRepoSelected(repo, isSelecting); } @@ -237,7 +237,7 @@ export const FilterSearchInput: React.FunctionComponent = () => { popper={bulkSelectMenu} appendTo={bulkSelectContainerRef.current || undefined} isVisible={isBulkSelectOpen} - popperMatchesTriggerWidth={false} + minWidth="auto" /> ); diff --git a/packages/react-core/src/demos/Filters/examples/FilterSingleSelect.tsx b/packages/react-core/src/demos/Filters/examples/FilterSingleSelect.tsx index 460349696bb..96be01ec6c8 100644 --- a/packages/react-core/src/demos/Filters/examples/FilterSingleSelect.tsx +++ b/packages/react-core/src/demos/Filters/examples/FilterSingleSelect.tsx @@ -73,12 +73,12 @@ export const FilterSingleSelect: React.FunctionComponent = () => { const isRepoSelectable = (repo: Repository) => repo.name !== 'a'; // Arbitrary logic for this example const [selectedRepoNames, setSelectedRepoNames] = React.useState([]); const setRepoSelected = (repo: Repository, isSelecting = true) => - setSelectedRepoNames(prevSelected => { - const otherSelectedRepoNames = prevSelected.filter(r => r !== repo.name); + setSelectedRepoNames((prevSelected) => { + const otherSelectedRepoNames = prevSelected.filter((r) => r !== repo.name); return isSelecting && isRepoSelectable(repo) ? [...otherSelectedRepoNames, repo.name] : otherSelectedRepoNames; }); const selectAllRepos = (isSelecting = true) => - setSelectedRepoNames(isSelecting ? filteredRepos.map(r => r.name) : []); + setSelectedRepoNames(isSelecting ? filteredRepos.map((r) => r.name) : []); const areAllReposSelected = selectedRepoNames.length === filteredRepos.length && filteredRepos.length > 0; const areSomeReposSelected = selectedRepoNames.length > 0; const isRepoSelected = (repo: Repository) => selectedRepoNames.includes(repo.name); @@ -95,7 +95,7 @@ export const FilterSingleSelect: React.FunctionComponent = () => { numberSelected > 0 ? Array.from(new Array(numberSelected + 1), (_x, i) => i + recentSelectedRowIndex) : Array.from(new Array(Math.abs(numberSelected) + 1), (_x, i) => i + rowIndex); - intermediateIndexes.forEach(index => setRepoSelected(repositories[index], isSelecting)); + intermediateIndexes.forEach((index) => setRepoSelected(repositories[index], isSelecting)); } else { setRepoSelected(repo, isSelecting); } @@ -224,7 +224,7 @@ export const FilterSingleSelect: React.FunctionComponent = () => { popper={bulkSelectMenu} appendTo={bulkSelectContainerRef.current || undefined} isVisible={isBulkSelectOpen} - popperMatchesTriggerWidth={false} + minWidth="auto" /> ); diff --git a/packages/react-core/src/helpers/Popper/Popper.tsx b/packages/react-core/src/helpers/Popper/Popper.tsx index 5b33fa0faee..a0f4c65a17d 100644 --- a/packages/react-core/src/helpers/Popper/Popper.tsx +++ b/packages/react-core/src/helpers/Popper/Popper.tsx @@ -57,14 +57,18 @@ export interface PopperProps { reference?: HTMLElement | (() => HTMLElement) | React.RefObject; /** The popper (menu/tooltip/popover) element */ popper: React.ReactElement; - /** True to set the width of the popper element to the trigger element's width */ - popperMatchesTriggerWidth?: boolean; /** popper direction */ direction?: 'up' | 'down'; /** popper position */ position?: 'right' | 'left' | 'center'; /** Instead of direction and position can set the placement of the popper */ placement?: Placement; + /** Custsom width of the popper. If the value is "trigger", it will set the width to the trigger element's width */ + width?: string | 'trigger'; + /** Minimum width of the popper. If the value is "trigger", it will set the min width to the trigger element's width */ + minWidth?: string | 'trigger'; + /** Maximum width of the popper. If the value is "trigger", it will set the max width to the trigger element's width */ + maxWidth?: string | 'trigger'; /** The container to append the popper to. Defaults to 'inline'. */ appendTo?: HTMLElement | (() => HTMLElement) | 'inline'; /** z-index of the popper element */ @@ -144,10 +148,12 @@ export interface PopperProps { export const Popper: React.FunctionComponent = ({ trigger, popper, - popperMatchesTriggerWidth = true, direction = 'down', position = 'left', placement, + width, + minWidth = 'trigger', + maxWidth, appendTo = 'inline', zIndex = 9999, isVisible = true, @@ -272,29 +278,57 @@ export const Popper: React.FunctionComponent = ({ return convertedPlacement as Placement; }; const getPlacementMemo = React.useMemo(getPlacement, [direction, position, placement]); - const getOppositePlacementMemo = React.useMemo(() => getOppositePlacement(getPlacement()), [ - direction, - position, - placement - ]); - const sameWidthMod: Modifier<'sameWidth', {}> = React.useMemo( + const getOppositePlacementMemo = React.useMemo( + () => getOppositePlacement(getPlacement()), + [direction, position, placement] + ); + + const widthMods: Modifier<'widthMods', {}> = React.useMemo( () => ({ - name: 'sameWidth', - enabled: popperMatchesTriggerWidth, + name: 'widthMods', + enabled: width !== undefined || minWidth !== undefined || maxWidth !== undefined, phase: 'beforeWrite', requires: ['computeStyles'], fn: ({ state }) => { - state.styles.popper.width = `${state.rects.reference.width}px`; + if (width) { + state.styles.popper.width = width === 'trigger' ? `${state.rects.reference.width}px` : width; + } + + if (minWidth) { + state.styles.popper.minWidth = minWidth === 'trigger' ? `${state.rects.reference.width}px` : minWidth; + } + + if (maxWidth) { + state.styles.popper.maxWidth = maxWidth === 'trigger' ? `${state.rects.reference.width}px` : maxWidth; + } }, effect: ({ state }) => { - state.elements.popper.style.width = `${(state.elements.reference as HTMLElement).offsetWidth}px`; + if (width) { + state.elements.popper.style.width = + width === 'trigger' ? `${(state.elements.reference as HTMLElement).offsetWidth}px` : width; + } + + if (minWidth) { + state.elements.popper.style.minWidth = + minWidth === 'trigger' ? `${(state.elements.reference as HTMLElement).offsetWidth}px` : minWidth; + } + + if (maxWidth) { + state.elements.popper.style.maxWidth = + maxWidth === 'trigger' ? `${(state.elements.reference as HTMLElement).offsetWidth}px` : maxWidth; + } return () => {}; } }), - [popperMatchesTriggerWidth] + [width, minWidth, maxWidth] ); - const { styles: popperStyles, attributes, update, forceUpdate } = usePopper(refOrTrigger, popperElement, { + const { + styles: popperStyles, + attributes, + update, + forceUpdate + } = usePopper(refOrTrigger, popperElement, { placement: getPlacementMemo, modifiers: [ { @@ -319,7 +353,7 @@ export const Popper: React.FunctionComponent = ({ fallbackPlacements: flipBehavior === 'flip' ? [getOppositePlacementMemo] : flipBehavior } }, - sameWidthMod + widthMods ] }); @@ -352,7 +386,7 @@ export const Popper: React.FunctionComponent = ({ return popperRef ? ( localPopper ) : ( -
setPopperElement(node?.firstElementChild as HTMLElement)}> +
setPopperElement(node?.firstElementChild as HTMLElement)}> {localPopper}
); @@ -370,7 +404,7 @@ export const Popper: React.FunctionComponent = ({ return ( <> {!reference && trigger && React.isValidElement(trigger) && ( -
setTriggerElement(node?.firstElementChild as HTMLElement)}> +
setTriggerElement(node?.firstElementChild as HTMLElement)}> {trigger}
)} diff --git a/packages/react-core/src/next/components/Select/Select.tsx b/packages/react-core/src/next/components/Select/Select.tsx index a2886771273..626e0ab555b 100644 --- a/packages/react-core/src/next/components/Select/Select.tsx +++ b/packages/react-core/src/next/components/Select/Select.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { css } from '@patternfly/react-styles'; import { Menu, MenuContent, MenuProps } from '../../../components/Menu'; -import { Popper } from '../../../helpers/Popper/Popper'; +import { Popper, PopperProps } from '../../../helpers/Popper/Popper'; import { getOUIAProps, OUIAProps, getDefaultOUIAId } from '../../../helpers'; export interface SelectProps extends MenuProps, OUIAProps { @@ -30,6 +30,8 @@ export interface SelectProps extends MenuProps, OUIAProps { zIndex?: number; /** @beta Determines the accessible role of the select. For a checkbox select pass in "menu". */ role?: string; + /** Additional properties to pass to the Popper */ + popperProps?: PopperProps; } const SelectBase: React.FunctionComponent = ({ @@ -45,6 +47,7 @@ const SelectBase: React.FunctionComponent = ({ innerRef, zIndex = 9999, role = 'listbox', + popperProps, ...props }: SelectProps & OUIAProps) => { const localMenuRef = React.useRef(); @@ -123,6 +126,7 @@ const SelectBase: React.FunctionComponent = ({ appendTo={containerRef.current || undefined} isVisible={isOpen} zIndex={zIndex} + {...popperProps} />
); diff --git a/packages/react-table/src/components/Table/ActionsColumn.tsx b/packages/react-table/src/components/Table/ActionsColumn.tsx index b8a2bdfab04..23418662fe1 100644 --- a/packages/react-table/src/components/Table/ActionsColumn.tsx +++ b/packages/react-table/src/components/Table/ActionsColumn.tsx @@ -38,7 +38,7 @@ const ActionsColumnBase: React.FunctionComponent = ({ popperProps = { position: 'right', direction: 'down', - popperMatchesTriggerWidth: false + minWidth: 'auto' }, ...props }: ActionsColumnProps) => { @@ -65,12 +65,12 @@ const ActionsColumnBase: React.FunctionComponent = ({ return ( {items - .filter(item => item.isOutsideDropdown) + .filter((item) => item.isOutsideDropdown) // eslint-disable-next-line @typescript-eslint/no-unused-vars .map(({ title, itemKey, onClick, isOutsideDropdown, ...props }, key) => typeof title === 'string' ? (