From 48a156e260a4ab32e5b0cb3d8a600dfed3764642 Mon Sep 17 00:00:00 2001 From: Brent Bovenzi Date: Mon, 13 Jun 2022 20:23:53 +0200 Subject: [PATCH] Improve grid rendering performance with a custom tooltip (#24417) * fully custom tooltip * use a customized chakra tooltip * update notice (cherry picked from commit e452949610cff67c0e0a9918a8fefa7e8cc4b8c8) --- NOTICE | 7 + .../static/js/grid/components/StatusBox.jsx | 2 +- .../www/static/js/grid/components/Tooltip.tsx | 179 ++++++++++++++++++ 3 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 airflow/www/static/js/grid/components/Tooltip.tsx diff --git a/NOTICE b/NOTICE index 4c7b795d88ce6..84c77cd4fc12c 100644 --- a/NOTICE +++ b/NOTICE @@ -20,3 +20,10 @@ This product contains a modified portion of 'Flask App Builder' developed by Dan (https://github.com/dpgaspar/Flask-AppBuilder). * Copyright 2013, Daniel Vaz Gaspar + +Chakra UI: +----- +This product contains a modified portion of 'Chakra UI' developed by Segun Adebayo. +(https://github.com/chakra-ui/chakra-ui). + +* Copyright 2019, Segun Adebayo diff --git a/airflow/www/static/js/grid/components/StatusBox.jsx b/airflow/www/static/js/grid/components/StatusBox.jsx index 316529930f3b9..2f079949a9fb8 100644 --- a/airflow/www/static/js/grid/components/StatusBox.jsx +++ b/airflow/www/static/js/grid/components/StatusBox.jsx @@ -23,10 +23,10 @@ import React from 'react'; import { isEqual } from 'lodash'; import { Box, - Tooltip, useTheme, } from '@chakra-ui/react'; +import Tooltip from './Tooltip'; import InstanceTooltip from './InstanceTooltip'; import { useContainerRef } from '../context/containerRef'; diff --git a/airflow/www/static/js/grid/components/Tooltip.tsx b/airflow/www/static/js/grid/components/Tooltip.tsx new file mode 100644 index 0000000000000..1a80e91bcff8b --- /dev/null +++ b/airflow/www/static/js/grid/components/Tooltip.tsx @@ -0,0 +1,179 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* Simplified version of chakra's Tooltip component for faster rendering but less customization */ + +import React from 'react'; +import { + chakra, + forwardRef, + HTMLChakraProps, + omitThemingProps, + ThemingProps, + useTheme, + useTooltip, + UseTooltipProps, + Portal, + PortalProps, +} from '@chakra-ui/react'; +import { AnimatePresence, motion } from 'framer-motion'; + +export interface TooltipProps + extends HTMLChakraProps<'div'>, + ThemingProps<'Tooltip'>, + UseTooltipProps { + /** + * The React component to use as the + * trigger for the tooltip + */ + children: React.ReactNode + /** + * The label of the tooltip + */ + label?: React.ReactNode + /** + * The accessible, human friendly label to use for + * screen readers. + * + * If passed, tooltip will show the content `label` + * but expose only `aria-label` to assistive technologies + */ + 'aria-label'?: string + /** + * If `true`, the tooltip will wrap its children + * in a `` with `tabIndex=0` + */ + shouldWrapChildren?: boolean + /** + * If `true`, the tooltip will show an arrow tip + */ + hasArrow?: boolean + /** + * Props to be forwarded to the portal component + */ + portalProps?: Pick +} + +const StyledTooltip = chakra(motion.div); + +const styles = { + '--popper-arrow-bg': ['var(--tooltip-bg)'], + '--tooltip-bg': 'colors.gray.700', + bg: ['var(--tooltip-bg)'], + borderRadius: 'sm', + boxShadow: 'md', + color: 'whiteAlpha.900', + fontSize: 'md', + fontWeight: 'medium', + maxW: '320px', + px: '8px', + py: '2px', + zIndex: 'tooltip', +}; + +/** + * Tooltips display informative text when users hover, focus on, or tap an element. + * + * @see Docs https://chakra-ui.com/docs/overlay/tooltip + * @see WAI-ARIA https://www.w3.org/TR/wai-aria-practices/#tooltip + */ +const Tooltip = forwardRef((props, ref) => { + const ownProps = omitThemingProps(props); + const theme = useTheme(); + + const { + children, + label, + shouldWrapChildren, + 'aria-label': ariaLabel, + hasArrow, + bg, + portalProps, + background, + backgroundColor, + bgColor, + ...rest + } = ownProps; + + const tooltip = useTooltip({ ...rest, direction: theme.direction }); + + /* + * Ensure tooltip has only one child node + */ + const child = React.Children.only(children) as React.ReactElement & { + ref?: React.Ref + }; + const trigger: React.ReactElement = React.cloneElement( + child, + tooltip.getTriggerProps(child.props, child.ref), + ); + + const tooltipProps = tooltip.getTooltipProps({}, ref); + + /** + * If the `label` is empty, there's no point showing the tooltip. + * Let's simply return the children + */ + if (!label) { + return <>{children}; + } + + return ( + <> + {trigger} + + {tooltip.isOpen && ( + + + + {label} + {hasArrow && ( + + + + )} + + + + )} + + + ); +}); + +export default Tooltip;