Bỏ qua đến nội dung

Chú thích

Gợi ý khi di chuột và khi nhấn vào các nút biểu tượng, phím tắt và nhãn bị cắt ngắn — với hiệu ứng viền và bóng theo phong cách tân thô mộc.

import { Button } from "@/components/ui/button"
import {
  Tooltip,

Tooltip là một nhãn ngắn xuất hiện khi di chuột hoặc focus bằng bàn phím, mô tả điều khiển mà nó bao quanh — văn bản bổ sung, không bao giờ là nơi đặt nội dung tương tác. Được xây dựng trên primitive Base UI Tooltip, render qua portal và tự né va chạm, tạo kiểu theo công thức neobrutalist: viền dày, bóng đổ đậm và nền đảo màu để dễ đọc trên mọi phông nền.

Nên dùng khi:

  • Nút chỉ có biểu tượng — gọi tên hành động mà một biểu tượng trơ trọi không nói được: thanh công cụ, hành động theo hàng trong bảng, điều khiển trình soạn thảo.
  • Phím tắt — ghi rõ tổ hợp phím bên cạnh nhãn bằng Kbd, như trong ví dụ bên dưới.
  • Văn bản bị cắt ngắn hoặc quá cô đọng — tên tệp đầy đủ, ô bảng bị cắt, mã trạng thái viết tắt.

Cài đặt

Chạy lệnh sau:

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/tooltip.json
npx shadcn@latest add https://neobrutalism.com/r/base/tooltip.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/tooltip.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/tooltip.json

Thêm TooltipProvider vào gốc của ứng dụng của bạn.

app/layout.tsx
import { TooltipProvider } from "@/components/ui/tooltip"
 
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <TooltipProvider>{children}</TooltipProvider>
      </body>
    </html>
  )
}

Cài đặt các dependency sau:

pnpm add @base-ui/react
npm install @base-ui/react
yarn add @base-ui/react
bun add @base-ui/react

Sao chép và dán đoạn mã sau vào dự án của bạn.

components/ui/tooltip.tsx
"use client"

import * as React from "react"
import { Tooltip as TooltipPrimitive } from "radix-ui"

import { cn } from "@/lib/utils"

function TooltipProvider({
  delayDuration = 0,
  ...props
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
  return (
    <TooltipPrimitive.Provider
      data-slot="tooltip-provider"
      delayDuration={delayDuration}
      {...props}
    />
  )
}

function Tooltip({
  ...props
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
  return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
}

function TooltipTrigger({
  ...props
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
  return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
}

function TooltipContent({
  className,
  sideOffset = 0,
  children,
  ...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
  return (
    <TooltipPrimitive.Portal>
      <TooltipPrimitive.Content
        data-slot="tooltip-content"
        sideOffset={sideOffset}
        className={cn(
          "z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded border-2 bg-foreground px-2 py-1 text-xs text-background shadow-md has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
          className
        )}
        {...props}
      >
        {children}
        <TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" />
      </TooltipPrimitive.Content>
    </TooltipPrimitive.Portal>
  )
}

export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }

Cập nhật các đường dẫn import cho phù hợp với cấu hình dự án của bạn.

Thêm TooltipProvider vào gốc của ứng dụng của bạn.

app/layout.tsx
import { TooltipProvider } from "@/components/ui/tooltip"
 
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <TooltipProvider>{children}</TooltipProvider>
      </body>
    </html>
  )
}

Cách dùng

import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@/components/ui/tooltip"
<Tooltip>
  <TooltipTrigger>Hover</TooltipTrigger>
  <TooltipContent>
    <p>Add to library</p>
  </TooltipContent>
</Tooltip>

Kết hợp

Dùng cách kết hợp sau để xây dựng một Tooltip:

Tooltip
├── TooltipTrigger
└── TooltipContent

Ví dụ

Vị trí

Dùng prop side để thay đổi vị trí của tooltip.

import { Button } from "@/components/ui/button"
import {
  Tooltip,

Với Phím tắt

import { SaveIcon } from "lucide-react"

import { Button } from "@/components/ui/button"

Nút Vô hiệu hóa

Hiển thị một tooltip trên một nút vô hiệu hóa bằng cách bao bọc nó bằng một span.

import { Button } from "@/components/ui/button"
import {
  Tooltip,

RTL

Để bật hỗ trợ RTL trong Neobrutalism, xem hướng dẫn cấu hình RTL.

"use client"

import {

Khả năng truy cập

Tooltip tuân theo mẫu Tooltip của WAI-ARIA: phần popup render với role="tooltip" và primitive trỏ aria-describedby của trigger đến nó, nên trình đọc màn hình đọc gợi ý này như phần mô tả của điều khiển. Bản thân tooltip không bao giờ nhận focus — hãy đặt liên kết hay nút trong một Popover thay thế, và giữ cho trigger vẫn dễ hiểu khi không có tooltip.

Tương tác bàn phím:

PhímHành động
Tab / Shift + TabDi chuyển focus đến trigger — focus sẽ mở tooltip, rời đi sẽ đóng nó
EscapeẨn tooltip trong khi focus vẫn ở trên trigger
Enter / SpaceKích hoạt hành động riêng của trigger — tooltip là phần mô tả, không phải điều khiển

Tham chiếu API

Xem tài liệu Base UI Tooltip.