feat: custom tooltip instead of browser tooltip

fix: remove default browser tooltip
fix: rename HelpTooltip into Tooltip
feat: allow custom tooltip element
fix: open cashout fudgefactor help tooltip on click
feat: edit and delete (editabletable) custom tooltip
feat: custom tooltip on single field editables
feat: SingleRowTable custom tooltip
feat: custom tooltip on modal close button
fix: operatorinfo custom tooltip
feat: confirmdialog custom close tooltip
fix: remove browser default tooltip from action buttons
fix: eslint
This commit is contained in:
Mauricio Navarro Miranda 2020-08-13 04:26:42 -05:00 committed by Josh Harvey
parent f700b29b3d
commit 653f939856
18 changed files with 250 additions and 145 deletions

View file

@ -10,6 +10,7 @@ import React, { useEffect, useState, memo } from 'react'
import { Button, IconButton } from 'src/components/buttons'
import { ReactComponent as CloseIcon } from 'src/styling/icons/action/close/zodiac.svg'
import Tooltip from './Tooltip'
import { TextInput } from './inputs'
import { H4, P } from './typography'
@ -41,13 +42,16 @@ export const DialogTitle = ({ children, onClose }) => {
<div className={classes.wrapper}>
{children}
{onClose && (
<IconButton
size={16}
aria-label="close"
<Tooltip
className={classes.closeButton}
onClick={onClose}>
enableOver
element={
<IconButton size={16} aria-label="close" onClick={onClose}>
<CloseIcon />
</IconButton>
}>
<P>Close</P>
</Tooltip>
)}
</div>
)

View file

@ -1,55 +0,0 @@
import { makeStyles, ClickAwayListener } from '@material-ui/core'
import React, { useState, memo } from 'react'
import Popper from 'src/components/Popper'
import { P } from 'src/components/typography'
import { ReactComponent as HelpIcon } from 'src/styling/icons/action/help/zodiac.svg'
const useStyles = makeStyles({
transparentButton: {
border: 'none',
backgroundColor: 'transparent',
marginTop: 4,
cursor: 'pointer'
},
popoverContent: ({ width }) => ({
width,
padding: [[10, 15]]
})
})
const HelpTooltip = memo(({ children, width }) => {
const classes = useStyles({ width })
const [helpPopperAnchorEl, setHelpPopperAnchorEl] = useState(null)
const handleOpenHelpPopper = event => {
setHelpPopperAnchorEl(helpPopperAnchorEl ? null : event.currentTarget)
}
const handleCloseHelpPopper = () => {
setHelpPopperAnchorEl(null)
}
const helpPopperOpen = Boolean(helpPopperAnchorEl)
return (
<ClickAwayListener onClickAway={handleCloseHelpPopper}>
<button
className={classes.transparentButton}
onClick={handleOpenHelpPopper}>
<HelpIcon />
<Popper
open={helpPopperOpen}
anchorEl={helpPopperAnchorEl}
placement="bottom"
onClose={handleCloseHelpPopper}>
<div className={classes.popoverContent}>
<P>{children}</P>
</div>
</Popper>
</button>
</ClickAwayListener>
)
})
export default HelpTooltip

View file

@ -3,9 +3,11 @@ import classnames from 'classnames'
import React from 'react'
import { IconButton } from 'src/components/buttons'
import { H1, H4 } from 'src/components/typography'
import { H1, H4, P } from 'src/components/typography'
import { ReactComponent as CloseIcon } from 'src/styling/icons/action/close/zodiac.svg'
import Tooltip from './Tooltip'
const styles = {
modal: {
display: 'flex',
@ -74,12 +76,16 @@ const Modal = ({
<Paper className={classnames(classes.wrapper, className)}>
<div className={classes.header}>
{title && <TitleCase className={classes.title}>{title}</TitleCase>}
<IconButton
size={closeSize}
<Tooltip
enableOver
className={classes.button}
onClick={() => handleClose()}>
element={
<IconButton size={closeSize} onClick={() => handleClose()}>
<CloseIcon />
</IconButton>
}>
<P>Close</P>
</Tooltip>
</div>
<div className={classes.content}>{children}</div>
</Paper>

View file

@ -0,0 +1,82 @@
import { makeStyles, ClickAwayListener } from '@material-ui/core'
import classnames from 'classnames'
import React, { useState, memo, cloneElement } from 'react'
import Popper from 'src/components/Popper'
import { ReactComponent as HelpIcon } from 'src/styling/icons/action/help/zodiac.svg'
const useStyles = makeStyles({
transparentButton: {
border: 'none',
backgroundColor: 'transparent',
marginTop: 4,
cursor: 'pointer'
},
preventDefaultTooltip: {
pointerEvents: 'none'
},
popoverContent: ({ width }) => ({
width,
padding: [[10, 15]]
})
})
const Tooltip = memo(
({
enableOver = false,
enableClick = false,
className,
element,
children,
width,
...props
}) => {
const classes = useStyles({ width })
const [helpPopperAnchorEl, setHelpPopperAnchorEl] = useState(null)
const handleOpenHelpPopper = event => {
setHelpPopperAnchorEl(helpPopperAnchorEl ? null : event.currentTarget)
}
const handleCloseHelpPopper = () => {
setHelpPopperAnchorEl(null)
}
const helpPopperOpen = Boolean(helpPopperAnchorEl)
return (
<ClickAwayListener onClickAway={handleCloseHelpPopper}>
<button
type={'button'}
className={classnames(className, classes.transparentButton)}
onPointerOver={event => enableOver && handleOpenHelpPopper(event)}
onClick={
element?.props?.onClick
? element.props.onClick
: event => enableClick && handleOpenHelpPopper(event)
}
{...props}>
{element &&
cloneElement(element, {
className: classnames(
element.props.className,
classes.preventDefaultTooltip
)
})}
{!element && (
<HelpIcon className={classes.preventDefaultTooltip}></HelpIcon>
)}
<Popper
open={helpPopperOpen}
anchorEl={helpPopperAnchorEl}
placement="bottom"
onClose={handleCloseHelpPopper}>
<div className={classes.popoverContent}>{children}</div>
</Popper>
</button>
</ClickAwayListener>
)
}
)
export default Tooltip

View file

@ -2,14 +2,16 @@ import { makeStyles } from '@material-ui/core/styles'
import classnames from 'classnames'
import React, { useState, memo } from 'react'
import { Link } from 'src/components/buttons'
import { Link, IconButton } from 'src/components/buttons'
import { RadioGroup } from 'src/components/inputs'
import { Table, TableBody, TableRow, TableCell } from 'src/components/table'
import BooleanCell from 'src/components/tables/BooleanCell'
import { H4 } from 'src/components/typography'
import { H4, P } from 'src/components/typography'
import { ReactComponent as EditIconDisabled } from 'src/styling/icons/action/edit/disabled.svg'
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg'
import Tooltip from '../Tooltip'
import { booleanPropertiesTableStyles } from './BooleanPropertiesTable.styles'
const useStyles = makeStyles(booleanPropertiesTableStyles)
@ -69,11 +71,25 @@ const BooleanPropertiesTable = memo(
</Link>
</div>
) : (
<div className={classes.transparentButton}>
<button disabled={disabled} onClick={() => setEditing(true)}>
{disabled ? <EditIconDisabled /> : <EditIcon />}
</button>
</div>
<>
{disabled && (
<IconButton disabled>
<EditIconDisabled />
</IconButton>
)}
{!disabled && (
<Tooltip
enableOver
element={
<IconButton onClick={() => setEditing(true)}>
<EditIcon />
</IconButton>
}>
<P>Configure the following properties as desired</P>
</Tooltip>
)}
</>
)}
</div>
<Table className={classes.fillColumn}>

View file

@ -19,7 +19,7 @@ const ActionButton = memo(
<button className={classnames(classNames, className)} {...props}>
{Icon && (
<div className={classes.actionButtonIcon}>
<Icon />
<Icon className={classes.preventDefaultTooltip} />
</div>
)}
{InverseIcon && (

View file

@ -23,6 +23,9 @@ const colors = (color1, color2, color3) => {
}
export default {
preventDefaultTooltip: {
pointerEvents: 'none'
},
actionButton: {
extend: p,
cursor: 'pointer',

View file

@ -7,6 +7,9 @@ import baseButtonStyles from './BaseButton.styles'
const { baseButton, primary } = baseButtonStyles
const styles = {
preventDefaultTooltip: {
pointerEvents: 'none'
},
featureButton: {
extend: baseButton,
width: baseButton.height,
@ -44,7 +47,7 @@ const FeatureButton = memo(
<button className={classnames(classNames, className)} {...props}>
{Icon && (
<div className={classes.buttonIcon}>
<Icon />
<Icon className={classes.preventDefaultTooltip} />
</div>
)}
{InverseIcon && (

View file

@ -7,6 +7,9 @@ import baseButtonStyles from './BaseButton.styles'
const { baseButton, primary } = baseButtonStyles
const styles = {
preventDefaultTooltip: {
pointerEvents: 'none'
},
button: {
extend: baseButton,
borderRadius: baseButton.height / 2,
@ -38,7 +41,7 @@ const SimpleButton = memo(
{...props}>
{Icon && (
<div className={classes.buttonIcon}>
<Icon />
<Icon className={classes.preventDefaultTooltip} />
</div>
)}
{InverseIcon && (

View file

@ -3,10 +3,11 @@ import { Field, useFormikContext } from 'formik'
import * as R from 'ramda'
import React, { useContext } from 'react'
import Tooltip from 'src/components/Tooltip'
import { Link, IconButton } from 'src/components/buttons'
import { Td, Tr } from 'src/components/fake-table/Table'
import { Switch } from 'src/components/inputs'
import { TL2 } from 'src/components/typography'
import { TL2, P } from 'src/components/typography'
import { ReactComponent as DisabledDeleteIcon } from 'src/styling/icons/action/delete/disabled.svg'
import { ReactComponent as DeleteIcon } from 'src/styling/icons/action/delete/enabled.svg'
import { ReactComponent as DisabledEditIcon } from 'src/styling/icons/action/edit/disabled.svg'
@ -54,19 +55,46 @@ const ActionCol = ({ disabled, editing }) => {
)}
{!editing && enableEdit && (
<Td textAlign="center" width={editWidth}>
{!disableEdit && (
<Tooltip
enableOver
element={
<IconButton
disabled={disableEdit}
className={classes.editButton}
onClick={() => onEdit && onEdit(values.id)}>
{disableEdit ? <DisabledEditIcon /> : <EditIcon />}
<EditIcon />
</IconButton>
}>
<P>Modify row contents</P>
</Tooltip>
)}
{disableEdit && (
<IconButton disabled className={classes.editButton}>
<DisabledEditIcon />
</IconButton>
)}
</Td>
)}
{!editing && enableDelete && (
<Td textAlign="center" width={deleteWidth}>
<IconButton disabled={disabled} onClick={() => onDelete(values.id)}>
{disabled ? <DisabledDeleteIcon /> : <DeleteIcon />}
{!disabled && (
<Tooltip
enableOver
element={
<IconButton onClick={() => onDelete(values.id)}>
<DeleteIcon />
</IconButton>
}>
<P>Delete row</P>
</Tooltip>
)}
{disabled && (
<IconButton disabled>
<DisabledDeleteIcon />
</IconButton>
)}
</Td>
)}
{!editing && enableToggle && (

View file

@ -39,7 +39,7 @@ function Select({ label, items, ...props }) {
<label {...getLabelProps()}>{startCase(label)}</label>
<button {...getToggleButtonProps()}>
<span className={classes.selectedItem}>{startCase(selectedItem)}</span>
<Arrowdown />
<Arrowdown className={classes.preventDefaultTooltip}/>
</button>
<ul {...getMenuProps()}>
{isOpen &&

View file

@ -6,6 +6,9 @@ const { p, label1 } = typographyStyles
const WIDTH = 152
export default {
preventDefaultTooltip: {
pointerEvents: 'none'
},
selectedItem: {
width: WIDTH - 41,
display: 'block',

View file

@ -2,6 +2,7 @@ import { makeStyles } from '@material-ui/core'
import classnames from 'classnames'
import React from 'react'
import Tooltip from 'src/components/Tooltip'
import { IconButton } from 'src/components/buttons'
import {
Table,
@ -13,6 +14,8 @@ import {
} from 'src/components/fake-table/Table'
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/white.svg'
import { P } from '../typography'
import styles from './SingleRowTable.styles'
const useStyles = makeStyles(styles)
@ -23,7 +26,8 @@ const SingleRowTable = ({
title,
items,
onEdit,
className
className,
editMessage
}) => {
const classes = useStyles({ width, height })
@ -33,9 +37,15 @@ const SingleRowTable = ({
<THead>
<Th className={classes.head}>
{title}
<Tooltip
enableOver
element={
<IconButton onClick={onEdit} className={classes.button}>
<EditIcon />
</IconButton>
}>
<P>{editMessage}</P>
</Tooltip>
</Th>
</THead>
<TBody>

View file

@ -4,7 +4,7 @@ import gql from 'graphql-tag'
import * as R from 'ramda'
import React, { useState } from 'react'
import HelpTooltip from 'src/components/HelpTooltip'
import Tooltip from 'src/components/Tooltip'
import { NamespacedTable as EditableTable } from 'src/components/editableTable'
import { Switch } from 'src/components/inputs'
import TitleSection from 'src/components/layout/TitleSection'
@ -88,7 +88,7 @@ const CashOut = ({ name: SCREEN_KEY }) => {
<Label2 className={classes.switchLabel}>
{fudgeFactorActive ? 'On' : 'Off'}
</Label2>
<HelpTooltip width={304}>
<Tooltip width={304} enableClick>
<P>
Automatically accept customer deposits as complete if their
received amount is 10 crypto atoms or less.
@ -97,7 +97,7 @@ const CashOut = ({ name: SCREEN_KEY }) => {
(Crypto atoms are the smallest unit in each cryptocurrency. E.g.,
satoshis in Bitcoin, or wei in Ethereum.)
</P>
</HelpTooltip>
</Tooltip>
</div>
</TitleSection>
<EditableTable

View file

@ -1,8 +1,9 @@
import { makeStyles } from '@material-ui/core'
import React from 'react'
import Tooltip from 'src/components/Tooltip'
import { Link, IconButton } from 'src/components/buttons'
import { H4 } from 'src/components/typography'
import { H4, P } from 'src/components/typography'
import { ReactComponent as DisabledEditIcon } from 'src/styling/icons/action/edit/disabled.svg'
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg'
@ -16,14 +17,27 @@ const Header = ({ title, editing, disabled, setEditing }) => {
return (
<div className={classes.header}>
<H4 className={classes.title}>{title}</H4>
{!editing && (
{!editing && !disabled && (
<Tooltip
enableOver
element={
<IconButton
onClick={() => setEditing(true)}
className={classes.button}
disabled={disabled}>
{disabled ? <DisabledEditIcon /> : <EditIcon />}
onClick={() => setEditing(true)}>
<EditIcon />
</IconButton>
}>
<P>Modify value</P>
</Tooltip>
)}
{!editing && disabled && (
<IconButton disabled className={classes.button}>
<DisabledEditIcon />
</IconButton>
)}
{editing && (
<div className={classes.editingButtons}>
<Link color="primary" type="submit">

View file

@ -4,7 +4,7 @@ import gql from 'graphql-tag'
import * as R from 'ramda'
import React, { useState, memo } from 'react'
import Popper from 'src/components/Popper'
import Tooltip from 'src/components/Tooltip'
import { Switch } from 'src/components/inputs'
import { H4, P, Label2 } from 'src/components/typography'
import { ReactComponent as HelpIcon } from 'src/styling/icons/action/help/zodiac.svg'
@ -51,7 +51,6 @@ const Row = memo(({ title, disabled = false, checked, save, label }) => {
})
const CoinATMRadar = memo(() => {
const [helpPopperAnchorEl, setHelpPopperAnchorEl] = useState(null)
const [coinAtmRadarConfig, setCoinAtmRadarConfig] = useState(null)
const classes = useStyles()
@ -82,16 +81,6 @@ const CoinATMRadar = memo(() => {
variables: { config: toNamespace(namespaces.COIN_ATM_RADAR, it) }
})
const handleOpenHelpPopper = event => {
setHelpPopperAnchorEl(helpPopperAnchorEl ? null : event.currentTarget)
}
const handleCloseHelpPopper = () => {
setHelpPopperAnchorEl(null)
}
const helpPopperOpen = Boolean(helpPopperAnchorEl)
if (!coinAtmRadarConfig) return null
return (
@ -99,18 +88,10 @@ const CoinATMRadar = memo(() => {
<div>
<div className={classes.titleWrapper}>
<H4>Coin ATM Radar share settings</H4>
<div className={classes.transparentButton}>
<button onClick={handleOpenHelpPopper}>
<HelpIcon />
<Popper
open={helpPopperOpen}
anchorEl={helpPopperAnchorEl}
placement="bottom"
onClose={handleCloseHelpPopper}>
<div className={classes.popoverContent}>
<Tooltip enableClick width={304} element={<HelpIcon />}>
<P>
For details on configuring this panel, please read the
relevant knowledgebase article{' '}
For details on configuring this panel, please read the relevant
knowledgebase article{' '}
<a
target="_blank"
rel="noopener noreferrer"
@ -119,10 +100,7 @@ const CoinATMRadar = memo(() => {
</a>
.
</P>
</div>
</Popper>
</button>
</div>
</Tooltip>
</div>
<Row
title={'Share information?'}

View file

@ -9,7 +9,8 @@ import React, { useState } from 'react'
import * as Yup from 'yup'
import ErrorMessage from 'src/components/ErrorMessage'
import { Link } from 'src/components/buttons'
import Tooltip from 'src/components/Tooltip'
import { Link, IconButton } from 'src/components/buttons'
import Switch from 'src/components/inputs/base/Switch'
import { TextInput, NumberInput } from 'src/components/inputs/formik'
import {
@ -231,11 +232,15 @@ const ContactInfo = () => {
<div className={classes.header}>
<Info2>Info card</Info2>
{!editing && (
<div className={classes.transparentButton}>
<button onClick={() => setEditing(true)}>
<Tooltip
enableOver
element={
<IconButton onClick={() => setEditing(true)}>
<EditIcon />
</button>
</div>
</IconButton>
}>
<P>Configure info card settings</P>
</Tooltip>
)}
</div>
<Formik
@ -305,7 +310,11 @@ const ContactInfo = () => {
</Formik>
</div>
<div className={classnames(classes.section, classes.infoMessage)}>
<WarningIcon />
<Tooltip width={304} enableOver element={<WarningIcon />}>
Sharing your information with your customers through your machines
allows them to contact you in case there's a problem with a machine in
your network or a transaction.
</Tooltip>
<Label1>
Sharing your information with your customers through your machines
allows them to contact you in case there's a problem with a machine in

View file

@ -63,6 +63,7 @@ const Services = () => {
{R.values(schemas).map(schema => (
<Grid item key={schema.code}>
<SingleRowTable
editMessage={'Configure ' + schema.title}
title={schema.title}
onEdit={() => setEditingSchema(schema)}
items={getItems(schema.code, schema.elements)}