Advertisement
Guest User

Tooltip - JSX

a guest
Jan 23rd, 2020
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import React, { Component } from 'react';
  2. import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
  3. import InfoIcon from '../../InfoIcon/InfoIcon';
  4.  
  5. let counter = 0;
  6.  
  7. class TooltipContainer extends Component {
  8.     constructor(props) {
  9.         super(props);
  10.         this.state = {
  11.             isFocused: false,
  12.             isHovered: false,
  13.         };
  14.         this.identifier = `react-accessible-tooltip-${counter}`;
  15.         counter += 1;
  16.         this.onFocus = this.onFocus.bind(this);
  17.         this.onBlur = this.onBlur.bind(this);
  18.         this.onMouseEnter = this.onMouseEnter.bind(this);
  19.         this.onMouseLeave = this.onMouseLeave.bind(this);
  20.         this.handleTouch = this.handleTouch.bind(this);
  21.         this.handleKeyDown = this.handleKeyDown.bind(this);
  22.         this.container = React.createRef();
  23.     }
  24.  
  25.     componentDidMount() {
  26.         document.addEventListener('keydown', this.handleKeyDown);
  27.         document.addEventListener('touchstart', this.handleTouch);
  28.     }
  29.  
  30.     componentWillUnmount() {
  31.         document.removeEventListener('keydown', this.handleKeyDown);
  32.         document.removeEventListener('touchstart', this.handleTouch);
  33.     }
  34.  
  35.     onFocus() {
  36.         this.setState({ isFocused: true });
  37.     };
  38.  
  39.     onBlur({
  40.         relatedTarget,
  41.         currentTarget,
  42.     }){
  43.         // relatedTarget is better for React testability etc, but activeElement works as an IE11 fallback:
  44.         const newTarget = relatedTarget || document.activeElement;
  45.  
  46.         // The idea of this logic is that we should only close the tooltip if focus has shifted from the tooltip AND all of its descendents.
  47.         if (!(newTarget)) {
  48.             this.setState({ isFocused: false });
  49.         } else if (!currentTarget.contains(newTarget)) {
  50.             this.setState({ isFocused: false });
  51.         }
  52.     }
  53.  
  54.     onMouseEnter() {
  55.         this.setState({ isHovered: true });
  56.     }
  57.  
  58.     onMouseLeave() {
  59.         this.setState({ isHovered: false });
  60.     }
  61.  
  62.     // This handles the support for touch devices that do not trigger blur on 'touch-away'.
  63.     handleTouch({ target }) {
  64.         const { activeElement } = document;
  65.  
  66.         if (
  67.             activeElement instanceof Element &&
  68.             target instanceof Element &&
  69.             this.container instanceof Element &&
  70.             !this.container.contains(target) && // touch target not a tooltip descendent
  71.             this.state.isFocused // prevent redundant state change
  72.         ) {
  73.             this.setState({ isFocused: false });
  74.             activeElement.blur();
  75.         } else if (
  76.             activeElement instanceof Element &&
  77.             target instanceof Element &&
  78.             this.container instanceof Element &&
  79.             this.container.contains(target) && // touch target is on tooltip descendant
  80.             !this.state.isFocused // prevent redundant state change
  81.         ) {
  82.             this.setState({ isFocused: true });
  83.         }
  84.     }
  85.  
  86.     handleKeyDown({ key, keyCode, which }) {
  87.         if (key === 'Escape' || keyCode === 27 || which === 27) {
  88.             this.setState({ isFocused: false });
  89.         }
  90.     }
  91.  
  92.  
  93.     render() {
  94.         console.log('props', this.props)
  95.         const { label: Label, overlay: Overlay, ...rest } = this.props;
  96.  
  97.         const { isFocused, isHovered } = this.state;
  98.         const isHidden = !(isFocused || isHovered);
  99.  
  100.         const labelProps = {
  101.             labelAttributes: {
  102.                 tabIndex: '0',
  103.                 'aria-describedby': this.identifier,
  104.                 onFocus: this.onFocus,
  105.             },
  106.             isHidden,
  107.         };
  108.  
  109.         const overlayProps = {
  110.             overlayAttributes: {
  111.                 role: 'tooltip',
  112.                 tabIndex: '-1',
  113.                 id: this.identifier,
  114.                 'aria-hidden': isHidden.toString(),
  115.             },
  116.             isHidden,
  117.         };
  118.  
  119.         return (
  120.             <div
  121.                 {...rest}
  122.                 onBlur={this.onBlur}
  123.                 ref={ref => {
  124.                     this.container = ref;
  125.                 }}
  126.                 onMouseEnter={this.onMouseEnter}
  127.                 onMouseLeave={this.onMouseLeave}
  128.             >
  129.                 <a><InfoIcon icon={faInfoCircle} {...labelProps} /></a>
  130.                 <Overlay {...overlayProps} />
  131.             </div>
  132.         );
  133.     }
  134. }
  135.  
  136. export default TooltipContainer;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement