Skip to content

Commit

Permalink
feat(tooltip): add tooltip component
Browse files Browse the repository at this point in the history
  • Loading branch information
RobinWijnant committed Jan 17, 2021
1 parent 35deca0 commit 26b2962
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 0 deletions.
38 changes: 38 additions & 0 deletions src/components/Tooltip/Tooltip.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
name: Tooltip
menu: Components
route: /tooltip
---

import { Playground, Props } from 'docz';
import { Tooltip, Menu, Button, Trash } from '../../index.ts';

# Popover

A Popover is used to display extra information or actions in a compact way.

## Best practices

- Make sure the correct popover events are covered, depending on the event. (Click, hover, focus, etc...).

## Examples

### Basic usage

<Playground>
<Tooltip content="More info here">
<Button>Hover here</Button>
</Tooltip>
</Playground>

### Bottom placement

<Playground>
<Tooltip placement="bottom" content="This is placed on the bottom">
<Button>Hover here</Button>
</Tooltip>
</Playground>

## API

<Props of={Tooltip} />
19 changes: 19 additions & 0 deletions src/components/Tooltip/Tooltip.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.content {
border-radius: var(--border-radius-small);
background-color: var(--color-neutral-8);
color: var(--color-neutral-1);
padding: 8px 14px;
box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.1);
z-index: 100;
transition: opacity 0.24s;
opacity: 1;
}

.content.enter,
.content.exit {
opacity: 0;
}

.triggerContainer {
display: inline-block;
}
26 changes: 26 additions & 0 deletions src/components/Tooltip/Tooltip.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import { fireEvent, render, waitFor } from '@testing-library/react';

import { Button } from '../../index';
import Tooltip from './Tooltip';

describe('Tooltip', () => {
const component = (
<Tooltip content="This is more info">
<Button>Hover over me</Button>
</Tooltip>
);

test('show on hover', async () => {
const { queryByText, getByText } = render(component);
const button = getByText('Hover over me');

expect(queryByText('This is more info')).toBe(null);

await waitFor(() => {
fireEvent.mouseEnter(button);
});

expect(queryByText('This is more info')).not.toBe(null);
});
});
72 changes: 72 additions & 0 deletions src/components/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React, { useRef, useState } from 'react';
import { usePopper } from 'react-popper';
import { CSSTransition } from 'react-transition-group';
import { Placement } from '@popperjs/core';
import classnames from 'classnames';

import styles from './Tooltip.module.css';

interface Props {
content?: React.ReactNode;
children?: React.ReactNode;
placement?: Placement;
className?: string;
}

const Popover: React.FC<Props> = ({ content, children, placement = 'top', className }: Props) => {
const [isShown, setIsShown] = useState(false);
const divRef = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null);
const [arrowRef, setArrowRef] = useState<HTMLDivElement | null>(null);
const contentClassNames = classnames(styles.content, className);

const hide = () => setIsShown(false);
const show = () => setIsShown(true);

const { styles: popperStyles, attributes } = usePopper(divRef.current, contentRef.current, {
modifiers: [
{
name: 'offset',
options: {
offset: [0, 10],
},
},
{
name: 'arrow',
options: {
element: arrowRef,
},
},
],
placement,
});

return (
<>
<div className={styles.triggerContainer} ref={divRef} onMouseEnter={show} onMouseLeave={hide}>
{children}
</div>

<CSSTransition
unmountOnExit
mountOnEnter
timeout={240}
in={isShown}
classNames={{ enter: styles.enter, exit: styles.exit }}
>
<div
ref={contentRef}
style={popperStyles.popper}
// eslint-disable-next-line react/jsx-props-no-spreading
{...attributes.popper}
className={contentClassNames}
>
<div ref={setArrowRef} style={popperStyles.arrow} className="arrow" />
{content}
</div>
</CSSTransition>
</>
);
};

export default Popover;
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export { default as Table } from './components/Table/Table';
export { default as TextArea } from './components/TextArea/TextArea';
export { default as Popover } from './components/Popover/Popover';
export { default as Menu } from './components/Menu/Menu';
export { default as Tooltip } from './components/Tooltip/Tooltip';
export { default as toaster } from './components/Toaster/Toaster';

export * from 'react-feather';

0 comments on commit 26b2962

Please sign in to comment.