Unverified Commit 93a8d0f1 authored by Alex Andreev's avatar Alex Andreev Committed by GitHub
Browse files

Do not render Tooltip and Menu elements until needed (#5168)


* Clean up Menu DOM elements
Signed-off-by: default avatarAlex Andreev <alex.andreev.email@gmail.com>

* Clean up Tooltip DOM
Signed-off-by: default avatarAlex Andreev <alex.andreev.email@gmail.com>

* Do not render Animate when not in need
Signed-off-by: default avatarAlex Andreev <alex.andreev.email@gmail.com>

* Update snapshots
Signed-off-by: default avatarAlex Andreev <alex.andreev.email@gmail.com>

* clean up <Animate/> and <Tooltip/>
Signed-off-by: default avatarRoman <ixrock@gmail.com>
Co-authored-by: default avatarRoman <ixrock@gmail.com>
parent ca21e084
Showing with 31 additions and 234 deletions
+31 -234
......@@ -83,19 +83,23 @@ export class Animate extends React.Component<AnimateProps> {
}
render() {
if (!this.isVisible) {
return null;
}
const { name, enterDuration, leaveDuration } = this.props;
const contentElem = this.contentElem;
const durations = {
const cssVarsForAnimation = {
"--enter-duration": `${enterDuration}ms`,
"--leave-duration": `${leaveDuration}ms`,
} as React.CSSProperties;
return React.cloneElement(contentElem, {
className: cssNames("Animate", name, contentElem.props.className, this.statusClassName),
children: this.isVisible ? contentElem.props.children : null,
children: contentElem.props.children,
style: {
...contentElem.props.style,
...durations,
...cssVarsForAnimation,
},
});
}
......
......@@ -37,10 +37,6 @@ exports[`kube-object-menu given kube object renders 1`] = `
</ul>
</div>
</div>
<div
class="Animate opacity-scale Dialog flex center ConfirmDialog modal"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
/>
</body>
`;
......
......@@ -16,58 +16,6 @@ exports[`kube-object-status-icon given info and warning statuses are present, wh
<div />
</i>
</div>
<div
class="Tooltip narrow formatter"
>
<div
class="KubeObjectStatusTooltip"
>
<div
class="level warning"
>
<span
class="title"
>
Warning
</span>
<div
class="status msg"
>
-
Some warning status for some-name
<span
class="age"
>
·
2d
</span>
</div>
</div>
<div
class="level info"
>
<span
class="title"
>
Info
</span>
<div
class="status msg"
>
-
Some info status for some-name
<span
class="age"
>
·
2d
</span>
</div>
</div>
</div>
</div>
</body>
`;
......@@ -87,36 +35,6 @@ exports[`kube-object-status-icon given level "critical" status, when rendered, r
<div />
</i>
</div>
<div
class="Tooltip narrow formatter"
>
<div
class="KubeObjectStatusTooltip"
>
<div
class="level error"
>
<span
class="title"
>
Critical
</span>
<div
class="status msg"
>
-
Some critical status for some-name
<span
class="age"
>
·
2d
</span>
</div>
</div>
</div>
</div>
</body>
`;
......@@ -136,36 +54,6 @@ exports[`kube-object-status-icon given level "info" status, when rendered, rende
<div />
</i>
</div>
<div
class="Tooltip narrow formatter"
>
<div
class="KubeObjectStatusTooltip"
>
<div
class="level info"
>
<span
class="title"
>
Info
</span>
<div
class="status msg"
>
-
Some info status for some-name
<span
class="age"
>
·
2d
</span>
</div>
</div>
</div>
</div>
</body>
`;
......@@ -185,36 +73,6 @@ exports[`kube-object-status-icon given level "warning" status, when rendered, re
<div />
</i>
</div>
<div
class="Tooltip narrow formatter"
>
<div
class="KubeObjectStatusTooltip"
>
<div
class="level warning"
>
<span
class="title"
>
Warning
</span>
<div
class="status msg"
>
-
Some warning status for some-name
<span
class="age"
>
·
2d
</span>
</div>
</div>
</div>
</div>
</body>
`;
......@@ -254,79 +112,5 @@ exports[`kube-object-status-icon given status for all levels is present, when re
<div />
</i>
</div>
<div
class="Tooltip narrow formatter"
>
<div
class="KubeObjectStatusTooltip"
>
<div
class="level error"
>
<span
class="title"
>
Critical
</span>
<div
class="status msg"
>
-
Some critical status for some-name
<span
class="age"
>
·
2d
</span>
</div>
</div>
<div
class="level warning"
>
<span
class="title"
>
Warning
</span>
<div
class="status msg"
>
-
Some warning status for some-name
<span
class="age"
>
·
2d
</span>
</div>
</div>
<div
class="level info"
>
<span
class="title"
>
Info
</span>
<div
class="status msg"
>
-
Some info status for some-name
<span
class="age"
>
·
2d
</span>
</div>
</div>
</div>
</div>
</body>
`;
......@@ -93,7 +93,6 @@ export class Menu extends React.Component<MenuProps, State> {
this.opener.addEventListener(this.props.toggleEvent, this.toggle);
this.opener.addEventListener("keydown", this.onKeyDown);
}
this.elem.addEventListener("keydown", this.onKeyDown);
window.addEventListener("resize", this.onWindowResize);
window.addEventListener("click", this.onClickOutside, true);
window.addEventListener("scroll", this.onScrollOutside, true);
......@@ -106,7 +105,6 @@ export class Menu extends React.Component<MenuProps, State> {
this.opener.removeEventListener(this.props.toggleEvent, this.toggle);
this.opener.removeEventListener("keydown", this.onKeyDown);
}
this.elem.removeEventListener("keydown", this.onKeyDown);
window.removeEventListener("resize", this.onWindowResize);
window.removeEventListener("click", this.onClickOutside, true);
window.removeEventListener("scroll", this.onScrollOutside, true);
......@@ -218,7 +216,7 @@ export class Menu extends React.Component<MenuProps, State> {
}
}
onKeyDown(evt: KeyboardEvent) {
onKeyDown(evt: React.KeyboardEvent | KeyboardEvent) {
if (!this.isOpen) return;
switch (evt.code) {
......@@ -330,6 +328,7 @@ export class Menu extends React.Component<MenuProps, State> {
left: this.state?.menuStyle?.left,
top: this.state?.menuStyle?.top,
}}
onKeyDown={this.onKeyDown}
>
{menuItems}
</ul>
......
......@@ -9,7 +9,7 @@ import React from "react";
import { createPortal } from "react-dom";
import { observer } from "mobx-react";
import { boundMethod, cssNames, IClassName } from "../../utils";
import { observable, makeObservable } from "mobx";
import { observable, makeObservable, action } from "mobx";
export enum TooltipPosition {
TOP = "top",
......@@ -54,7 +54,8 @@ export class Tooltip extends React.Component<TooltipProps> {
@observable.ref elem: HTMLElement;
@observable activePosition: TooltipPosition;
@observable isVisible = false;
@observable isVisible = this.props.visible ?? false;
@observable isContentVisible = false; // animation manager
constructor(props: TooltipProps) {
super(props);
......@@ -87,15 +88,16 @@ export class Tooltip extends React.Component<TooltipProps> {
this.hoverTarget.removeEventListener("mouseleave", this.onLeaveTarget);
}
@boundMethod
@action.bound
protected onEnterTarget() {
this.isVisible = true;
this.refreshPosition();
requestAnimationFrame(action(() => this.isContentVisible = true));
}
@boundMethod
@action.bound
protected onLeaveTarget() {
this.isVisible = false;
this.isContentVisible = false;
}
@boundMethod
......@@ -103,6 +105,10 @@ export class Tooltip extends React.Component<TooltipProps> {
const { preferredPositions } = this.props;
const { elem, targetElem } = this;
if (!elem) {
return;
}
let positions = new Set<TooltipPosition>([
TooltipPosition.RIGHT,
TooltipPosition.BOTTOM,
......@@ -150,6 +156,10 @@ export class Tooltip extends React.Component<TooltipProps> {
}
protected setPosition(pos: { left: number; top: number }) {
if (!this.elem) {
return;
}
const elemStyle = this.elem.style;
elemStyle.left = `${pos.left}px`;
......@@ -214,13 +224,17 @@ export class Tooltip extends React.Component<TooltipProps> {
}
render() {
const { style, formatters, usePortal, children, visible } = this.props;
if (!this.isVisible) {
return null;
}
const { style, formatters, usePortal, children } = this.props;
const className = cssNames("Tooltip", this.props.className, formatters, this.activePosition, {
visible: visible ?? this.isVisible,
visible: this.isContentVisible,
formatter: !!formatters,
});
const tooltip = (
<div className={className} style={style} ref={this.bindRef}>
<div className={className} style={style} ref={this.bindRef} role="tooltip">
{children}
</div>
);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment