diff --git a/packages/react/components/Tooltip.tsx b/packages/react/components/Tooltip.tsx new file mode 100644 index 0000000..11d6887 --- /dev/null +++ b/packages/react/components/Tooltip.tsx @@ -0,0 +1,93 @@ +import React, { useState } from "react"; +import { VariantProps, vcn } from "../shared"; + +interface TooltipContextBody { + position: "top" | "bottom" | "left" | "right"; +} + +const Tooltip$Context$InitialState: TooltipContextBody = { + position: "top", +}; +const Tooltip$Context = React.createContext< + [TooltipContextBody, React.Dispatch>] +>([Tooltip$Context$InitialState, () => {}]); + +const [Tooltip$Variant, Tooltip$resolveVariantProps] = vcn({ + base: "w-fit h-fit relative group/tooltip", + variants: { + position: { + top: "", + bottom: "", + left: "", + right: "", + }, + }, + defaults: { + position: "top", + }, +}); + +interface TooltipProps + extends React.HTMLAttributes, + VariantProps {} + +const Tooltip = React.forwardRef((props, ref) => { + const [variantProps, rest] = Tooltip$resolveVariantProps(props); + const contextState = useState({ + ...Tooltip$Context$InitialState, + ...variantProps, + }); + + return ( + +
+ + ); +}); + +const [TooltipContent$Variant, TooltipContent$resolveVariantProps] = vcn({ + base: "absolute py-1 px-3 bg-white dark:bg-black border border-black/10 dark:border-white/20 [--tooltip-offset:2px] opacity-0 group-hover/tooltip:opacity-100 pointer-events-none group-hover/tooltip:pointer-events-auto transition-all rounded-md", + variants: { + position: { + top: "bottom-[calc(100%+var(--tooltip-offset))] left-1/2 -translate-x-1/2 group-hover/tooltip:translate-y-0 translate-y-[10px]", + bottom: + "top-[calc(100%+var(--tooltip-offset))] left-1/2 -translate-x-1/2 group-hover/tooltip:translate-y-0 translate-y-[-10px]", + left: "right-[calc(100%+var(--tooltip-offset))] top-1/2 -translate-y-1/2 group-hover/tooltip:translate-x-0 translate-x-[10px]", + right: + "left-[calc(100%+var(--tooltip-offset))] top-1/2 -translate-y-1/2 group-hover/tooltip:translate-x-0 translate-x-[-10px]", + }, + offset: { + sm: "[--tooltip-offset:2px]", + md: "[--tooltip-offset:4px]", + lg: "[--tooltip-offset:8px]", + }, + }, + defaults: { + position: "top", + offset: "md", + }, +}); + +interface TooltipContentProps + extends React.HTMLAttributes, + Omit, "position"> {} + +const TooltipContent = React.forwardRef( + (props, ref) => { + const [variantProps, rest] = TooltipContent$resolveVariantProps(props); + const [contextState] = React.useContext(Tooltip$Context); + + return ( +
+ ); + } +); + +export { Tooltip, TooltipContent }; diff --git a/packages/react/stories/Tooltip.stories.tsx b/packages/react/stories/Tooltip.stories.tsx new file mode 100644 index 0000000..3bc4356 --- /dev/null +++ b/packages/react/stories/Tooltip.stories.tsx @@ -0,0 +1,65 @@ +import { Button } from "../components/Button"; +import { Tooltip, TooltipContent } from "../components/Tooltip"; + +export default { + title: "React/Tooltip", + component: Tooltip, + parameters: { + layout: "centered", + }, +}; + +export const Default = () => { + return ( + + +

Hello World!

+
+ +
+ ); +}; + +export const Top = () => { + return ( + + +

Hello World!

+
+ +
+ ); +}; + +export const Bottom = () => { + return ( + + +

Hello World!

+
+ +
+ ); +}; + +export const Left = () => { + return ( + + +

Hello World!

+
+ +
+ ); +}; + +export const Right = () => { + return ( + + +

Hello World!

+
+ +
+ ); +};