From 39269b5b4a902e2020e4e7f66927918806a8e47a Mon Sep 17 00:00:00 2001 From: "Eduardo C. de Souza" Date: Thu, 18 Feb 2021 11:44:13 -0300 Subject: [PATCH] DEV-15 Add tooltip component (#29) * Init tooltip * Add react-popper * Add title prop and fix children usage * Improve styles and add example * Add visibility toggle through hovering * Add tests * Fix test warnings --- .eslintrc.js | 1 + package.json | 2 + src/components/Tooltip/Tooltip.md | 15 ++++ src/components/Tooltip/Tooltip.stories.tsx | 26 ++++++ src/components/Tooltip/Tooltip.test.tsx | 31 +++++++ src/components/Tooltip/Tooltip.tsx | 96 ++++++++++++++++++++++ src/components/index.ts | 1 + yarn.lock | 2 +- 8 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 src/components/Tooltip/Tooltip.md create mode 100644 src/components/Tooltip/Tooltip.stories.tsx create mode 100644 src/components/Tooltip/Tooltip.test.tsx create mode 100644 src/components/Tooltip/Tooltip.tsx diff --git a/.eslintrc.js b/.eslintrc.js index d6c9ba54..85e518c6 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -44,6 +44,7 @@ module.exports = { ], rules: { "unicorn/no-nested-ternary": "off", + "unicorn/no-null": "off", "react/jsx-uses-react": "off", "react/react-in-jsx-scope": "off", "react/self-closing-comp": ["error"], diff --git a/package.json b/package.json index 59104352..39ce28ba 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,13 @@ }, "homepage": "https://github.com/micromed-dev/herz-ui#readme", "dependencies": { + "@popperjs/core": "^2.6.0", "@theme-ui/presets": "^0.3.5", "downshift": "^6.1.0", "normalize.css": "^8.0.1", "react": "^17.0.1", "react-dom": "^17.0.1", + "react-popper": "^2.2.4", "react-scripts": "4.0.1", "theme-ui": "^0.3.5", "web-vitals": "^0.2.4" diff --git a/src/components/Tooltip/Tooltip.md b/src/components/Tooltip/Tooltip.md new file mode 100644 index 00000000..720f9d26 --- /dev/null +++ b/src/components/Tooltip/Tooltip.md @@ -0,0 +1,15 @@ +#### default example: + +```js + + + +``` + +#### placed on top example: + +```js + + + +``` diff --git a/src/components/Tooltip/Tooltip.stories.tsx b/src/components/Tooltip/Tooltip.stories.tsx new file mode 100644 index 00000000..2e9ac060 --- /dev/null +++ b/src/components/Tooltip/Tooltip.stories.tsx @@ -0,0 +1,26 @@ +import React from "react" +import { Meta, Story } from "@storybook/react/types-6-0" + +import Tooltip, { ITooltipProps } from "./Tooltip" + +export default { + title: "Design System/Tooltip", + component: Tooltip, +} as Meta + +const Template: Story = (props) => + +export const Default = Template.bind({}) + +Default.args = { + children: , + title: "I'm the title", +} + +export const TopPlacement = Template.bind({}) + +TopPlacement.args = { + children: , + title: "I'm the title", + placement: "top", +} diff --git a/src/components/Tooltip/Tooltip.test.tsx b/src/components/Tooltip/Tooltip.test.tsx new file mode 100644 index 00000000..463623c3 --- /dev/null +++ b/src/components/Tooltip/Tooltip.test.tsx @@ -0,0 +1,31 @@ +import "@testing-library/jest-dom/extend-expect" +import React from "react" +import { render, waitFor } from "@testing-library/react" + +import Tooltip from "./Tooltip" + +describe("Tooltip", () => { + it("renders successfully", async () => { + const { getByTestId } = render( + + + + ) + + /** + * Check if the element exists + */ + + await waitFor(() => expect(getByTestId("tooltip")).toBeInTheDocument()) + }) + + it("renders the children succesfully", async () => { + const { getByText } = render( + + + + ) + + await waitFor(() => expect(getByText("hover me")).toBeInTheDocument()) + }) +}) diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx new file mode 100644 index 00000000..0c255fb5 --- /dev/null +++ b/src/components/Tooltip/Tooltip.tsx @@ -0,0 +1,96 @@ +/** @jsxRuntime classic /* +/** @jsx jsx */ +import React, { Fragment, useState } from "react" +import { jsx, Text } from "theme-ui" +import { usePopper } from "react-popper" + +type Placement = + | "auto" + | "auto-start" + | "auto-end" + | "top" + | "top-start" + | "top-end" + | "bottom" + | "bottom-start" + | "bottom-end" + | "right" + | "right-start" + | "right-end" + | "left" + | "left-start" + | "left-end" + +export interface ITooltipProps { + title: string + children: React.ReactChild + placement?: Placement +} + +export default function Tooltip({ + children, + title, + placement = "bottom", +}: ITooltipProps) { + const [popperElement, setPopperElement] = useState( + null + ) + const [ + referenceElement, + setReferenceElement, + ] = useState(null) + const [arrowElement, setArrowElement] = useState(null) + const { styles, attributes } = usePopper(referenceElement, popperElement, { + modifiers: [ + { name: "arrow", options: { element: arrowElement } }, + { name: "offset", options: { offset: [0, 8] } }, + ], + placement, + }) + + return ( + + + {children} + +
+ + {title} + +
+
+ + ) +} diff --git a/src/components/index.ts b/src/components/index.ts index ec2f7a76..e686f2b5 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -2,3 +2,4 @@ export { default as Button } from "./Button/Button" export { default as Paper } from "./Paper/Paper" export { default as DropdownSelect } from "./DropdownSelect/DropdownSelect" export { default as Pagination } from "./Pagination/Pagination" +export { default as Tooltip } from "./Tooltip/Tooltip" diff --git a/yarn.lock b/yarn.lock index ddfff4f5..6d14f3e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1874,7 +1874,7 @@ schema-utils "^2.6.5" source-map "^0.7.3" -"@popperjs/core@^2.4.4", "@popperjs/core@^2.5.4": +"@popperjs/core@^2.4.4", "@popperjs/core@^2.5.4", "@popperjs/core@^2.6.0": version "2.6.0" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.6.0.tgz#f022195afdfc942e088ee2101285a1d31c7d727f" integrity sha512-cPqjjzuFWNK3BSKLm0abspP0sp/IGOli4p5I5fKFAzdS8fvjdOwDCfZqAaIiXd9lPkOWi3SUUfZof3hEb7J/uw==