42

MC Tooltip

A popup that displays information on hover or focus.

Overview

The mc-tooltip is a core component of Micro Club UI. Built on the @base-ui/react tooltip primitive, it combines world-class accessibility with Micro Club's signature styling via Tailwind CSS v4.

As a part of Micro Club UI, this component is designed for instant deployment into your codebase, giving you full ownership of its look and behavior.

Preview

Loading...
import { McButton } from '@/components/ui/mc-button';import { McTooltip, McTooltipContent, McTooltipTrigger } from '@/components/ui/mc-tooltip';export default function McTooltipDemo() {  return (    <McTooltip>      <McTooltipTrigger render={<McButton variant="secondary">Hover</McButton>} />      <McTooltipContent        title="Lovely tooltip title"        description="There are a lot of things you can do in space, and space essentially is unlimited resources."      />    </McTooltip>  );}

Add to Your Project

Deploy the mc-tooltip directly to your components/ui directory:

npx mcoli-ui@latest add mc-tooltip
pnpm dlx mcoli-ui@latest add mc-tooltip
yarn dlx mcoli-ui@latest add mc-tooltip
bunx mcoli-ui@latest add mc-tooltip

Manual Setup

If you prefer manual control:

Install the core dependencies
npm install @base-ui/react
pnpm add @base-ui/react
yarn add @base-ui/react
bun add @base-ui/react
Copy the source code
'use client';import * as React from 'react';import { Tooltip as TooltipPrimitive } from '@base-ui/react/tooltip';import { cn } from '@/lib/utils';function McTooltipProvider({ delay = 0, ...props }: TooltipPrimitive.Provider.Props) {  return <TooltipPrimitive.Provider data-slot="tooltip-provider" delay={delay} {...props} />;}function McTooltip({ ...props }: TooltipPrimitive.Root.Props) {  return <TooltipPrimitive.Root data-slot="tooltip" {...props} />;}function McTooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {  return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;}function McTooltipContent({  className,  side = 'top',  sideOffset = 16,  align = 'center',  alignOffset = 0,  arrow = true,  title,  description,  desc,  children,  ...props}: Omit<TooltipPrimitive.Popup.Props, 'title'> &  Pick<TooltipPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'> & {    /** Show the arrow pointing at the trigger. */    arrow?: boolean;    /** Bold first line of the tooltip. */    title?: React.ReactNode;    /** Body text below the title. */    description?: React.ReactNode;    /** @deprecated Use `description`. */    desc?: React.ReactNode;  }) {  const body = description ?? desc;  return (    <TooltipPrimitive.Portal>      <TooltipPrimitive.Positioner        align={align}        alignOffset={alignOffset}        side={side}        sideOffset={sideOffset}        className="isolate z-50"      >        <TooltipPrimitive.Popup          data-slot="tooltip-content"          className={cn(            'relative z-50 flex w-fit max-w-58 origin-(--transform-origin) flex-col gap-2 rounded-sm bg-card p-4 text-xs text-card-foreground drop-shadow-[0_1px_4px_var(--border)]',            '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',            'data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2',            className          )}          {...props}        >          {title && <p className="font-semibold text-foreground">{title}</p>}          {body && <p className="leading-4.5 text-muted-foreground">{body}</p>}          {children}          {arrow && (            // The arrow box is 20×15 and points up; it is rotated per side and pushed past the            // popup edge so 14px sticks out (1px overlaps the popup to avoid a seam). Rotated            // boxes need 2.5px more because the box is wider than it is tall. The popup's            // drop-shadow follows the combined outline, so the arrow is shadowed too.            <TooltipPrimitive.Arrow              className={cn(                'flex h-[15px] w-5',                'data-[side=bottom]:-top-3.5',                'data-[side=top]:-bottom-3.5 data-[side=top]:rotate-180',                'data-[side=left]:-right-[16.5px] data-[side=left]:rotate-90 data-[side=inline-start]:-right-[16.5px] data-[side=inline-start]:rotate-90',                'data-[side=right]:-left-[16.5px] data-[side=right]:-rotate-90 data-[side=inline-end]:-left-[16.5px] data-[side=inline-end]:-rotate-90'              )}            >              <svg width="20" height="15" viewBox="0 0 20 15" aria-hidden className="fill-card">                <path d="M0 15L8.5 2.25Q10 0 11.5 2.25L20 15Z" />              </svg>            </TooltipPrimitive.Arrow>          )}        </TooltipPrimitive.Popup>      </TooltipPrimitive.Positioner>    </TooltipPrimitive.Portal>  );}export { McTooltip, McTooltipTrigger, McTooltipContent, McTooltipProvider };
Adjust import paths

Ensure your @/lib/utils or equivalent classname helper is correctly imported.

Usage

import {
  McTooltip,
  McTooltipTrigger,
  McTooltipContent,
  McTooltipProvider,
} from '@/components/ui/mc-tooltip';

export default function Example() {
  return (
    <McTooltipProvider>
      <McTooltip>
        <McTooltipTrigger>Hover me</McTooltipTrigger>
        <McTooltipContent title="Tooltip title" description="This is a description." />
      </McTooltip>
    </McTooltipProvider>
  );
}

McTooltipTrigger renders a <button>. To use your own element, pass it through render instead of nesting it:

<McTooltipTrigger render={<McButton variant="secondary">Hover me</McButton>} />

Tooltip content isn't announced by screen readers. Give icon-only triggers an aria-label.

Examples

Positioning

<McTooltip>
  <McTooltipTrigger>Bottom</McTooltipTrigger>
  <McTooltipContent side="bottom" align="start" title="Bottom start" />
</McTooltip>

Without Arrow

<McTooltip>
  <McTooltipTrigger>Hover me</McTooltipTrigger>
  <McTooltipContent arrow={false} title="Tooltip title" description="No arrow." />
</McTooltip>

With Custom Content

Children render below the title and description.

<McTooltip>
  <McTooltipTrigger>Custom</McTooltipTrigger>
  <McTooltipContent title="Shortcuts">
    <p>
      Press <kbd>⌘K</kbd> to search.
    </p>
  </McTooltipContent>
</McTooltip>

API Reference

McTooltipProvider Props

PropTypeDefaultDescription
delaynumber0Delay in ms before showing tooltip

All other props from @base-ui/react/tooltip/provider are supported.

McTooltip Props

All props from @base-ui/react/tooltip/root are supported.

McTooltipTrigger Props

All props from @base-ui/react/tooltip/trigger are supported.

McTooltipContent Props

PropTypeDefaultDescription
classNamestringundefinedAdditional CSS classes
side"top" | "bottom" | "left" | "right""top"The side of the trigger to position the tooltip
sideOffsetnumber16The offset from the trigger
align"start" | "center" | "end""center"The alignment of the tooltip
alignOffsetnumber0The offset for alignment
arrowbooleantrueShow the arrow pointing at the trigger
titleReactNodeundefinedThe title text of the tooltip
descriptionReactNodeundefinedThe description text of the tooltip
descReactNodeundefinedDeprecated alias for description
childrenReactNodeundefinedCustom content for the tooltip

All other props from @base-ui/react/tooltip/popup and @base-ui/react/tooltip/positioner are supported.

On this page