Skip to content

Commit

Permalink
Introduce tooltip component (#1)
Browse files Browse the repository at this point in the history
* chore: Install dependencies

* feature: Add new tooltip component

* chore: Add a storybook story for the tooltip component

* fix: postcss preventing some css classes from being applied

* feature: allow tooltip content to be overiden

* chore: Add story for customized tooltip content

* chore: add radix ui tooltip as external in rollupOptions in vite configs

* chore: housekeeping

* chore: format files
  • Loading branch information
DGiannaris authored Sep 4, 2024
1 parent c95bc1e commit 5e707da
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 3 deletions.
8 changes: 5 additions & 3 deletions examples/storybook/postcss.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export const plugins = {
tailwindcss: {},
autoprefixer: {},
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
112 changes: 112 additions & 0 deletions examples/storybook/src/stories/Tooltip.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import type { Meta, StoryObj } from "@storybook/react";
import * as React from "react";
import { Tooltip, type TooltipProps } from "@synopsisapp/symbiosis-ui";

const meta: Meta<typeof Tooltip.Root> = {
title: "Components/Tooltip",
component: Tooltip.Root,
tags: ["autodocs"],
decorators: [
(Story) => (
<div className="flex flex-col gap-4 items-start">
<Story />
</div>
),
],
};

export default meta;

type Story = StoryObj<typeof Tooltip.Root>;

export const Uncontrolled: Story = {
render: (args: TooltipProps["Root"]) => (
<Tooltip.Root {...args}>
<Tooltip.Trigger>
<span>Hover me</span>
</Tooltip.Trigger>
<Tooltip.Content label="Tooltip label" />
</Tooltip.Root>
),
argTypes: {
defaultOpen: {
control: false,
table: {
defaultValue: { summary: "false" },
type: { summary: "boolean" },
},
description:
"The open state of the tooltip when it is initially rendered. Use when you do not need to control its open state.",
required: false,
},
open: {
control: {
type: "boolean",
},
table: {
defaultValue: { summary: "false" },
},
type: "boolean",
description: "The controlled open state of the tooltip. Must be used in conjunction with onOpenChange.",
defaultValue: false,
required: false,
},
onOpenChange: {
table: {
type: { summary: "(open: boolean) => void" },
},
description: "Event handler called when the open state of the tooltip changes.",
control: false,
required: false,
},
},
};

export const Controlled: Story = {
render: (args) => {
const [open, setOpen] = React.useState(false);
return (
<Tooltip.Root {...args} open={open} onOpenChange={setOpen}>
<Tooltip.Trigger>
<span>Hover me</span>
</Tooltip.Trigger>
<Tooltip.Content label="Controlled Tooltip" />
</Tooltip.Root>
);
},
parameters: {
docs: {
source: {
code: `
const ControlledTooltip = () => {
const [open, setOpen] = React.useState(false);
return (
<Tooltip.Root open={open} onOpenChange={setOpen}>
<Tooltip.Trigger>
<span>Hover me</span>
</Tooltip.Trigger>
<Tooltip.Content label="Controlled Tooltip" />
</Tooltip.Root>
);
};
`,
language: "jsx",
type: "code",
},
},
},
};

export const CustomContent: Story = {
render: (args: TooltipProps["Root"]) => (
<Tooltip.Root {...args}>
<Tooltip.Trigger>
<span>Hover me</span>
</Tooltip.Trigger>
<Tooltip.Content className="bg-mainColors-light-200 rounded-none">
<div>Popover content</div>
</Tooltip.Content>
</Tooltip.Root>
),
};
1 change: 1 addition & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"peerDependencies": {
"@radix-ui/react-checkbox": "^1.1.1",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@tailwindcss/typography": "^0.5.13",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
Expand Down
51 changes: 51 additions & 0 deletions packages/ui/src/components/Tooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import { Text } from "../Text";
import { cn } from "../../utils/cn";
import type { TooltipRootProps, TooltipContentProps, TooltipTriggerProps } from "./types";
import { sharedTooltipStyles } from "./styles";

export const TooltipRoot = ({ children, defaultOpen, open, onOpenChange }: TooltipRootProps) => {
return (
<TooltipPrimitive.Provider>
<TooltipPrimitive.Root delayDuration={100} open={open} onOpenChange={onOpenChange} defaultOpen={defaultOpen}>
{children}
</TooltipPrimitive.Root>
</TooltipPrimitive.Provider>
);
};

TooltipRoot.displayName = "Tooltip.Root";

export const TooltipContent = ({ children, label, className }: TooltipContentProps) => {
return (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content sideOffset={5} forceMount className={cn(sharedTooltipStyles, className)}>
{label ? (
<Text variant="body-small-200" noTranslations className="m-0 p-0">
{label}
</Text>
) : (
children
)}
</TooltipPrimitive.Content>
</TooltipPrimitive.Portal>
);
};

TooltipContent.displayName = "Tooltip.Content";

export const TooltipTrigger = ({ children }: TooltipTriggerProps) => {
return (
<TooltipPrimitive.Trigger asChild>
<div>{children}</div>
</TooltipPrimitive.Trigger>
);
};

TooltipTrigger.displayName = "Tooltip.Trigger";

export const Tooltip = {
Root: TooltipRoot,
Content: TooltipContent,
Trigger: TooltipTrigger,
};
10 changes: 10 additions & 0 deletions packages/ui/src/components/Tooltip/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { cn } from "../../utils/cn";

export const sharedTooltipStyles = cn(
"py-2 px-3 rounded-md bg-gray-700 text-white max-w-[200px]",
"will-change-[transform,opacity]",
"data-[state=delayed-open]:data-[side=top]:animate-slide-up-and-fade",
"data-[state=delayed-open]:data-[side=right]:animate-slide-right-and-fade",
"data-[state=delayed-open]:data-[side=left]:animate-slide-left-and-fade",
"data-[state=delayed-open]:data-[side=bottom]:animate-slide-down-and-fade",
);
22 changes: 22 additions & 0 deletions packages/ui/src/components/Tooltip/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export type TooltipRootProps = {
children: React.ReactNode;
defaultOpen?: boolean;
open?: boolean;
onOpenChange?: (open: boolean) => void;
};

export type TooltipContentProps = {
children?: React.ReactNode;
label?: string;
className?: string;
};

export type TooltipTriggerProps = {
children: React.ReactNode;
};

export type TooltipProps = {
Root: TooltipRootProps;
Content: TooltipContentProps;
Trigger: TooltipTriggerProps;
};
4 changes: 4 additions & 0 deletions packages/ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export { Text } from "./components/Text";
export * from "./components/Text/types";
export type { TextProps } from "./components/Text/types";

export { Tooltip } from "./components/Tooltip";
export * from "./components/Tooltip/types";
export type { TooltipProps } from "./components/Tooltip/types";

export * from "./designSystemTokens";

export { shadcnPreset } from "./tailwind/shadcn-preset";
Expand Down
20 changes: 20 additions & 0 deletions packages/ui/src/tailwind/shadcn-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,22 @@ export const shadcnPlugin = plugin(
transform: "translateY(0px)",
},
},
"slide-down-and-fade": {
from: { opacity: "0", transform: "translateY(-5px)" },
to: { opacity: "1", transform: "translateY(0)" },
},
"slide-left-and-fade": {
from: { opacity: "0", transform: "translateX(5px)" },
to: { opacity: "1", transform: "translateX(0)" },
},
"slide-up-and-fade": {
from: { opacity: "0", transform: "translateY(5px)" },
to: { opacity: "1", transform: "translateY(0)" },
},
"slide-right-and-fade": {
from: { opacity: "0", transform: "translateX(-5px)" },
to: { opacity: "1", transform: "translateX(0)" },
},
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
Expand All @@ -161,6 +177,10 @@ export const shadcnPlugin = plugin(
"fade-down": "fade-down 0.5s",
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
"slide-down-and-fade": "slide-down-and-fade 0.2s ease-out",
"slide-up-and-fade": "slide-up-and-fade 0.2s ease-out",
"slide-left-and-fade": "slide-left-and-fade 0.2s ease-out",
"slide-right-and-fade": "slide-right-and-fade 0.2s ease-out",
},
},
},
Expand Down
1 change: 1 addition & 0 deletions packages/ui/vite.config.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default defineConfig({
"@biomejs/biome",
"@radix-ui/react-checkbox",
"@radix-ui/react-slot",
"@radix-ui/react-tooltip",
"@tailwindcss/typography",
"@types/fs-extra",
"@types/node",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default defineConfig({
"@biomejs/biome",
"@radix-ui/react-checkbox",
"@radix-ui/react-slot",
"@radix-ui/react-tooltip",
"@tailwindcss/typography",
"@types/fs-extra",
"@types/node",
Expand Down

0 comments on commit 5e707da

Please sign in to comment.