|
| 1 | +import Link from "@material-ui/core/Link" |
| 2 | +import Popover from "@material-ui/core/Popover" |
| 3 | +import { makeStyles } from "@material-ui/core/styles" |
| 4 | +import HelpIcon from "@material-ui/icons/HelpOutline" |
| 5 | +import OpenInNewIcon from "@material-ui/icons/OpenInNew" |
| 6 | +import { useState } from "react" |
| 7 | +import { Stack } from "../Stack/Stack" |
| 8 | + |
| 9 | +type Size = "small" | "medium" |
| 10 | +export interface HelpTooltipProps { |
| 11 | + // Useful to test on storybook |
| 12 | + open?: boolean |
| 13 | + size?: Size |
| 14 | +} |
| 15 | + |
| 16 | +export const HelpTooltip: React.FC<HelpTooltipProps> = ({ children, open, size = "medium" }) => { |
| 17 | + const styles = useStyles({ size }) |
| 18 | + const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null) |
| 19 | + open = open ?? Boolean(anchorEl) |
| 20 | + const id = open ? "help-popover" : undefined |
| 21 | + |
| 22 | + return ( |
| 23 | + <> |
| 24 | + <button aria-describedby={id} className={styles.button} onClick={(event) => setAnchorEl(event.currentTarget)}> |
| 25 | + <HelpIcon className={styles.icon} /> |
| 26 | + </button> |
| 27 | + <Popover |
| 28 | + classes={{ paper: styles.popoverPaper }} |
| 29 | + id={id} |
| 30 | + open={open} |
| 31 | + anchorEl={anchorEl} |
| 32 | + onClose={() => { |
| 33 | + setAnchorEl(null) |
| 34 | + }} |
| 35 | + anchorOrigin={{ |
| 36 | + vertical: "bottom", |
| 37 | + horizontal: "left", |
| 38 | + }} |
| 39 | + transformOrigin={{ |
| 40 | + vertical: "top", |
| 41 | + horizontal: "left", |
| 42 | + }} |
| 43 | + > |
| 44 | + {children} |
| 45 | + </Popover> |
| 46 | + </> |
| 47 | + ) |
| 48 | +} |
| 49 | + |
| 50 | +export const HelpTooltipTitle: React.FC = ({ children }) => { |
| 51 | + const styles = useStyles() |
| 52 | + |
| 53 | + return <h4 className={styles.title}>{children}</h4> |
| 54 | +} |
| 55 | + |
| 56 | +export const HelpTooltipText: React.FC = ({ children }) => { |
| 57 | + const styles = useStyles() |
| 58 | + |
| 59 | + return <p className={styles.text}>{children}</p> |
| 60 | +} |
| 61 | + |
| 62 | +export const HelpTooltipLink: React.FC<{ href: string }> = ({ children, href }) => { |
| 63 | + const styles = useStyles() |
| 64 | + |
| 65 | + return ( |
| 66 | + <Link href={href} target="_blank" rel="noreferrer" className={styles.link}> |
| 67 | + <OpenInNewIcon className={styles.linkIcon} /> |
| 68 | + {children} |
| 69 | + </Link> |
| 70 | + ) |
| 71 | +} |
| 72 | + |
| 73 | +export const HelpTooltipLinksGroup: React.FC = ({ children }) => { |
| 74 | + const styles = useStyles() |
| 75 | + |
| 76 | + return ( |
| 77 | + <Stack spacing={1} className={styles.linksGroup}> |
| 78 | + {children} |
| 79 | + </Stack> |
| 80 | + ) |
| 81 | +} |
| 82 | + |
| 83 | +const getButtonSpacingFromSize = (size?: Size): number => { |
| 84 | + switch (size) { |
| 85 | + case "small": |
| 86 | + return 2.75 |
| 87 | + case "medium": |
| 88 | + default: |
| 89 | + return 3 |
| 90 | + } |
| 91 | +} |
| 92 | + |
| 93 | +const getIconSpacingFromSize = (size?: Size): number => { |
| 94 | + switch (size) { |
| 95 | + case "small": |
| 96 | + return 1.75 |
| 97 | + case "medium": |
| 98 | + default: |
| 99 | + return 2 |
| 100 | + } |
| 101 | +} |
| 102 | + |
| 103 | +const useStyles = makeStyles((theme) => ({ |
| 104 | + button: { |
| 105 | + display: "flex", |
| 106 | + alignItems: "center", |
| 107 | + justifyContent: "center", |
| 108 | + width: ({ size }: { size?: Size }) => theme.spacing(getButtonSpacingFromSize(size)), |
| 109 | + height: ({ size }: { size?: Size }) => theme.spacing(getButtonSpacingFromSize(size)), |
| 110 | + padding: 0, |
| 111 | + border: 0, |
| 112 | + background: "transparent", |
| 113 | + color: theme.palette.text.secondary, |
| 114 | + cursor: "pointer", |
| 115 | + |
| 116 | + "&:hover": { |
| 117 | + color: theme.palette.text.primary, |
| 118 | + }, |
| 119 | + }, |
| 120 | + |
| 121 | + icon: { |
| 122 | + width: ({ size }: { size?: Size }) => theme.spacing(getIconSpacingFromSize(size)), |
| 123 | + height: ({ size }: { size?: Size }) => theme.spacing(getIconSpacingFromSize(size)), |
| 124 | + }, |
| 125 | + |
| 126 | + popoverPaper: { |
| 127 | + marginTop: theme.spacing(0.5), |
| 128 | + width: theme.spacing(38), |
| 129 | + padding: theme.spacing(2.5), |
| 130 | + color: theme.palette.text.secondary, |
| 131 | + }, |
| 132 | + |
| 133 | + title: { |
| 134 | + marginTop: 0, |
| 135 | + marginBottom: theme.spacing(1), |
| 136 | + color: theme.palette.text.primary, |
| 137 | + }, |
| 138 | + |
| 139 | + text: { |
| 140 | + marginTop: theme.spacing(0.5), |
| 141 | + marginBottom: theme.spacing(0.5), |
| 142 | + }, |
| 143 | + |
| 144 | + link: { |
| 145 | + display: "flex", |
| 146 | + alignItems: "center", |
| 147 | + }, |
| 148 | + |
| 149 | + linkIcon: { |
| 150 | + color: "inherit", |
| 151 | + width: 14, |
| 152 | + height: 14, |
| 153 | + marginRight: theme.spacing(1), |
| 154 | + }, |
| 155 | + |
| 156 | + linksGroup: { |
| 157 | + marginTop: theme.spacing(2), |
| 158 | + }, |
| 159 | +})) |
0 commit comments