Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New tooltip + making the DropdownTrigger be a Button #276

Merged
merged 3 commits into from
Jul 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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',
}
466 changes: 465 additions & 1 deletion 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