HextaUI

Tooltip

Hover ya da klavye odağında, kısa bir bekleyişten sonra açılan, komşular arasında anında geçen ve kısayolları gösteren kısa bir ipucu.

import {
  IconArrowBackUp,
  IconArrowForwardUp,
  IconShare2,
  IconTrash,
} from "@tabler/icons-react"

import { Button } from "@/components/ui/button"
import { Kbd } from "@/components/ui/kbd"
import { TooltipGroup, TooltipTrigger } from "@/components/ui/tooltip"

export function TooltipDemo() {
  return (
    <TooltipGroup>
      <div className="flex items-center gap-1">
        <TooltipTrigger
          content={
            <>
              Undo
              <Kbd keys="mod+z" />
            </>
          }
          render={<Button variant="ghost" size="icon" aria-label="Undo" />}
        >
          <IconArrowBackUp />
        </TooltipTrigger>
        <TooltipTrigger
          content={
            <>
              Redo
              <Kbd keys="mod+shift+z" />
            </>
          }
          render={<Button variant="ghost" size="icon" aria-label="Redo" />}
        >
          <IconArrowForwardUp />
        </TooltipTrigger>
        <TooltipTrigger
          content="Share"
          render={<Button variant="ghost" size="icon" aria-label="Share" />}
        >
          <IconShare2 />
        </TooltipTrigger>
        <TooltipTrigger
          content="Move to trash"
          render={
            <Button variant="ghost" size="icon" aria-label="Move to trash" />
          }
        >
          <IconTrash />
        </TooltipTrigger>
      </div>
    </TooltipGroup>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/tooltip.json

Bileşeni, HextaUI tema token'larını ve bileşenin bağımlı olduğu tüm HextaUI bileşenlerini ekler.

import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip"
<Tooltip>
  <TooltipTrigger render={<Button variant="ghost" size="icon" aria-label="Undo" />}>
    <IconArrowBackUp />
  </TooltipTrigger>
  <TooltipContent>Undo</TooltipContent>
</Tooltip>

Tooltip, tetikleyicide kısa bir bekleyişten sonra veya tetikleyici klavye odağı alınca hemen açılır. Biri gösterilirken komşuları anında ve animasyonsuz açılır; böylece bir araç çubuğunu taramak her birini beklemek yerine etiket okumak gibi hissedilir.

Bu anlık geçiş, bir TooltipProvider paylaşan tooltip'ler arasında çalışır. Gecikmeyi paylaşmak için uygulamanızı (veya bir araç çubuğunu) birine sarın. Sağlayıcısız bir tooltip aynı varsayılanlarla tek başına yine çalışır.

<TooltipProvider>
  <App />
</TooltipProvider>
TooltipProvider
└── Tooltip
    ├── TooltipTrigger
    └── TooltipContent

TooltipGroup
└── TooltipTrigger

Kenarlar

TooltipContent üzerinde side ayarlayın. Mantıksal taraflar okuma yönünü izler ve yer olmadığında tooltip çevrilir.

import { Button } from "@/components/ui/button"
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip"

const sides = [
  { side: "top", cell: "col-start-2 row-start-1" },
  { side: "inline-start", cell: "col-start-1 row-start-2" },
  { side: "inline-end", cell: "col-start-3 row-start-2" },
  { side: "bottom", cell: "col-start-2 row-start-3" },
] as const

export function TooltipSides() {
  return (
    <TooltipProvider>
      <div className="grid grid-cols-3 grid-rows-3 place-items-center gap-2">
        {sides.map(({ side, cell }) => (
          <div key={side} className={cell}>
            <Tooltip>
              <TooltipTrigger render={<Button variant="outline" />}>
                {side}
              </TooltipTrigger>
              <TooltipContent side={side}>{side}</TooltipContent>
            </Tooltip>
          </div>
        ))}
      </div>
    </TooltipProvider>
  )
}

Okla

arrow, tooltip ekrana sığmak için kaysa bile tetikleyicide kalan bir işaretçi ekler.

import { IconBell } from "@tabler/icons-react"

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

export function TooltipWithArrow() {
  return (
    <Tooltip>
      <TooltipTrigger
        render={
          <Button variant="outline" size="icon" aria-label="Notifications" />
        }
      >
        <IconBell />
      </TooltipTrigger>
      <TooltipContent arrow>Notifications</TooltipContent>
    </Tooltip>
  )
}

Klavye kısayolu

Etiketten sonra bir Kbd veya KbdGroup koyun. Tooltip'in renklerini alır ve sonda durur; Apple cihazlarında ⌘, diğerlerinde Ctrl gösterir.

import { IconDeviceFloppy } from "@tabler/icons-react"

import { Button } from "@/components/ui/button"
import { KbdGroup } from "@/components/ui/kbd"
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@/components/ui/tooltip"

export function TooltipShortcut() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-2">
      <Tooltip>
        <TooltipTrigger render={<Button variant="outline" />}>
          <IconDeviceFloppy data-icon="inline-start" />
          Save
        </TooltipTrigger>
        <TooltipContent>
          Save changes
          <KbdGroup keys="mod+s" size="sm" />
        </TooltipContent>
      </Tooltip>
      <Tooltip>
        <TooltipTrigger render={<Button variant="outline" />}>
          Go to inbox
        </TooltipTrigger>
        <TooltipContent>
          Go to inbox
          <KbdGroup keys="g i" size="sm" />
        </TooltipContent>
      </Tooltip>
    </div>
  )
}

Araç çubuğu

Bir düğmede bekleyin, sonra grup boyunca kayın. Tek bir TooltipProvider altındaki tooltip'ler aralarında gezinirken anında değişir.

import {
  IconBold,
  IconItalic,
  IconLink,
  IconStrikethrough,
  IconUnderline,
} from "@tabler/icons-react"

import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
import { Kbd } from "@/components/ui/kbd"
import { TooltipGroup, TooltipTrigger } from "@/components/ui/tooltip"

const tools = [
  { label: "Bold", keys: "mod+b", icon: IconBold },
  { label: "Italic", keys: "mod+i", icon: IconItalic },
  { label: "Underline", keys: "mod+u", icon: IconUnderline },
  { label: "Strikethrough", keys: "mod+shift+x", icon: IconStrikethrough },
  { label: "Insert link", keys: "mod+k", icon: IconLink },
]

export function TooltipToolbar() {
  return (
    <TooltipGroup side="bottom">
      <ButtonGroup aria-label="Formatting">
        {tools.map(({ label, keys, icon: Icon }) => (
          <TooltipTrigger
            key={label}
            content={
              <>
                {label}
                <Kbd keys={keys} size="sm" />
              </>
            }
            render={<Button variant="outline" size="icon" aria-label={label} />}
          >
            <Icon />
          </TooltipTrigger>
        ))}
      </ButtonGroup>
    </TooltipGroup>
  )
}

Devre dışı

Devre dışı bir düğme yine de focusableWhenDisabled ile nedenini açıklayabilir; bu onu hover edilebilir ve sekme sırasında tutar. Tooltip üzerindeki disabled tooltip'i kapatır.

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

export function TooltipDisabled() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-2">
      <Tooltip>
        <TooltipTrigger render={<Button disabled focusableWhenDisabled />}>
          Publish
        </TooltipTrigger>
        <TooltipContent>Add a title before publishing</TooltipContent>
      </Tooltip>
      <Tooltip disabled>
        <TooltipTrigger render={<Button variant="outline" />}>
          No tooltip
        </TooltipTrigger>
        <TooltipContent>You won’t see this</TooltipContent>
      </Tooltip>
    </div>
  )
}

Uzun içerik

Metin rahat bir genişlikte sarar ve uzun URL'ler dahil ekran kenarını asla aşmaz.

import { IconInfoCircle } from "@tabler/icons-react"

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

export function TooltipLongContent() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-2">
      <Tooltip>
        <TooltipTrigger render={<Button variant="outline" />}>
          <IconInfoCircle data-icon="inline-start" />
          Retention
        </TooltipTrigger>
        <TooltipContent>
          Deleted projects stay in the trash for 30 days. After that they’re
          removed for good, along with their deployments and logs.
        </TooltipContent>
      </Tooltip>
      <Tooltip>
        <TooltipTrigger render={<Button variant="outline" />}>
          Webhook URL
        </TooltipTrigger>
        <TooltipContent>
          https://api.example.com/v1/hooks/8f3a2c91d7e64b0f9a1c5e2d7b8a4f60/deliveries
        </TooltipContent>
      </Tooltip>
    </div>
  )
}

Kontrollü

Tooltip'i kendiniz yönetmek için open ve onOpenChange verin. Neden, onu neyin açtığını veya kapattığını söyler.

"use client"

import * as React from "react"

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

export function TooltipControlled() {
  const [open, setOpen] = React.useState(false)
  const [reason, setReason] = React.useState("none")

  return (
    <div className="flex flex-col items-center gap-3">
      <div className="flex items-center gap-2">
        <Tooltip
          open={open}
          onOpenChange={(next, details) => {
            setOpen(next)
            setReason(details.reason)
          }}
        >
          <TooltipTrigger render={<Button variant="outline" />}>
            Hover or focus me
          </TooltipTrigger>
          <TooltipContent>Controlled tooltip</TooltipContent>
        </Tooltip>
        <Button
          variant="ghost"
          onClick={() => {
            setOpen((value) => !value)
            setReason("button")
          }}
        >
          {open ? "Hide" : "Show"}
        </Button>
      </div>
      <p className="text-sm text-muted-foreground">
        Open: {String(open)} · last reason: {reason}
      </p>
    </div>
  )
}

Bir tooltip, çok tetikleyici

createTooltipHandle ile bir handle oluşturun ve tek bir tooltip paylaşmak için her tetikleyiciden bir payload geçirin.

"use client"

import { Avatar, AvatarFallback } from "@/components/ui/avatar"
import {
  createTooltipHandle,
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip"

type Person = { name: string; initials: string; status: string }

const people: Person[] = [
  { name: "Ada Lovelace", initials: "AL", status: "Online" },
  { name: "Alan Turing", initials: "AT", status: "In a meeting" },
  { name: "Grace Hopper", initials: "GH", status: "Away" },
]

const presence = createTooltipHandle<Person>()

export function TooltipDetached() {
  return (
    <TooltipProvider>
      <div className="flex items-center gap-2">
        {people.map((person) => (
          <TooltipTrigger
            key={person.name}
            handle={presence}
            payload={person}
            aria-label={person.name}
            render={
              <button className="rounded-full outline-none focus-visible:ring-3 focus-visible:ring-focus-ring focus-visible:outline-hidden" />
            }
          >
            <Avatar>
              <AvatarFallback>{person.initials}</AvatarFallback>
            </Avatar>
          </TooltipTrigger>
        ))}
        <Tooltip handle={presence}>
          {({ payload }) => (
            <TooltipContent side="bottom">
              {payload ? `${payload.name} · ${payload.status}` : null}
            </TooltipContent>
          )}
        </Tooltip>
      </div>
    </TooltipProvider>
  )
}

Sağdan sola

dir="rtl" içinde inline-end solda açılır ve kısayol diğer uca geçer.

import { IconBookmark, IconHeart, IconShare2 } from "@tabler/icons-react"

import { Button } from "@/components/ui/button"
import { Kbd } from "@/components/ui/kbd"
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip"

const actions = [
  { label: "أعجبني", icon: IconHeart },
  { label: "حفظ", icon: IconBookmark, keys: "mod+d" },
  { label: "مشاركة", icon: IconShare2 },
]

export function TooltipRtl() {
  return (
    <div dir="rtl">
      <TooltipProvider>
        <div className="flex items-center gap-1">
          {actions.map(({ label, icon: Icon, keys }) => (
            <Tooltip key={label}>
              <TooltipTrigger
                render={
                  <Button variant="ghost" size="icon" aria-label={label} />
                }
              >
                <Icon />
              </TooltipTrigger>
              <TooltipContent side="inline-end" arrow>
                {label}
                {keys && <Kbd keys={keys} size="sm" />}
              </TooltipContent>
            </Tooltip>
          ))}
        </div>
      </TooltipProvider>
    </div>
  )
}
TuşAction
TabTetikleyiciye klavyeden odaklanmak tooltip'ini hemen açar.
EscTooltip'i kapatır ve odağı tetikleyicide tutar.
EnterSpaceTetikleyiciyi etkinleştirir ve tooltip'i kapatır, böylece sonrasında olanı örtmez.
  • Tooltip görsel bir ipucudur, etiket değildir. Yalnızca simgeli tetikleyicilere tooltip metniyle eşleşen bir aria-label verin.
  • Dokunmatikte hiçbir şey açılmaz ve dokunuş yalnızca tetikleyicinin yaptığını yapar. İnsanların ihtiyaç duyduğu hiçbir şeyi tooltip'e koymayın; bunun için popover kullanın.
  • İşaretçi kullanıcıları tooltip'i okumak veya seçmek için kapanmadan üzerine gidebilir.
  • Azaltılmış hareket açıkken tooltip ölçeklenmeden solar.

Base UI tooltip üzerine kuruludur. Her parça sardığı ilkelin prop'larını kabul eder.

PropTürVarsayılan
delayAçılmadan önce bir tetikleyicide beklenecek milisaniye.
number300
closeDelayAyrıldıktan sonra kapanmadan önceki milisaniye.
number0
timeoutBiri kapandıktan sonra sonrakinin ne kadar süre anında açılacağı.
number400
PropTürVarsayılan
open
boolean–
defaultOpen
booleanfalse
onOpenChange
(open, details) => void–
onOpenChangeCompleteAçma ya da kapatma animasyonundan sonra çağrılır.
(open) => void–
disabledTooltip'i kapatır.
booleanfalse
disableHoverablePopupİşaretçi tetikleyiciden ayrılır ayrılmaz kapanır.
booleanfalse
trackCursorAxis
"none" | "x" | "y" | "both""none"
handlecreateTooltipHandle'dan.
TooltipHandle<Payload>–
children
ReactNode | ({ payload }) => ReactNode–
PropTürVarsayılan
delayBu tetikleyici için sağlayıcı gecikmesini geçersiz kılar.
number–
closeDelay
number–
closeOnClick
booleantrue
disabledBu tetikleyicinin tooltip'i açmasını durdurur. Öğe etkin kalır.
booleanfalse
handle
TooltipHandle<Payload>–
payload
Payload–
render
ReactElement | (props, state) => ReactElement<button>
ÖznitelikAçıklama
data-slot="tooltip-trigger"Tetikleyici.
data-popup-openTooltip'i açıkken bulunur.
data-trigger-disabledTetikleyici tooltip'i açamadığında bulunur.
PropTürVarsayılan
side
"top" | "bottom" | "left" | "right" | "inline-start" | "inline-end""top"
align
"start" | "center" | "end""center"
sideOffset
number | (data) => number6, or 8 with arrow
alignOffset
number0
arrow
booleanfalse
collisionPadding
number8
arrowPadding
number8
portalPropscontainer veya keepMounted gibi.
TooltipPortal props–
ÖznitelikAçıklama
data-slot="tooltip-content"Açılır pencere.
data-slot="tooltip-positioner"Açılır pencerenin çevresindeki konumlandırma sarmalayıcısı.
data-sideÇevrildikten sonra açıldığı taraf.
data-alignHizalama.
data-instantAnimasyonsuz açıldığında veya kapandığında "delay", "focus" veya "dismiss".
data-starting-styleAnimasyonla belirirken bulunur.
data-ending-styleAnimasyonla kaybolurken bulunur.
--available-widthTetikleyici ile ekran kenarı arasındaki boşluk.
--transform-originTooltip'in ölçeklendiği nokta.

arrow tarafından sizin için işlenir. Yalnızca kendi içerik parçanızı birleştirirken doğrudan kullanın.

ÖznitelikAçıklama
data-slot="tooltip-arrow"Ok.
data-uncenteredTetikleyicinin merkezini işaret edemediğinde bulunur.

Kullanıldığı bloklar

Tooltip üzerine kurulan bloklar.