From daa2ce3a374c2546f2b8197829665331a9034418 Mon Sep 17 00:00:00 2001 From: Foxhoundn Date: Wed, 11 Dec 2024 17:33:18 +0100 Subject: [PATCH 1/2] Performance fixes #2 --- package.json | 2 +- src/components/Drawer/backdrop.tsx | 31 ++++-- src/components/Drawer/index.tsx | 165 ++++++++++++++++++----------- src/components/Header/index.tsx | 2 +- src/components/Panel/index.tsx | 14 +-- 5 files changed, 132 insertions(+), 82 deletions(-) diff --git a/package.json b/package.json index 961abaf8..1e105807 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/components/Drawer/backdrop.tsx b/src/components/Drawer/backdrop.tsx index 196ce627..05c7e149 100644 --- a/src/components/Drawer/backdrop.tsx +++ b/src/components/Drawer/backdrop.tsx @@ -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 '../..'; @@ -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 ( { - // 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} /> ); } diff --git a/src/components/Drawer/index.tsx b/src/components/Drawer/index.tsx index e2007069..b713ce7f 100644 --- a/src/components/Drawer/index.tsx +++ b/src/components/Drawer/index.tsx @@ -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 '../..'; @@ -247,6 +247,96 @@ export const ReqoreDrawer: React.FC = 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 ? ( @@ -287,57 +377,14 @@ export const ReqoreDrawer: React.FC = 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 ? ( = memo( customTheme={theme} className='reqore-drawer-control reqore-drawer-hide-button' icon={getHideShowIcon(position, _isHidden)} - onClick={() => { - setIsHidden(!_isHidden); - onHideToggle?.(!_isHidden); - }} + onClick={onHideToggleClick} /> ) : null} @@ -370,16 +414,9 @@ export const ReqoreDrawer: React.FC = 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} diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 6601d394..33aa1a40 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -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, diff --git a/src/components/Panel/index.tsx b/src/components/Panel/index.tsx index acb84035..cf27e65f 100644 --- a/src/components/Panel/index.tsx +++ b/src/components/Panel/index.tsx @@ -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, @@ -408,8 +407,6 @@ export const ReqorePanel = forwardRef( const [itemRef, setItemRef] = useState(undefined); const [measureRef, { width }] = useMeasure(); - useTooltip(itemRef, tooltip); - useUpdateEffect(() => { setIsCollapsed(!!isCollapsed); }, [isCollapsed]); @@ -680,6 +677,13 @@ export const ReqorePanel = forwardRef( return show; }, [isSmall, collapsible, actions, hasNonResponsiveActions]); + const iconTooltip = useMemo( + () => ({ + content: label, + }), + [label] + ); + return ( ( image={loading ? undefined : iconImage} margin='right' color={iconColor} - tooltip={{ - content: label, - }} + tooltip={iconTooltip} effect={{ opacity: CONTROL_ICON_OPACITY, }} From 0da1c79eb6ee11a9e5cd61b9935458bb2b78c500 Mon Sep 17 00:00:00 2001 From: Foxhoundn Date: Wed, 11 Dec 2024 17:55:06 +0100 Subject: [PATCH 2/2] Remove tooltip functionality from component and associated tests --- __tests__/panel.test.tsx | 19 ------------------- src/components/Panel/index.tsx | 3 --- 2 files changed, 22 deletions(-) diff --git a/__tests__/panel.test.tsx b/__tests__/panel.test.tsx index d4d787b3..f5e0614d 100644 --- a/__tests__/panel.test.tsx +++ b/__tests__/panel.test.tsx @@ -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 properly', () => { @@ -203,24 +202,6 @@ test('Renders without title & bottom actions if all actions are not sh expect(document.querySelectorAll('.reqore-panel-bottom-actions').length).toBe(0); }); -test('Tooltip on works', () => { - jest.useFakeTimers(); - - render( - - Hello - - ); - - 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 ', () => { jest.useFakeTimers(); const onClose = jest.fn(); diff --git a/src/components/Panel/index.tsx b/src/components/Panel/index.tsx index cf27e65f..adff38fd 100644 --- a/src/components/Panel/index.tsx +++ b/src/components/Panel/index.tsx @@ -370,7 +370,6 @@ export const ReqorePanel = forwardRef( headerSize, contentSize, minimal, - tooltip, badge, iconColor, iconProps = {}, @@ -404,7 +403,6 @@ export const ReqorePanel = forwardRef( const isMobile = useReqoreProperty('isMobile'); const { targetRef } = useCombinedRefs(ref); - const [itemRef, setItemRef] = useState(undefined); const [measureRef, { width }] = useMeasure(); useUpdateEffect(() => { @@ -697,7 +695,6 @@ export const ReqorePanel = forwardRef( } targetRef.current = _ref; - setItemRef(_ref); }} isCollapsed={_isCollapsed} rounded={rounded}