Skip to content

Commit

Permalink
Merge pull request #82 from abusix/pla-930-migrate-from-abusix-ui-to-…
Browse files Browse the repository at this point in the history
…hailstorm-tooltip

feat(Tooltip): add tooltip component
  • Loading branch information
pallendes authored Dec 29, 2023
2 parents 63c163f + 4e456d3 commit f558bb7
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 2 deletions.
5 changes: 3 additions & 2 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ export { IconButton } from "./icon-button";
export { InlineAlert } from "./inline-alert";
export { LastChangedInfo } from "./last-changed-info";
export { Menu } from "./menu";
export { Navigation } from "./navigation";
export { Page } from "./page";
export { Panel } from "./panel";
export { Section } from "./section";
export { Sidebar } from "./sidebar";
export { SidebarContainer } from "./sidebar-container";
export { Sidesheet } from "./sidesheet";
export { Skeleton } from "./skeleton";
export { Spinner } from "./spinner";
export { SpinnerOverlay } from "./spinner-overlay";
export { Tab } from "./tab";
Expand All @@ -24,6 +26,5 @@ export { TableVirtualized, TableVirtualizedProps } from "./table-virtualized";
export { Tag } from "./tag";
export { Toast } from "./toast";
export { Toggle } from "./toggle";
export { Tooltip } from "./tooltip";
export { TopBar } from "./top-bar";
export { Skeleton } from "./skeleton";
export { Navigation } from "./navigation";
1 change: 1 addition & 0 deletions src/components/tooltip/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Tooltip } from "./tooltip";
58 changes: 58 additions & 0 deletions src/components/tooltip/tooltip.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { Meta, StoryObj } from "@storybook/react";
import React from "react";
import { getStoryDescription } from "../../util/storybook-utils";
import { Tooltip } from "./tooltip";
import { Button } from "../button";

const meta: Meta<typeof Tooltip> = {
title: "Tooltip",
component: Tooltip,
parameters: {
...getStoryDescription(
"Tooltip component. By default displays a tooltip on hover, but it can be controlled with the `open` prop as well."
),
},
args: {
position: "right",
title: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
className: "",
},
};

export default meta;

type Story = StoryObj<typeof Tooltip>;

export const UncontrolledTooltip: Story = {
render: (args) => (
<Tooltip {...args}>
<div className="rounded border border-neutral-50 p-2 text-sm hover:bg-neutral-100">
Hover to toggle
</div>
</Tooltip>
),
};

const ControlledTooltipExample = () => {
const [open, setOpen] = React.useState(false);

return (
<Tooltip
position="right"
title="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
open={open}
>
<Button
variant="minimal"
className="rounded border p-2 text-sm hover:bg-neutral-100"
onClick={() => setOpen(!open)}
>
Click to toggle
</Button>
</Tooltip>
);
};

export const ControlledTooltip: Story = {
render: () => <ControlledTooltipExample />,
};
66 changes: 66 additions & 0 deletions src/components/tooltip/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Transition } from "@headlessui/react";
import { Placement } from "@popperjs/core";
import React, { useEffect, useState } from "react";
import { usePopper } from "react-popper";
import { classNames } from "../../util/class-names";

interface TooltipProps {
children: React.ReactNode;
title: React.ReactNode;
position?: Placement;
className?: string;
open?: boolean;
onClose?: () => void;
}

export const Tooltip = ({ children, title, position = "right", className, open }: TooltipProps) => {
const [referenceElement, setReferenceElement] = useState<HTMLDivElement>();
const [popperElement, setPopperElement] = useState<HTMLDivElement>();
const [show, setShow] = useState(false);
const [isControlled, setIsControlled] = useState(false);

const { styles, attributes } = usePopper(referenceElement, popperElement, {
placement: position,
modifiers: [{ name: "offset", options: { offset: [0, 8] } }],
});

useEffect(() => {
if (open !== undefined) {
setIsControlled(true);
setShow(open);
}
}, [open]);

return (
<div>
<div
ref={(el) => el && setReferenceElement(el)}
onMouseEnter={() => !isControlled && setShow(true)}
onMouseLeave={() => !isControlled && setShow(false)}
>
{children}
</div>
<Transition
show={show}
enter="transition-opacity duration-75"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity duration-150"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div
ref={(el) => el && setPopperElement(el)}
className={classNames(
"rounded-lg bg-neutral-900 p-4 px-4 py-2 text-xs text-neutral-0 shadow",
className
)}
style={styles.popper}
{...attributes.popper}
>
{title}
</div>
</Transition>
</div>
);
};

0 comments on commit f558bb7

Please sign in to comment.