F: Improve tooltip performance

This commit is contained in:
Ivan 2024-12-20 14:36:30 +03:00
parent 2b73f5e6af
commit 8bec236f0f
5 changed files with 45 additions and 49 deletions

View File

@ -1,10 +1,11 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { useConceptOptions } from '@/context/ConceptOptionsContext';
import { CstClass, IConstituenta } from '@/models/rsform'; import { CstClass, IConstituenta } from '@/models/rsform';
import { APP_COLORS, colorFgCstStatus } from '@/styling/color'; import { APP_COLORS, colorFgCstStatus } from '@/styling/color';
import { globals } from '@/utils/constants';
import { CProps } from '../props'; import { CProps } from '../props';
import TooltipConstituenta from './TooltipConstituenta';
interface BadgeConstituentaProps extends CProps.Styling { interface BadgeConstituentaProps extends CProps.Styling {
/** Prefix for tooltip ID. */ /** Prefix for tooltip ID. */
@ -18,6 +19,8 @@ interface BadgeConstituentaProps extends CProps.Styling {
* Displays a badge with a constituenta alias and information tooltip. * Displays a badge with a constituenta alias and information tooltip.
*/ */
function BadgeConstituenta({ value, prefixID, className, style }: BadgeConstituentaProps) { function BadgeConstituenta({ value, prefixID, className, style }: BadgeConstituentaProps) {
const { setHoverCst } = useConceptOptions();
return ( return (
<div <div
id={`${prefixID}${value.id}`} id={`${prefixID}${value.id}`}
@ -35,9 +38,10 @@ function BadgeConstituenta({ value, prefixID, className, style }: BadgeConstitue
backgroundColor: value.cst_class === CstClass.BASIC ? APP_COLORS.bgGreen25 : APP_COLORS.bgInput, backgroundColor: value.cst_class === CstClass.BASIC ? APP_COLORS.bgGreen25 : APP_COLORS.bgInput,
...style ...style
}} }}
data-tooltip-id={globals.constituenta_tooltip}
onMouseEnter={() => setHoverCst(value)}
> >
{value.alias} {value.alias}
<TooltipConstituenta anchor={`#${prefixID}${value.id}`} data={value} />
</div> </div>
); );
} }

View File

@ -1,18 +0,0 @@
import InfoConstituenta from '@/components/info/InfoConstituenta';
import Tooltip from '@/components/ui/Tooltip';
import { IConstituenta } from '@/models/rsform';
interface TooltipConstituentaProps {
data: IConstituenta;
anchor: string;
}
function TooltipConstituenta({ data, anchor }: TooltipConstituentaProps) {
return (
<Tooltip clickable layer='z-modalTooltip' anchorSelect={anchor} className='max-w-[30rem]'>
<InfoConstituenta data={data} onClick={event => event.stopPropagation()} />
</Tooltip>
);
}
export default TooltipConstituenta;

View File

@ -3,8 +3,11 @@
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { flushSync } from 'react-dom'; import { flushSync } from 'react-dom';
import InfoConstituenta from '@/components/info/InfoConstituenta';
import Loader from '@/components/ui/Loader';
import Tooltip from '@/components/ui/Tooltip'; import Tooltip from '@/components/ui/Tooltip';
import useLocalStorage from '@/hooks/useLocalStorage'; import useLocalStorage from '@/hooks/useLocalStorage';
import { IConstituenta } from '@/models/rsform';
import { globals, PARAMETER, storage } from '@/utils/constants'; import { globals, PARAMETER, storage } from '@/utils/constants';
import { contextOutsideScope } from '@/utils/labels'; import { contextOutsideScope } from '@/utils/labels';
@ -37,6 +40,8 @@ interface IOptionsContext {
location: string; location: string;
setLocation: React.Dispatch<React.SetStateAction<string>>; setLocation: React.Dispatch<React.SetStateAction<string>>;
setHoverCst: (newValue: IConstituenta | undefined) => void;
calculateHeight: (offset: string, minimum?: string) => string; calculateHeight: (offset: string, minimum?: string) => string;
} }
@ -62,6 +67,8 @@ export const OptionsState = ({ children }: React.PropsWithChildren) => {
const [noFooter, setNoFooter] = useState(false); const [noFooter, setNoFooter] = useState(false);
const [showScroll, setShowScroll] = useState(false); const [showScroll, setShowScroll] = useState(false);
const [hoverCst, setHoverCst] = useState<IConstituenta | undefined>(undefined);
function setDarkClass(isDark: boolean) { function setDarkClass(isDark: boolean) {
const root = window.document.documentElement; const root = window.document.documentElement;
if (isDark) { if (isDark) {
@ -158,23 +165,27 @@ export const OptionsState = ({ children }: React.PropsWithChildren) => {
toggleShowHelp: () => setShowHelp(prev => !prev), toggleShowHelp: () => setShowHelp(prev => !prev),
viewportHeight, viewportHeight,
mainHeight, mainHeight,
calculateHeight calculateHeight,
setHoverCst
}} }}
> >
<> <>
<Tooltip <Tooltip
float // prettier: split-lines float
id={`${globals.tooltip}`} id={globals.tooltip}
layer='z-topmost' layer='z-topmost'
place='right-start' place='right-start'
className='mt-8 max-w-[20rem] break-words' className='mt-8 max-w-[20rem] break-words'
/> />
<Tooltip <Tooltip
float float
id={`${globals.value_tooltip}`} id={globals.value_tooltip}
layer='z-topmost' layer='z-topmost'
className='max-w-[calc(min(40rem,100dvw-2rem))] text-justify' className='max-w-[calc(min(40rem,100dvw-2rem))] text-justify'
/> />
<Tooltip clickable id={globals.constituenta_tooltip} layer='z-modalTooltip' className='max-w-[30rem]'>
{hoverCst ? <InfoConstituenta data={hoverCst} onClick={event => event.stopPropagation()} /> : <Loader />}
</Tooltip>
{children} {children}
</> </>

View File

@ -3,7 +3,6 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { IconDropArrow, IconDropArrowUp } from '@/components/Icons'; import { IconDropArrow, IconDropArrowUp } from '@/components/Icons';
import TooltipConstituenta from '@/components/info/TooltipConstituenta';
import { CProps } from '@/components/props'; import { CProps } from '@/components/props';
import MiniButton from '@/components/ui/MiniButton'; import MiniButton from '@/components/ui/MiniButton';
import Overlay from '@/components/ui/Overlay'; import Overlay from '@/components/ui/Overlay';
@ -13,7 +12,7 @@ import useWindowSize from '@/hooks/useWindowSize';
import { GraphColoring } from '@/models/miscellaneous'; import { GraphColoring } from '@/models/miscellaneous';
import { ConstituentaID, IRSForm } from '@/models/rsform'; import { ConstituentaID, IRSForm } from '@/models/rsform';
import { APP_COLORS, colorBgGraphNode } from '@/styling/color'; import { APP_COLORS, colorBgGraphNode } from '@/styling/color';
import { PARAMETER, prefixes, storage } from '@/utils/constants'; import { globals, PARAMETER, prefixes, storage } from '@/utils/constants';
interface ViewHiddenProps { interface ViewHiddenProps {
items: ConstituentaID[]; items: ConstituentaID[];
@ -31,6 +30,7 @@ function ViewHidden({ items, selected, toggleSelection, setFocus, schema, colori
const windowSize = useWindowSize(); const windowSize = useWindowSize();
const localSelected = items.filter(id => selected.includes(id)); const localSelected = items.filter(id => selected.includes(id));
const [isFolded, setIsFolded] = useLocalStorage(storage.rsgraphFoldHidden, false); const [isFolded, setIsFolded] = useLocalStorage(storage.rsgraphFoldHidden, false);
const { setHoverCst } = useConceptOptions();
function handleClick(cstID: ConstituentaID, event: CProps.EventMouse) { function handleClick(cstID: ConstituentaID, event: CProps.EventMouse) {
if (event.ctrlKey || event.metaKey) { if (event.ctrlKey || event.metaKey) {
@ -89,11 +89,9 @@ function ViewHidden({ items, selected, toggleSelection, setFocus, schema, colori
const adjustedColoring = coloringScheme === 'none' ? 'status' : coloringScheme; const adjustedColoring = coloringScheme === 'none' ? 'status' : coloringScheme;
const id = `${prefixes.cst_hidden_list}${cst.alias}`; const id = `${prefixes.cst_hidden_list}${cst.alias}`;
return ( return (
<div key={`wrap-${id}`}>
<button <button
type='button'
key={id} key={id}
id={id} type='button'
className='min-w-[3rem] rounded-md text-center select-none' className='min-w-[3rem] rounded-md text-center select-none'
style={{ style={{
backgroundColor: colorBgGraphNode(cst, adjustedColoring), backgroundColor: colorBgGraphNode(cst, adjustedColoring),
@ -107,11 +105,11 @@ function ViewHidden({ items, selected, toggleSelection, setFocus, schema, colori
}} }}
onClick={event => handleClick(cstID, event)} onClick={event => handleClick(cstID, event)}
onDoubleClick={() => onEdit(cstID)} onDoubleClick={() => onEdit(cstID)}
data-tooltip-id={globals.constituenta_tooltip}
onMouseEnter={() => setHoverCst(cst)}
> >
{cst.alias} {cst.alias}
</button> </button>
<TooltipConstituenta data={cst} anchor={`#${id}`} />
</div>
); );
})} })}
</div> </div>

View File

@ -144,6 +144,7 @@ export const storage = {
export const globals = { export const globals = {
tooltip: 'global_tooltip', tooltip: 'global_tooltip',
value_tooltip: 'value_tooltip', value_tooltip: 'value_tooltip',
constituenta_tooltip: 'cst_tooltip',
password_tooltip: 'password_tooltip', password_tooltip: 'password_tooltip',
email_tooltip: 'email_tooltip', email_tooltip: 'email_tooltip',
main_scroll: 'main_scroll', main_scroll: 'main_scroll',