Skip to content

Commit

Permalink
fix: always inline toolbar for listbox popover
Browse files Browse the repository at this point in the history
  • Loading branch information
PurwaShrivastava committed Apr 3, 2023
1 parent 3442169 commit 5620640
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 24 deletions.
36 changes: 21 additions & 15 deletions apis/nucleus/src/components/listbox/ListBoxInline.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ const StyledGrid = styled(Grid, { shouldForwardProp: (p) => !['containerPadding'
})
);

const Title = styled(Typography)(({ theme }) => ({
const Title = styled(Typography)(({ theme, isPopover }) => ({
color: theme.listBox?.title?.main?.color,
fontSize: theme.listBox?.title?.main?.fontSize,
fontFamily: theme.listBox?.title?.main?.fontFamily,
fontWeight: theme.listBox?.title?.main?.fontWeight || 'bold',
textOverflow: isPopover ? 'ellipsis' : undefined,
overflow: isPopover ? 'hidden' : undefined,
}));

function ListBoxInline({ options, layout }) {
Expand All @@ -82,7 +84,7 @@ function ListBoxInline({ options, layout }) {
scrollState = undefined,
renderedCallback,
toolbar = true,
isCollapsed = false,
isPopover = false,
} = options;

// Hook that will trigger update when used in useEffects.
Expand Down Expand Up @@ -142,7 +144,7 @@ function ListBoxInline({ options, layout }) {
active: keyboardActive,
};

const showDetachedToolbarOnly = toolbar && (layout?.title === '' || layout?.showTitle === false);
const showDetachedToolbarOnly = toolbar && (layout?.title === '' || layout?.showTitle === false) && !isPopover;
const showToolbarWithTitle = toolbar && layout?.title !== '' && layout?.showTitle !== false;

useEffect(() => {
Expand All @@ -155,13 +157,13 @@ function ListBoxInline({ options, layout }) {
setShowSearch(false);
}
};
if (isCollapsed) {
if (isPopover) {
if (!selections.isActive()) {
selections.begin('/qListObjectDef');
selections.on('activated', show);
selections.on('deactivated', hide);
}
setShowToolbar(isCollapsed);
setShowToolbar(isPopover);
}
if (selections) {
if (!selections.isModal()) {
Expand All @@ -177,7 +179,7 @@ function ListBoxInline({ options, layout }) {
selections.removeListener('deactivated', hide);
}
};
}, [selections, isCollapsed]);
}, [selections, isPopover]);

useEffect(() => {
if (!searchContainer || !searchContainer.current) {
Expand Down Expand Up @@ -229,9 +231,9 @@ function ListBoxInline({ options, layout }) {
}
};

const getActionToolbarProps = (isPopover) =>
const getActionToolbarProps = (isDetached) =>
getListboxActionProps({
isPopover,
isDetached: isPopover ? false : isDetached,
showToolbar,
containerRef,
isLocked,
Expand All @@ -246,6 +248,7 @@ function ListBoxInline({ options, layout }) {
const iconsWidth = (showSearchOrLockIcon ? BUTTON_ICON_WIDTH : 0) + (isDrillDown ? ICON_WIDTH + ICON_PADDING : 0); // Drill-down icon needs padding right so there is space between the icon and the title
const headerPaddingLeft = CELL_PADDING_LEFT - (showSearchOrLockIcon ? ICON_PADDING : 0);
const headerPaddingRight = isRtl ? CELL_PADDING_LEFT - (showIcons ? ICON_PADDING : 0) : 0;
const { isDetached, reasonDetached } = showToolbarDetached({ containerRef, titleRef, iconsWidth });

// Add a container padding for grid mode to harmonize with the grid item margins (should sum to 8px).
const isGridMode = layoutOptions?.dataLayout === 'grid';
Expand Down Expand Up @@ -294,7 +297,7 @@ function ListBoxInline({ options, layout }) {
ref={containerRef}
hasIcon={showIcons}
>
{showToolbarWithTitle && (
{(showToolbarWithTitle || isPopover) && (
<Grid
item
container
Expand Down Expand Up @@ -328,18 +331,21 @@ function ListBoxInline({ options, layout }) {
)}
<Grid item sx={{ justifyContent: isRtl ? 'flex-end' : 'flex-start' }} className={classes.listBoxHeader}>
{showTitle && (
<Title variant="h6" noWrap ref={titleRef} title={layout.title}>
{layout.title}
<Title
variant="h6"
sx={{ width: isPopover && reasonDetached === 'noSpace' ? '60px' : undefined }}
noWrap
ref={titleRef}
title={layout.title}
>
{showToolbarWithTitle ? layout.title : ''}
</Title>
)}
</Grid>
</Grid>
<Grid item xs />
<Grid item>
<ActionsToolbar
direction={direction}
{...getActionToolbarProps(showToolbarDetached({ containerRef, titleRef, iconsWidth }))}
/>
<ActionsToolbar direction={direction} {...getActionToolbarProps(isDetached)} />
</Grid>
</Grid>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ describe('<ListboxInline />', () => {
selections,
update: undefined,
fetchStart: 'fetchStart',
isCollapsed: false,
isPopover: false,
};

useRef.mockReturnValue({ current: 'current' });
Expand Down Expand Up @@ -263,7 +263,7 @@ describe('<ListboxInline />', () => {

test('should show toolbar when opened in a popover', async () => {
options.search = false;
options.isCollapsed = true;
options.isPopover = true;
await render();
const actionToolbars = renderer.root.findAllByType(ActionsToolbar);
expect(actionToolbars).toHaveLength(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,27 @@ describe('show listbox toolbar detached', () => {
it('should return true if there is not enough space for toolbar', () => {
const containerRef = { current: { clientWidth: 100 } };
const titleRef = { current: { clientWidth: 60, scrollWidth: 80, offsetWidth: 81 } };
expect(showToolbarDetached({ containerRef, titleRef, iconsWidth })).toBe(true);
expect(showToolbarDetached({ containerRef, titleRef, iconsWidth })).toStrictEqual({
isDetached: true,
reasonDetached: 'noSpace',
});
});

it('should return true if title is truncated', () => {
const containerRef = { current: { clientWidth: 300 } };
const titleRef = { current: { clientWidth: 60, scrollWidth: 200, offsetWidth: 199 } };
expect(showToolbarDetached({ containerRef, titleRef, iconsWidth })).toBe(true);
expect(showToolbarDetached({ containerRef, titleRef, iconsWidth })).toStrictEqual({
isDetached: true,
reasonDetached: 'truncated',
});
});

it('should return false if there is enough space for title and toolbar', () => {
const containerRef = { current: { clientWidth: 300 } };
const titleRef = { current: { clientWidth: 60, scrollWidth: 200, offsetWidth: 201 } };
expect(showToolbarDetached({ containerRef, titleRef, iconsWidth })).toBe(false);
expect(showToolbarDetached({ containerRef, titleRef, iconsWidth })).toStrictEqual({
isDetached: false,
reasonDetached: '',
});
});
});
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
export default function getListboxActionProps({
isPopover,
isDetached,
showToolbar,
containerRef,
isLocked,
listboxSelectionToolbarItems,
selections,
}) {
return {
show: showToolbar && !isPopover,
show: showToolbar && !isDetached,
popover: {
show: showToolbar && isPopover,
show: showToolbar && isDetached,
anchorEl: containerRef.current,
},
more: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/* eslint-disable no-nested-ternary */
export default function showToolbarDetached({ containerRef, titleRef, iconsWidth }) {
const containerWidth = containerRef?.current?.clientWidth ?? 0;
const padding = 16;
const contentWidth = (titleRef?.current?.clientWidth ?? 0) + iconsWidth + padding;
const actionToolbarWidth = 128;
const notSufficientSpace = containerWidth < contentWidth + actionToolbarWidth;
const isTruncated = titleRef?.current?.scrollWidth > titleRef?.current?.offsetWidth;
const isDetached = !!(notSufficientSpace | isTruncated);
const reasonDetached = isDetached ? (notSufficientSpace ? 'noSpace' : 'truncated') : '';

return !!(notSufficientSpace | isTruncated);
return { isDetached, reasonDetached };
}

0 comments on commit 5620640

Please sign in to comment.