MC Popover

A floating panel that appears on click or trigger.

Overview

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

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

Preview

Loading...
import { McButton } from '../ui/mc-button';import {  McPopover,  McPopoverContent,  McPopoverDescription,  McPopoverHeader,  McPopoverTitle,  McPopoverTrigger,} from '../ui/mc-popover';const fields = [  { id: 'width', label: 'Width' },  { id: 'height', label: 'Height' },  { id: 'depth', label: 'Depth' },  { id: 'offset', label: 'Offset' },] as const;export default function McPopoverDemo() {  return (    <div className="relative -top-4 py-10">      <McPopover>        <McPopoverTrigger          render={            <McButton variant="secondary" size="md">              Popover            </McButton>          }        />        <McPopoverContent>          <McPopoverHeader className="mb-4">            <McPopoverTitle>Dimensions</McPopoverTitle>            <McPopoverDescription>Set the dimensions for the layer.</McPopoverDescription>          </McPopoverHeader>          <div className="flex flex-col gap-2 pl-4">            {fields.map((field) => (              <div key={field.id} className="flex items-center gap-2">                <label                  htmlFor={field.id}                  className="w-1/2 text-sm font-medium text-card-foreground"                >                  {field.label}                </label>                <input                  id={field.id}                  defaultValue="100%"                  className="h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base text-foreground shadow-sm transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 md:text-sm"                />              </div>            ))}          </div>        </McPopoverContent>      </McPopover>    </div>  );}

Add to Your Project

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

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

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 { Popover as PopoverPrimitive } from '@base-ui/react/popover';import { cn } from '@/lib/utils';function McPopover({ ...props }: PopoverPrimitive.Root.Props) {  return <PopoverPrimitive.Root data-slot="popover" {...props} />;}function McPopoverTrigger({ ...props }: PopoverPrimitive.Trigger.Props) {  return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />;}function McPopoverContent({  className,  align = 'center',  alignOffset = 0,  side = 'bottom',  sideOffset = 23,  ...props}: PopoverPrimitive.Popup.Props &  Pick<PopoverPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>) {  return (    <PopoverPrimitive.Portal>      <PopoverPrimitive.Positioner        align={align}        alignOffset={alignOffset}        side={side}        sideOffset={sideOffset}        className="isolate z-50"      >        <PopoverPrimitive.Popup          data-slot="popover-content"          className={cn(            'z-50 flex h-[268px] w-[276px] origin-(--transform-origin) flex-col gap-[13px] rounded-lg bg-card p-4 text-sm text-card-foreground shadow-sm outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-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-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}        />      </PopoverPrimitive.Positioner>    </PopoverPrimitive.Portal>  );}function McPopoverHeader({ className, ...props }: React.ComponentProps<'div'>) {  return (    <div      data-slot="popover-header"      className={cn('flex flex-col gap-[9px] text-sm', className)}      {...props}    />  );}function McPopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {  return (    <PopoverPrimitive.Title      data-slot="popover-title"      className={cn(        'font-plus-jakarta-sans text-left text-[20px] leading-[30px] font-medium tracking-[0] text-card-foreground',        className      )}      {...props}    />  );}function McPopoverDescription({ className, ...props }: PopoverPrimitive.Description.Props) {  return (    <PopoverPrimitive.Description      data-slot="popover-description"      className={cn(        'font-dm-sans text-left text-[14px] leading-[20px] font-normal tracking-[0] text-muted-foreground',        className      )}      {...props}    />  );}export {  McPopover,  McPopoverContent,  McPopoverDescription,  McPopoverHeader,  McPopoverTitle,  McPopoverTrigger,};
Add the CSS variables

Add the following to your global CSS file:

@layer base {
  :root {
    --z-popover: 50;

    /* Dimensions */
    --popover-width: 276px;
    --popover-height: 268px;

    /* Positioning */
    --popover-top: 59px;
    --popover-left: 22px;

    /* Appearance */
    --popover-radius: var(--radius-gl);
    --popover-bg: var(--Card-Background, #ffffff);
    --popover-shadow: 0px 4px 12px -4px #00000014;
    --popover-opacity: 1;

    /* Spacing */
    --popover-gap: 13px;
    --popover-padding: 16px;
    --popover-header-gap: 0.125rem;

    /* Typography */
    --popover-font-size: 0.875rem;

    /* Animation */
    --popover-duration: 100ms;
  }
}
Adjust import paths

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

Usage

import {
  McPopover,
  McPopoverTrigger,
  McPopoverContent,
  McPopoverHeader,
  McPopoverTitle,
  McPopoverDescription,
} from '@/components/ui/mc-popover';

export default function Example() {
  return (
    <McPopover>
      <McPopoverTrigger>Open</McPopoverTrigger>
      <McPopoverContent>
        <McPopoverHeader>
          <McPopoverTitle>Title</McPopoverTitle>
          <McPopoverDescription>Description goes here.</McPopoverDescription>
        </McPopoverHeader>
      </McPopoverContent>
    </McPopover>
  );
}

Examples

Side Placement

<McPopover>
  <McPopoverTrigger>Top</McPopoverTrigger>
  <McPopoverContent side="top">
    <McPopoverHeader>
      <McPopoverTitle>Top McPopover</McPopoverTitle>
    </McPopoverHeader>
  </McPopoverContent>
</McPopover>

<McPopover>
  <McPopoverTrigger>Right</McPopoverTrigger>
  <McPopoverContent side="right">
    <McPopoverHeader>
      <McPopoverTitle>Right McPopover</McPopoverTitle>
    </McPopoverHeader>
  </McPopoverContent>
</McPopover>

<McPopover>
  <McPopoverTrigger>Bottom</McPopoverTrigger>
  <McPopoverContent side="bottom">
    <McPopoverHeader>
      <McPopoverTitle>Bottom McPopover</McPopoverTitle>
    </McPopoverHeader>
  </McPopoverContent>
</McPopover>

<McPopover>
  <McPopoverTrigger>Left</McPopoverTrigger>
  <McPopoverContent side="left">
    <McPopoverHeader>
      <McPopoverTitle>Left McPopover</McPopoverTitle>
    </McPopoverHeader>
  </McPopoverContent>
</McPopover>

Alignment

<McPopover>
  <McPopoverTrigger>Start</McPopoverTrigger>
  <McPopoverContent align="start">
    <McPopoverHeader>
      <McPopoverTitle>Aligned Start</McPopoverTitle>
    </McPopoverHeader>
  </McPopoverContent>
</McPopover>

<McPopover>
  <McPopoverTrigger>Center</McPopoverTrigger>
  <McPopoverContent align="center">
    <McPopoverHeader>
      <McPopoverTitle>Aligned Center</McPopoverTitle>
    </McPopoverHeader>
  </McPopoverContent>
</McPopover>

<McPopover>
  <McPopoverTrigger>End</McPopoverTrigger>
  <McPopoverContent align="end">
    <McPopoverHeader>
      <McPopoverTitle>Aligned End</McPopoverTitle>
    </McPopoverHeader>
  </McPopoverContent>
</McPopover>

With Custom Content

<McPopover>
  <McPopoverTrigger>Settings</McPopoverTrigger>
  <McPopoverContent>
    <McPopoverHeader>
      <McPopoverTitle>Settings</McPopoverTitle>
      <McPopoverDescription>Manage your preferences.</McPopoverDescription>
    </McPopoverHeader>
    <div className="flex flex-col gap-2">
      <McButton variant="secondary">Save Changes</McButton>
      <McButton variant="tertiary">Reset</McButton>
    </div>
  </McPopoverContent>
</McPopover>

API Reference

McPopover

The root component that manages open/close state.

PropTypeDefaultDescription
defaultOpenbooleanfalseInitial open state (uncontrolled)
openbooleanundefinedControlled open state
onOpenChange(open: boolean) => voidundefinedCallback fired when open state changes

McPopoverTrigger

The element that toggles the popover. Renders a <button> by default.

All props from @base-ui/react/popover Trigger are supported.

McPopoverContent

The floating panel that appears when the popover is open.

PropTypeDefaultDescription
side"top" | "bottom" | "left" | "right""bottom"Preferred side of the trigger to open on
sideOffsetnumber4Distance in px from the trigger
align"start" | "center" | "end""center"Alignment along the trigger axis
alignOffsetnumber0Offset in px along the alignment axis
classNamestringundefinedAdditional CSS classes

All other props from @base-ui/react/popover Popup are supported.

McPopoverHeader

A layout wrapper for the title and description.

PropTypeDefaultDescription
classNamestringundefinedAdditional CSS classes

McPopoverTitle

The accessible title of the popover.

PropTypeDefaultDescription
classNamestringundefinedAdditional CSS classes

McPopoverDescription

The accessible description of the popover.

PropTypeDefaultDescription
classNamestringundefinedAdditional CSS classes

On this page