Skip to content

Commit

Permalink
Improve grid rendering performance with a custom tooltip (#24417)
Browse files Browse the repository at this point in the history
* fully custom tooltip

* use a customized chakra tooltip

* update notice

(cherry picked from commit e452949)
  • Loading branch information
bbovenzi authored and ephraimbuddy committed Jun 29, 2022
1 parent 717ccb2 commit 48a156e
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 1 deletion.
7 changes: 7 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion airflow/www/static/js/grid/components/StatusBox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down
179 changes: 179 additions & 0 deletions airflow/www/static/js/grid/components/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -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 `<span/>` 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<PortalProps, 'appendToParentPortal' | 'containerRef'>
}

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<TooltipProps, 'div'>((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<any>
};
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}
<AnimatePresence>
{tooltip.isOpen && (
<Portal {...portalProps}>
<chakra.div
{...tooltip.getTooltipPositionerProps()}
__css={{
zIndex: styles.zIndex,
pointerEvents: 'none',
}}
>
<StyledTooltip
{...(tooltipProps as any)}
initial="exit"
animate="enter"
exit="exit"
__css={styles}
>
{label}
{hasArrow && (
<chakra.div
data-popper-arrow
className="chakra-tooltip__arrow-wrapper"
>
<chakra.div
data-popper-arrow-inner
className="chakra-tooltip__arrow"
__css={{ bg: styles.bg }}
/>
</chakra.div>
)}
</StyledTooltip>
</chakra.div>
</Portal>
)}
</AnimatePresence>
</>
);
});

export default Tooltip;

0 comments on commit 48a156e

Please sign in to comment.