【NextJs14】NextJs14 と 便利なライブラリ【#16Shadcn-ui Tooltip 】

2023/12/30に公開

【#16Shadcn-ui Tooltip 】

YouTube: https://youtu.be/x_R_iWlFgXE

https://youtu.be/x_R_iWlFgXE

今回はtooltipを使用して
コピーボタンにホバーした際に
ヘルプメッセージが表示されるようにしていきます。

https://ui.shadcn.com/docs/components/tooltip

components/own-tooltip-wrapper.tsx
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip";

interface OwnTooltipWrapperProps {
  children: React.ReactNode;
  label: string;
  side?: "top" | "bottom" | "left" | "right";
  sideOffset?: number;
}

export const OwnTooltipWrapper = ({
  children,
  label,
  side = "right",
  sideOffset = 10,
}: OwnTooltipWrapperProps) => {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger asChild>{children}</TooltipTrigger>
        <TooltipContent side={side} sideOffset={sideOffset}>
          <p>{label}</p>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
};

こちらが作成できたら、
サイドバーのコピーボタンを
上記コンポーネントでラップします。

app/(main)/_components/main-sidebar.tsx
"use client";

import { Copy, Database, Home, Image, ShieldCheck, User } from "lucide-react";
import { Separator } from "@/components/ui/separator";
import { MainSidebarItem } from "./main-sidebar-item";
import { Button } from "@/components/ui/button";
import { useModal } from "@/store/use-modal-store";
import { useEffect } from "react";
import { useEventListener } from "usehooks-ts";
import { OwnTooltipWrapper } from "@/components/own-tooltip-wrapper";

export type MenuItem = {
  id: string;
  href: string;
  pathname: string;
  label: string;
  icon: React.ReactNode;
};

const menuItems = [
  {
    id: "0",
    href: "/home",
    pathname: "/home",
    label: "Home",
    icon: <Home className="h-5 w-5 mr-3 group-hover:text-white" />,
  },
  {
    id: "1",
    href: "/account",
    pathname: "/account",
    label: "Account",
    icon: <User className="h-5 w-5 mr-3 group-hover:text-white" />,
  },
  {
    id: "2",
    href: "/images",
    pathname: "/images",
    label: "Images",
    icon: <Image className="h-5 w-5 mr-3 group-hover:text-white" />,
  },
  {
    id: "3",
    href: "/data",
    pathname: "/data",
    label: "Data",
    icon: <Database className="h-5 w-5 mr-3 group-hover:text-white" />,
  },
  {
    id: "4",
    href: "/protected",
    pathname: "/protected",
    label: "Protected",
    icon: <ShieldCheck className="h-5 w-5 mr-3 group-hover:text-white" />,
  },
];

export const MainSidebar = () => {
  const { onOpen } = useModal();

  const modalOpen = (e: KeyboardEvent) => {
    if (e.key === "c" && (e.metaKey || e.ctrlKey)) {
      e.preventDefault();
      onOpen();
    }
  };

  // useEffect(() => {
  //   window.addEventListener("keydown", modalOpen);

  //   return () => {
  //     window.removeEventListener("keydown", modalOpen);
  //   };
  // }, []);

  useEventListener("keydown", modalOpen);

  return (
    <div className="w-full flex py-4 px-4 flex-col items-center">
      <div className="w-full">
        <h3 className="text-lg">Menu</h3>
      </div>
      <Separator className="bg-slate-400 mt-2" />
      <div className="w-full py-4">
        <ul>
          {menuItems.map((item) => (
            <MainSidebarItem key={item.id} item={item} />
          ))}
        </ul>
      </div>
      <Separator className="bg-slate-400 mt-2" />
      <div className="w-full py-4">
        <OwnTooltipWrapper label="ShortCutKey Ctrl + C">
          <Button
            onClick={onOpen}
            className="w-full flex items-center gap-x-2"
            variant="primary"
          >
            <Copy className="h-4 w-4" />
            Copy Email
          </Button>
        </OwnTooltipWrapper>
      </div>
    </div>
  );
};

Discussion