Skip to content

Commit

Permalink
New tooltip + making the DropdownTrigger be a Button (#276)
Browse files Browse the repository at this point in the history
* New tooltip + making the DropdownTrigger be a Button
* Add z-index to tooltip to stay above our own popover
* Enable having a small delay before showing or hiding a tooltip
  • Loading branch information
gnapse authored Jul 30, 2020
1 parent 80f86c4 commit b84c7f8
Show file tree
Hide file tree
Showing 26 changed files with 958 additions and 761 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"webpack.config.*"
],
"rules": {
"jest/expect-expect": "off",
"prettier/prettier": "error",
"linebreak-style": ["error", "unix"],
"react/no-did-mount-set-state": "error",
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ module.exports = {
'\\.(css|less)$': '<rootDir>/src/__mocks__/styleMock.ts',
},
testURL: 'http://localhost',
testEnvironment: 'jest-environment-jsdom-sixteen',
}
464 changes: 464 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"eslint-plugin-react": "^7.19.0",
"husky": "^4.2.5",
"jest": "^24.7.1",
"jest-environment-jsdom-sixteen": "^1.0.3",
"less": "^3.8.1",
"less-loader": "^4.1.0",
"lint-staged": "^10.2.11",
Expand Down Expand Up @@ -118,5 +119,7 @@
"typescript": "^3.9.2",
"webpack": "^4.43.0"
},
"dependencies": {}
"dependencies": {
"reakit": "^1.1.2"
}
}
10 changes: 5 additions & 5 deletions src/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import React from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
import Tooltip from './Tooltip'
import { Tooltip } from './Tooltip'
import './styles/button.less'

type NativeButtonProps = React.DetailedHTMLProps<
React.ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
>

type Props = Omit<NativeButtonProps, 'title'> & {
export type ButtonProps = Omit<NativeButtonProps, 'title' | 'ref'> & {
/**
* Loading style. When true it disables the button, but it also adds a visual indication of
* some in-progress operation going on.
Expand All @@ -31,7 +31,7 @@ type Props = Omit<NativeButtonProps, 'title'> & {
tooltip?: React.ReactNode
}

const Button = React.forwardRef<HTMLButtonElement, Props>(function Button(
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(function Button(
{
type = 'button',
variant,
Expand Down Expand Up @@ -66,7 +66,7 @@ const Button = React.forwardRef<HTMLButtonElement, Props>(function Button(
</button>
)

return tooltip ? <Tooltip text={tooltip}>{button}</Tooltip> : button
return tooltip ? <Tooltip content={tooltip}>{button}</Tooltip> : button
})

Button.displayName = 'Button'
Expand All @@ -75,7 +75,7 @@ Button.propTypes = {
loading: PropTypes.bool,
variant: PropTypes.oneOf(['primary', 'secondary', 'danger', 'link']),
size: PropTypes.oneOf(['default', 'small', 'large']),
tooltip: PropTypes.string,
tooltip: PropTypes.node,
}

Button.defaultProps = {
Expand Down
4 changes: 2 additions & 2 deletions src/components/ColorPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React from 'react'
import classnames from 'classnames'

import Dropdown from './Dropdown'
import Tooltip from './Tooltip'
import { Tooltip } from './Tooltip'

type NamedColor = { name: string; color: string }

Expand Down Expand Up @@ -106,7 +106,7 @@ function ColorItem({ color, colorIndex, isActive, onClick, tooltip }: ColorItemP
</span>
)

return tooltip ? <Tooltip text={tooltip}>{item}</Tooltip> : item
return tooltip ? <Tooltip content={tooltip}>{item}</Tooltip> : item
}
ColorItem.displayName = 'ColorItem'

Expand Down
94 changes: 43 additions & 51 deletions src/components/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import './styles/dropdown.less'
import React from 'react'
import ReactDOM from 'react-dom'
import classNames from 'classnames'
import Button from './Button'

type BoxProps = {
onShowBody?: () => void
Expand Down Expand Up @@ -167,38 +168,41 @@ class Box extends React.Component<React.PropsWithChildren<BoxProps>, BoxState> {
)
}
}
Box.displayName = 'Dropdown.Box'

type TriggerProps = {
onClick?: (event?: React.MouseEvent) => void
}
Box.displayName = 'Dropdown.Box'

class Trigger extends React.Component<TriggerProps> {
public static displayName: string
type NativeButtonProps = React.DetailedHTMLProps<
React.ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
>

constructor(props: TriggerProps, context: React.Context<unknown>) {
super(props, context)
this._onClick = this._onClick.bind(this)
}
type TriggerProps = Omit<NativeButtonProps, 'title'> & {
tooltip?: React.ReactNode
}

_onClick(event: React.MouseEvent) {
const Trigger = React.forwardRef<HTMLButtonElement, TriggerProps>(function Trigger(
{ children, onClick, tooltip, className, ...props },
ref,
) {
function handleClick(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
event.preventDefault()
event.stopPropagation()
if (this.props.onClick) this.props.onClick(event)
if (onClick) onClick(event)
}

render() {
const style = {
display: 'block',
}
return (
<Button
{...props}
className={classNames('trigger', className)}
onClick={handleClick}
tooltip={tooltip}
ref={ref}
>
{children}
</Button>
)
})

return (
<div style={style} className="trigger" onClick={this._onClick}>
{this.props.children}
</div>
)
}
}
Trigger.displayName = 'Dropdown.Trigger'

type BodyProps = {
Expand All @@ -208,38 +212,26 @@ type BodyProps = {
right?: boolean
}

class Body extends React.Component<React.PropsWithChildren<BodyProps>> {
public static displayName: string

render() {
const style: React.CSSProperties = {
position: 'absolute',
right: 0,
top: 0,
}
function Body({ top, right, children, setPosition }: BodyProps) {
const style: React.CSSProperties = { position: 'absolute', right: 0, top: 0 }

if (this.props.top) {
style.top = 'auto'
style.bottom = 0
}

if (this.props.right) {
style.right = 'auto'
style.left = 0
}
if (top) {
style.top = 'auto'
style.bottom = 0
}

return (
<div
ref={this.props.setPosition}
style={style}
className="body"
id="reactist-dropdown-body"
>
{this.props.children}
</div>
)
if (right) {
style.right = 'auto'
style.left = 0
}

return (
<div ref={setPosition} style={style} className="body" id="reactist-dropdown-body">
{children}
</div>
)
}

Body.displayName = 'Dropdown.Body'

const Dropdown = {
Expand Down
4 changes: 2 additions & 2 deletions src/components/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import './styles/icon.less'
import React from 'react'
import classNames from 'classnames'

import Tooltip from './Tooltip'
import { Tooltip } from './Tooltip'
import ThreeDotsIcon from './icons/ThreeDotsIcon.svg'

type Props = {
Expand Down Expand Up @@ -87,7 +87,7 @@ class Icon extends React.Component<Props, State> {
</a>
/* eslint-enable jsx-a11y/anchor-is-valid */
)
return tooltip ? <Tooltip text={tooltip}>{component}</Tooltip> : component
return tooltip ? <Tooltip content={tooltip}>{component}</Tooltip> : component
}
}
Icon.displayName = 'Icon'
Expand Down
14 changes: 12 additions & 2 deletions src/components/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,16 +221,26 @@ class Popover extends React.Component<Props> {
const popoverClass = position ? this._getClassNameForPosition(position) : ''
const popoverContentClass = classNames('reactist_popover__content', popoverClassName)
const wrapperClass = classNames('reactist_popover__wrapper', wrapperClassName)
const triggerElement = React.Children.only<React.ReactElement>(
trigger as React.ReactElement,
)

function handleTriggerClick(event: React.SyntheticEvent) {
// @ts-expect-error This is temporary while we revisit the Popover interface
if (onClick) onClick(event)
if (typeof triggerElement.props.onClick === 'function') {
triggerElement.props.onClick(event)
}
}

return (
<span
className={wrapperClass}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onClick={onClick}
ref={this._updateWrapperRef}
>
{trigger}
{React.cloneElement(triggerElement, { onClick: handleTriggerClick })}
<span className={popoverClass} ref={this._updatePopoverRef}>
{this.props.visible ? (
<span className={popoverContentClass}>
Expand Down
7 changes: 3 additions & 4 deletions src/components/Time.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import './styles/time.less'

import React from 'react'

import Tooltip from './Tooltip'
import { Tooltip } from './Tooltip'
import TimeUtils, { TimeConfig } from './utils/TimeUtils'

const DELAY = 60000
Expand Down Expand Up @@ -122,14 +122,13 @@ class Time extends React.Component<Props, State> {
>
{this.props.tooltipOnHover ? (
<Tooltip
text={
content={
this.props.tooltip ||
(this.props.time &&
TimeUtils.formatTimeLong(this.props.time, this.props.config))
}
delayShow={500}
>
{timeComponent}
<span>{timeComponent}</span>
</Tooltip>
) : (
timeComponent
Expand Down
Loading

0 comments on commit b84c7f8

Please sign in to comment.