Skip to content

Commit a5b45a7

Browse files
Merge pull request #312 from eccenca/fix/improveTooltipPerformanceReplacement-CMEM-6784
Improve tooltip performance process on icon buttons (CMEM-6784)
2 parents 1c518f5 + 2b0cf16 commit a5b45a7

File tree

5 files changed

+30
-7
lines changed

5 files changed

+30
-7
lines changed

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
99
### Added
1010

1111
- Extended existing height and readOnly props from `CodeEditorProps` to `AutoSuggestionProps` & `ExtendedCodeEditorProps` to be configurable from `<CodeAutocompleteField />`
12-
- Added additional actions to `<ActivityControlWidget />`
12+
- `<ActivityControlWidget />`
13+
- `additionalActions` property to include other more complex components between the action buttons and the context menu of the widget
14+
- `<Tooltip />`
15+
- `swapPlaceholderDelay` property to allow configuration of the delay time before the placeholder element is replaced by the actual tooltip component
16+
17+
### Changed
18+
19+
- `<NodeContent />`
20+
- prevent start of a react flow drag action of a node when user clicks in the node menu section
1321

1422
## [24.3.0] - 2025-06-05
1523

src/cmem/ActivityControl/ActivityControlWidget.stories.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,15 @@ const actions: ActivityControlWidgetAction[] = [
3838
{
3939
"data-test-id": "activity-start-activity",
4040
icon: "item-start",
41+
// eslint-disable-next-line no-console
4142
action: () => console.log("start"),
4243
tooltip: "Start Activity",
4344
disabled: false,
4445
},
4546
{
4647
"data-test-id": "activity-stop-activity",
4748
icon: "item-stop",
49+
// eslint-disable-next-line no-console
4850
action: () => console.log("cancel"),
4951
tooltip: "Stop Activity",
5052
disabled: false,

src/components/Icon/IconButton.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const IconButton = ({
5050
const defaultIconTooltipProps = {
5151
hoverOpenDelay: 1000,
5252
openOnTargetFocus: restProps.disabled || (restProps.tabIndex ?? 0) < 0 ? false : undefined,
53+
swapPlaceholderDelay: 1,
5354
};
5455
const iconProps = {
5556
small: restProps.small,

src/components/Tooltip/Tooltip.tsx

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ export interface TooltipProps extends Omit<BlueprintTooltipProps, "position"> {
4242
* You can prevent it in any case by setting it to `false`.
4343
*/
4444
usePlaceholder?: boolean;
45+
/**
46+
* Time after the placeholder element is replaced by the actual tooltip component.
47+
* Must be greater than 0.
48+
* For the first display of the tooltip this time adds up to `hoverOpenDelay`.
49+
*/
50+
swapPlaceholderDelay?: number;
4551
}
4652

4753
export const Tooltip = ({
@@ -53,18 +59,21 @@ export const Tooltip = ({
5359
markdownEnabler = "\n\n",
5460
markdownProps,
5561
usePlaceholder,
56-
hoverOpenDelay = 500,
62+
swapPlaceholderDelay = 100,
63+
hoverOpenDelay = 450,
5764
...otherTooltipProps
5865
}: TooltipProps) => {
5966
const placeholderRef = React.useRef(null);
6067
const eventMemory = React.useRef<null | "afterhover" | "afterfocus">(null);
6168
const searchId = React.useRef<null | string>(null);
62-
const swapDelayTime = 100;
69+
const swapDelay = React.useRef<null | NodeJS.Timeout>(null);
70+
const swapDelayTime = swapPlaceholderDelay;
6371
const [placeholder, setPlaceholder] = React.useState<boolean>(
6472
!otherTooltipProps.disabled &&
6573
!otherTooltipProps.defaultIsOpen &&
6674
!otherTooltipProps.isOpen &&
6775
otherTooltipProps.renderTarget === undefined &&
76+
swapDelayTime > 0 &&
6877
hoverOpenDelay > swapDelayTime &&
6978
(usePlaceholder === true || (typeof content === "string" && usePlaceholder !== false))
7079
);
@@ -77,7 +86,10 @@ export const Tooltip = ({
7786
React.useEffect(() => {
7887
if (placeholderRef.current !== null) {
7988
const swap = (ev: MouseEvent | globalThis.FocusEvent) => {
80-
const swapDelay = setTimeout(() => {
89+
if (swapDelay.current) {
90+
clearTimeout(swapDelay.current);
91+
}
92+
swapDelay.current = setTimeout(() => {
8193
// we delay the swap to prevent unwanted effects
8294
// (e.g. forced mouseover after the swap but the cursor is already somewhere else)
8395
eventMemory.current = ev.type === "focusin" ? "afterfocus" : "afterhover";
@@ -93,7 +105,7 @@ export const Tooltip = ({
93105
) {
94106
eventMemory.current = null;
95107
}
96-
clearTimeout(swapDelay);
108+
clearTimeout(swapDelay.current as NodeJS.Timeout);
97109
});
98110
}
99111
};
@@ -166,7 +178,7 @@ export const Tooltip = ({
166178
) : (
167179
<BlueprintTooltip
168180
lazy={true}
169-
hoverOpenDelay={hoverOpenDelay - swapDelayTime}
181+
hoverOpenDelay={hoverOpenDelay}
170182
{...otherTooltipProps}
171183
content={tooltipContent}
172184
className={targetClassName}

src/extensions/react-flow/nodes/NodeContent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ export function NodeContent<CONTENT_PROPS = any>({
668668
)}
669669
</div>
670670
{(menuButtons || (showExecutionButtons && executionButtons)) && (
671-
<div className={`${eccgui}-graphviz__node__header-menu`}>
671+
<div className={`${eccgui}-graphviz__node__header-menu nodrag`}>
672672
{showExecutionButtons && typeof executionButtons === "function"
673673
? executionButtons(adjustedContentProps, setAdjustedContentProps)
674674
: null}

0 commit comments

Comments
 (0)