Tooltip primitive wrappers
import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
...import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
export default function TooltipDemoExample() {
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild><Button variant="outline">Hover</Button></TooltipTrigger>
<TooltipContent><p>Add to library</p></TooltipContent>
</Tooltip>
</TooltipProvider>
)
}
Installation
npx @fictjs/shadcn@latest add tooltipInstall the runtime dependencies:
npm install @fictjs/radix-uiCopy the Fict shadcn component into your project.
Source
components/ui/tooltip.tsx
src/components/ui/tooltip.tsx
import { Tooltip as TooltipPrimitive } from '@fictjs/radix-ui'
import { cn } from '@/lib/cn'
export const TooltipProvider = TooltipPrimitive.Provider
export const Tooltip = TooltipPrimitive.Root
export const TooltipTrigger = TooltipPrimitive.Trigger
export const TooltipTriggerEl = TooltipPrimitive.Trigger
type TooltipContentProps = {
class?: string
children?: unknown
[key: string]: unknown
}
export function TooltipContent(props: TooltipContentProps) {
const { class: className, sideOffset = 4, ...rest } = props
return (
<TooltipPrimitive.Content
sideOffset={sideOffset}
class={cn('z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground', className)}
{...rest}
/>
)
}
Usage
Examples
Sides
import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
...import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
const sides = ['left', 'top', 'bottom', 'right'] as const
export default function TooltipSidesExample() {
return (
<TooltipProvider>
<div class="flex flex-wrap gap-2">
{sides.map(side => (
<Tooltip>
<TooltipTrigger asChild><Button variant="outline" class="w-fit capitalize">{side}</Button></TooltipTrigger>
<TooltipContent side={side}><p>Add to library</p></TooltipContent>
</Tooltip>
))}
</div>
</TooltipProvider>
)
}
Keyboard
import { Button } from '@/components/ui/button'
import { Kbd } from '@/components/ui/kbd'
...import { Button } from '@/components/ui/button'
import { Kbd } from '@/components/ui/kbd'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
function SaveIcon() {
return <svg aria-hidden="true" viewBox="0 0 24 24"><path d="M15.2 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V8.8zM17 21v-8H7v8M7 3v5h8" /></svg>
}
export default function TooltipKeyboardExample() {
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild><Button variant="outline" size="icon-sm" aria-label="Save changes"><SaveIcon /></Button></TooltipTrigger>
<TooltipContent class="pr-1.5"><div class="flex items-center gap-2">Save Changes <Kbd>S</Kbd></div></TooltipContent>
</Tooltip>
</TooltipProvider>
)
}
Disabled
import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
...import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
export default function TooltipDisabledExample() {
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild><span class="inline-block w-fit"><Button variant="outline" disabled>Disabled</Button></span></TooltipTrigger>
<TooltipContent><p>This feature is currently unavailable</p></TooltipContent>
</Tooltip>
</TooltipProvider>
)
}
Rtl
import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
...import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
const translations = {
ar: { dir: 'rtl', content: 'إضافة إلى المكتبة', left: 'يسار', top: 'أعلى', bottom: 'أسفل', right: 'يمين' },
he: { dir: 'rtl', content: 'הוסף לספרייה', left: 'שמאל', top: 'למעלה', bottom: 'למטה', right: 'ימין' },
en: { dir: 'ltr', content: 'Add to library', left: 'Left', top: 'Top', bottom: 'Bottom', right: 'Right' },
} as const
const sides = ['left', 'top', 'bottom', 'right'] as const
export default function TooltipRtlExample() {
let language = $state<keyof typeof translations>('ar')
const t = translations[language]
return (
<div>
<select aria-label="Preview language" value={language} onChange={event => language = event.currentTarget.value as keyof typeof translations}>
<option value="ar">Arabic (العربية)</option><option value="he">Hebrew (עברית)</option><option value="en">English</option>
</select>
<TooltipProvider dir={t.dir}>
<div class="flex flex-wrap gap-2" dir={t.dir}>
{sides.map(side => (
<Tooltip>
<TooltipTrigger asChild><Button variant="outline" class="w-fit capitalize">{t[side]}</Button></TooltipTrigger>
<TooltipContent side={side}>{t.content}</TooltipContent>
</Tooltip>
))}
</div>
</TooltipProvider>
</div>
)
}