Skip to content

Commit

Permalink
Merge pull request #421 from qoretechnologies/bugfix/collection-insid…
Browse files Browse the repository at this point in the history
…e-panel-action-prop-infinite-loop

Remove tooltip from <Panel /> component and improve performance
  • Loading branch information
Foxhoundn authored Dec 11, 2024
2 parents 3042918 + 0da1c79 commit 61350bd
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 104 deletions.
19 changes: 0 additions & 19 deletions __tests__/panel.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { fireEvent, render, screen } from '@testing-library/react';
import React from 'react';
import { ReqoreInput, ReqoreLayoutContent, ReqorePanel, ReqoreUIProvider } from '../src';

test('Renders basic <Panel /> properly', () => {
Expand Down Expand Up @@ -203,24 +202,6 @@ test('Renders <Panel /> without title & bottom actions if all actions are not sh
expect(document.querySelectorAll('.reqore-panel-bottom-actions').length).toBe(0);
});

test('Tooltip on <Panel /> works', () => {
jest.useFakeTimers();

render(
<ReqoreUIProvider>
<ReqorePanel tooltip='Hello'>Hello</ReqorePanel>
</ReqoreUIProvider>
);

expect(document.querySelectorAll('.reqore-popover-content').length).toBe(0);

fireEvent.mouseEnter(document.querySelectorAll('.reqore-panel')[0]);

jest.advanceTimersByTime(1);

expect(document.querySelectorAll('.reqore-popover-content').length).toBe(1);
});

test('Custom control props on <Panel />', () => {
jest.useFakeTimers();
const onClose = jest.fn();
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@qoretechnologies/reqore",
"version": "0.48.19",
"version": "0.48.20",
"description": "ReQore is a highly theme-able and modular UI library for React",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
31 changes: 21 additions & 10 deletions src/components/Drawer/backdrop.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { animated } from '@react-spring/web';
import { rgba } from 'polished';
import { memo, useMemo } from 'react';
import { memo, useCallback, useMemo } from 'react';
import styled from 'styled-components';
import { IReqoreDrawerStyle } from '.';
import { useReqoreProperty } from '../..';
Expand Down Expand Up @@ -32,22 +32,33 @@ export const ReqoreBackdrop = memo(
const getAndIncreaseZIndex = useReqoreProperty('getAndIncreaseZIndex');
const finalZIndex = useMemo(() => zIndex || getAndIncreaseZIndex(), [zIndex]);

const handleClick = useCallback(
(event) => {
event.stopPropagation();
// Only close if the click is on the backdrop itself
if (event.target === event.currentTarget) {
onClose?.();
}
},
[onClose]
);

const style = useMemo(
() => ({
opacity,
}),
[opacity]
);

return (
<StyledBackdrop
{...rest}
className={`${rest.className || ''} reqore-drawer-backdrop`}
onClick={(event) => {
// Only close if the click is on the backdrop itself
if (event.target === event.currentTarget) {
onClose?.();
}
}}
onClick={handleClick}
closable={!!onClose}
zIndex={finalZIndex}
blur={blur}
style={{
opacity,
}}
style={style}
/>
);
}
Expand Down
165 changes: 101 additions & 64 deletions src/components/Drawer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { animated, useTransition } from '@react-spring/web';
import { Resizable } from 're-resizable';
import { memo, useEffect, useMemo, useState } from 'react';
import { memo, useCallback, useEffect, useMemo, useState } from 'react';
import { createPortal } from 'react-dom';
import styled, { css } from 'styled-components';
import { useReqoreProperty } from '../..';
Expand Down Expand Up @@ -247,6 +247,96 @@ export const ReqoreDrawer: React.FC<IReqoreDrawerProps> = memo(
};
}, [_isModal, position, layout, floating]);

const closeButtonProps = useMemo(
() => ({
className: 'reqore-drawer-close-button',
...(rest.closeButtonProps || {}),
}),
[rest.closeButtonProps]
);

const panelStyle = useMemo(
() => ({
width: '100%',
maxHeight: '100%',
...rest.style,
}),
[JSON.stringify(rest.style)]
);

const resizeableStyle = useMemo(
() =>
({
zIndex: wrapperZIndex,
display: 'flex',
position: 'fixed',
overflow: hidable ? undefined : 'hidden',
transformOrigin: 'center center',
backfaceVisibility: 'hidden',
...positions,
} as any),
[wrapperZIndex, hidable, positions]
);

const handleWrapperStyle = useMemo(
() => ({
zIndex: wrapperZIndex + 1,
}),
[wrapperZIndex]
);

const sizeObject = useMemo(
() => ({
width: _isModal
? _size.width
: layout === 'vertical'
? _isHidden
? 0
: _size.width
: 'auto',
height: _isModal
? _size.height
: layout === 'horizontal'
? _isHidden
? 0
: _size.height
: 'auto',
}),
[_isModal, layout, _isHidden, _size]
);

const onHideToggleClick = useCallback(() => {
setIsHidden(!_isHidden);
onHideToggle?.(!_isHidden);
}, [_isHidden, onHideToggle]);

const handleResize = useCallback(
(_, _direction, component: HTMLElement) => {
if (resizable) {
setSize({
width: component.style.width,
height: component.style.height,
});
}
},

[resizable]
);

const enable = useMemo(
() => ({
top: (resizable && position === 'bottom') || _isModal ? true : false,
right: (resizable && position === 'left') || _isModal ? true : false,
left: (resizable && position === 'right') || _isModal ? true : false,
bottom: (resizable && position === 'top') || _isModal ? true : false,
bottomLeft: _isModal,
bottomRight: _isModal,
topLeft: _isModal,
topRight: _isModal,
}),
[resizable, position, _isModal]
);

return createPortal(
transitions((styles: any, item) =>
item ? (
Expand Down Expand Up @@ -287,57 +377,14 @@ export const ReqoreDrawer: React.FC<IReqoreDrawerProps> = memo(
: undefined
}
as={StyledDrawerResizable}
style={
{
zIndex: wrapperZIndex,
display: 'flex',
position: 'fixed',
overflow: hidable ? undefined : 'hidden',
transformOrigin: 'center center',
backfaceVisibility: 'hidden',
...positions,
...styles,
} as any
}
handleWrapperStyle={{
zIndex: wrapperZIndex + 1,
}}
size={{
width: _isModal
? _size.width
: layout === 'vertical'
? _isHidden
? 0
: _size.width
: 'auto',
height: _isModal
? _size.height
: layout === 'horizontal'
? _isHidden
? 0
: _size.height
: 'auto',
}}
onResize={
resizable
? (_, _direction, component: HTMLElement) => {
setSize({
width: component.style.width,
height: component.style.height,
});
}
: undefined
}
enable={{
top: (resizable && position === 'bottom') || _isModal ? true : false,
right: (resizable && position === 'left') || _isModal ? true : false,
left: (resizable && position === 'right') || _isModal ? true : false,
bottom: (resizable && position === 'top') || _isModal ? true : false,
bottomLeft: _isModal,
bottomRight: _isModal,
topLeft: _isModal,
topRight: _isModal,
style={{
...resizeableStyle,
...styles,
}}
handleWrapperStyle={handleWrapperStyle}
size={sizeObject}
onResize={handleResize}
enable={enable}
>
{_isHidden && hidable ? (
<StyledCloseWrapper
Expand All @@ -351,10 +398,7 @@ export const ReqoreDrawer: React.FC<IReqoreDrawerProps> = memo(
customTheme={theme}
className='reqore-drawer-control reqore-drawer-hide-button'
icon={getHideShowIcon(position, _isHidden)}
onClick={() => {
setIsHidden(!_isHidden);
onHideToggle?.(!_isHidden);
}}
onClick={onHideToggleClick}
/>
</StyledCloseWrapper>
) : null}
Expand All @@ -370,16 +414,9 @@ export const ReqoreDrawer: React.FC<IReqoreDrawerProps> = memo(
rounded={floating || _isModal ? true : false}
flat={flat}
onClose={onClose}
closeButtonProps={{
className: 'reqore-drawer-close-button',
...(rest.closeButtonProps || {}),
}}
closeButtonProps={closeButtonProps}
className={`reqore-drawer`}
style={{
width: '100%',
maxHeight: '100%',
...rest.style,
}}
style={panelStyle}
>
{children}
</ReqorePanel>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { HEADER_SIZE_TO_NUMBER, TSizes } from '../../constants/sizes';
import { IReqoreTheme, TReqoreIntent } from '../../constants/theme';
import { isStringSize } from '../../helpers/utils';
import { useReqoreTheme } from '../../hooks/useTheme';
import { useTooltip } from '../../hooks/useTooltip';
import { IWithReqoreEffect, IWithReqoreTooltip } from '../../types/global';
import { StyledTextEffect } from '../Effect';
import { useTooltip } from '../../hooks/useTooltip';

export interface IReqoreHeadingProps
extends IWithReqoreEffect,
Expand Down
17 changes: 8 additions & 9 deletions src/components/Panel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import { getOneHigherSize, isActionShown } from '../../helpers/utils';
import { useCombinedRefs } from '../../hooks/useCombinedRefs';
import { useReqoreProperty } from '../../hooks/useReqoreContext';
import { useReqoreTheme } from '../../hooks/useTheme';
import { useTooltip } from '../../hooks/useTooltip';
import { ACTIVE_ICON_SCALE, DisabledElement, INACTIVE_ICON_SCALE } from '../../styles';
import {
IReqoreIntent,
Expand Down Expand Up @@ -371,7 +370,6 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
headerSize,
contentSize,
minimal,
tooltip,
badge,
iconColor,
iconProps = {},
Expand Down Expand Up @@ -405,11 +403,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(

const isMobile = useReqoreProperty('isMobile');
const { targetRef } = useCombinedRefs(ref);
const [itemRef, setItemRef] = useState<HTMLDivElement>(undefined);
const [measureRef, { width }] = useMeasure();

useTooltip(itemRef, tooltip);

useUpdateEffect(() => {
setIsCollapsed(!!isCollapsed);
}, [isCollapsed]);
Expand Down Expand Up @@ -680,6 +675,13 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
return show;
}, [isSmall, collapsible, actions, hasNonResponsiveActions]);

const iconTooltip = useMemo(
() => ({
content: label,
}),
[label]
);

return (
<StyledPanel
{...omit(rest, ['onResize'])}
Expand All @@ -693,7 +695,6 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
}

targetRef.current = _ref;
setItemRef(_ref);
}}
isCollapsed={_isCollapsed}
rounded={rounded}
Expand Down Expand Up @@ -752,9 +753,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
image={loading ? undefined : iconImage}
margin='right'
color={iconColor}
tooltip={{
content: label,
}}
tooltip={iconTooltip}
effect={{
opacity: CONTROL_ICON_OPACITY,
}}
Expand Down

0 comments on commit 61350bd

Please sign in to comment.