Skip to content
Snippets Groups Projects
Unverified Commit 9be2d8f2 authored by Dalton's avatar Dalton Committed by GitHub
Browse files

Add hideOnEsc plugin to TippyPopover (#20299)

* Add hideOnEsc plugin & tweak lazy plugin

* full example

* rmv unused defaultValue
parent 8278110d
No related branches found
No related tags found
No related merge requests found
......@@ -54,6 +54,20 @@ function LazyContentExample() {
return <LazyPopoverBody opacity={opacity}>popover content</LazyPopoverBody>;
}
function VisiblePropExample() {
const [visible, setVisible] = React.useState(true);
return (
<TippyPopover
visible={visible}
onHide={() => setVisible(false)}
placement="left-end"
content={content}
>
<div onClick={() => setVisible(true)}>{target}</div>
</TippyPopover>
);
}
export const examples = {
"vertical placement": (
<TippyPopover placement="top-start" content={content}>
......@@ -84,4 +98,5 @@ export const examples = {
{target}
</TippyPopover>
),
"control mode + handling of Esc press": <VisiblePropExample />,
};
import React, { useState, useMemo } from "react";
import PropTypes from "prop-types";
import * as Tippy from "@tippyjs/react";
import * as TippyReact from "@tippyjs/react";
import * as tippy from "tippy.js";
import cx from "classnames";
import { isReducedMotionPreferred } from "metabase/lib/dom";
import EventSandbox from "metabase/components/EventSandbox";
import { isCypressActive } from "metabase/env";
const TippyComponent = Tippy.default;
type TippyProps = Tippy.TippyProps;
const TippyComponent = TippyReact.default;
type TippyProps = TippyReact.TippyProps;
type TippyInstance = tippy.Instance;
export interface ITippyPopoverProps extends TippyProps {
disableContentSandbox?: boolean;
......@@ -23,40 +25,55 @@ const propTypes = {
...TippyComponent.propTypes,
};
function appendTo() {
return document.body;
}
const hideOnEscPlugin = {
name: "hideOnEsc",
fn({ hide }: TippyInstance) {
function onKeyDown(event: KeyboardEvent) {
if (event.key === "Escape") {
hide();
}
}
return {
onShow() {
document.addEventListener("keydown", onKeyDown);
},
onHide() {
document.removeEventListener("keydown", onKeyDown);
},
};
},
};
function TippyPopover({
className,
disableContentSandbox,
lazy = true,
content,
delay,
lazy = true,
...props
}: ITippyPopoverProps) {
delay = isCypressActive ? 0 : delay;
const animationDuration = isReducedMotionPreferred() ? 0 : undefined;
const [mounted, setMounted] = useState(!lazy);
const plugins = useMemo(
() =>
lazy
? [
{
fn: () => ({
onMount: () => setMounted(true),
onHidden: () => setMounted(false),
}),
},
]
: [],
const shouldShowContent = mounted && content != null;
const lazyPlugin = useMemo(
() => ({
name: "lazy",
fn: () => ({
onMount: () => setMounted(true),
onHidden: () => setMounted(!lazy),
}),
}),
[lazy],
);
let computedContent;
if (!mounted) {
computedContent = "";
} else if (content != null) {
computedContent = (
<EventSandbox disabled={disableContentSandbox}>{content}</EventSandbox>
);
}
const plugins = useMemo(() => [lazyPlugin, hideOnEscPlugin], [lazyPlugin]);
return (
<TippyComponent
......@@ -64,12 +81,18 @@ function TippyPopover({
theme="popover"
arrow={false}
offset={OFFSET}
appendTo={() => document.body}
appendTo={appendTo}
plugins={plugins}
{...props}
duration={animationDuration}
delay={delay}
content={computedContent}
content={
shouldShowContent ? (
<EventSandbox disabled={disableContentSandbox}>
{content}
</EventSandbox>
) : null
}
/>
);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment