github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/web/src/Tooltip.tsx (about)

     1  import { makeStyles } from "@material-ui/core/styles"
     2  import Tooltip, { TooltipProps } from "@material-ui/core/Tooltip"
     3  import React from "react"
     4  import { useStorageState } from "react-storage-hooks"
     5  import styled from "styled-components"
     6  import { ReactComponent as InfoSvg } from "./assets/svg/info.svg"
     7  import { InstrumentedButton } from "./instrumentedComponents"
     8  import {
     9    Color,
    10    ColorRGBA,
    11    Font,
    12    FontSize,
    13    mixinResetButtonStyle,
    14    SizeUnit,
    15  } from "./style-helpers"
    16  
    17  const INFO_TOOLTIP_LEAVE_DELAY = 500
    18  
    19  let useStyles = makeStyles((theme: any) => ({
    20    arrow: {
    21      color: Color.grayLightest,
    22      "&::before": {
    23        border: `1px solid ${Color.gray50}`,
    24      },
    25    },
    26    tooltip: {
    27      backgroundColor: Color.grayLightest,
    28      fontFamily: Font.sansSerif,
    29      fontSize: FontSize.smallest,
    30      fontWeight: 400,
    31      color: Color.gray20,
    32      padding: SizeUnit(0.25),
    33      border: `1px solid ${Color.gray50}`,
    34    },
    35    popper: {
    36      filter: "drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25))",
    37    },
    38  }))
    39  
    40  export default function TiltTooltip(props: TooltipProps) {
    41    const classes = useStyles()
    42  
    43    return (
    44      <Tooltip
    45        arrow
    46        placement="top-start"
    47        classes={classes}
    48        role="tooltip"
    49        enterNextDelay={500}
    50        {...props}
    51      />
    52    )
    53  }
    54  
    55  const InfoIcon = styled(InfoSvg)`
    56    cursor: pointer;
    57    margin: ${SizeUnit(0.25)};
    58    flex-shrink: 0;
    59  
    60    &.shadow {
    61      border-radius: 50%;
    62      box-shadow: 0px 0px 5px 2px ${ColorRGBA(Color.gray20, 0.6)};
    63    }
    64  
    65    .fillStd {
    66      fill: ${Color.gray60};
    67    }
    68  `
    69  const DismissButton = styled(InstrumentedButton)`
    70    ${mixinResetButtonStyle};
    71  
    72    width: 100%;
    73  
    74    .MuiButton-label {
    75      font-size: ${FontSize.smallester};
    76      font-style: italic;
    77      color: ${Color.gray50};
    78      text-align: right;
    79      display: block;
    80    }
    81  `
    82  
    83  export interface InfoTooltipProps {
    84    dismissId?: string // If set, this tooltip will be dismissable, keyed by this string
    85    displayShadow?: boolean
    86    idForIcon?: string // Use to semantically associate the tooltip with another element through `aria-describedby` or `aria-labelledby`
    87  }
    88  
    89  export function TiltInfoTooltip(
    90    props: Omit<TooltipProps, "children"> & InfoTooltipProps
    91  ) {
    92    const { displayShadow, idForIcon, title, dismissId, ...tooltipProps } = props
    93    const shadowClass = displayShadow ? "shadow" : ""
    94  
    95    // bug: if multiple tooltips are on the same page with the same key,
    96    // "dismiss" will only affect the tooltip clicked, until next refresh
    97    // https://app.clubhouse.io/windmill/story/12654/modifying-usepersistentstate-state-doesn-t-update-other-components-in-the-same-page-using-the-same-key
    98    const [dismissed, setDismissed] = useStorageState(
    99      localStorage,
   100      `tooltip-dismissed-${props.dismissId}`,
   101      false
   102    )
   103    if (dismissed) {
   104      return null
   105    }
   106  
   107    let content = title
   108  
   109    if (dismissId !== undefined) {
   110      content = (
   111        <>
   112          <div>{title}</div>
   113          <DismissButton
   114            size="small"
   115            analyticsName={"ui.web.dismissTooltip"}
   116            analyticsTags={{ tooltip: props.dismissId }}
   117            onClick={() => setDismissed(true)}
   118          >
   119            Don't show this tip
   120          </DismissButton>
   121        </>
   122      )
   123    }
   124  
   125    return (
   126      <TiltTooltip
   127        interactive
   128        leaveDelay={INFO_TOOLTIP_LEAVE_DELAY}
   129        title={content}
   130        {...tooltipProps}
   131      >
   132        <InfoIcon id={idForIcon} height={16} width={16} className={shadowClass} />
   133      </TiltTooltip>
   134    )
   135  }