Popin

PreviousNext

A modal dialog component that displays content in a centered overlay with smooth animations and backdrop support

'use client';

import { useState } from 'react';
import { Popin } from '@/ui/Popin';
import { Button } from '@/ui/buttons/Button';

export function PopinDemo() {
  const [isVisible, setIsVisible] = useState(false);

  return (
    <div>
      <Button onClick={() => setIsVisible(true)}>Open Popin</Button>
      <Popin
        isVisible={isVisible}
        onClose={() => setIsVisible(false)}
        title="Welcome!"
        closeLabel="Close"
      >
        <p>
          This is a modal dialog that overlays the page content. Click the backdrop or the close
          button to dismiss it.
        </p>
      </Popin>
    </div>
  );
}

Installation

npx shadcn@latest add https://develop.trident-ui.pro.clubmed/r/popin.json

Usage

'use client';
 
import { useState } from 'react';
import { Popin } from '@/docs/lib/ui/popin';
import { Button } from '@/docs/lib/ui/Button';
 
export function Component() {
  const [isVisible, setIsVisible] = useState(false);
 
  return (
    <div>
      <Button onClick={() => setIsVisible(true)}>Open Dialog</Button>
      <Popin
        isVisible={isVisible}
        onClose={() => setIsVisible(false)}
        title="Confirmation"
        closeLabel="Close dialog"
      >
        <p>Are you sure you want to proceed with this action?</p>
      </Popin>
    </div>
  );
}

API Reference

Popin

PropTypeDefaultDescription
isVisibleboolean(required)Controls the visibility of the modal. When true, the modal is displayed with entrance animations.
onClose() => void(required)Callback function invoked when the user closes the modal by clicking the backdrop or close button.
titleReactNodeundefinedOptional title displayed at the top of the modal. Can be a string or any React element.
closeLabelstringundefinedAccessible label for the close button, used for aria-label attribute. Important for screen readers.
classNamestring"sm:w-360"Custom CSS classes for the modal container. The default width is 360px on small screens and above.
bodyClassNamestringundefinedCustom CSS classes for the modal body container that wraps the title, content, and footer.
targetHTMLElementundefinedOptional portal target element where the modal should be rendered. Uses document.body by default.
childrenReactNodeundefinedContent to display inside the modal. Supports slot-based footer customization via data-slot="popinFooter".

Notes

  • Backdrop Integration: The Popin component uses the Backdrop component internally to provide a fullscreen overlay. Clicking the backdrop will trigger the onClose callback.

  • Smooth Animations: Features entrance (animate-zoomIn) and exit (animate-zoomOut) animations for a polished user experience. The modal scales and fades smoothly during transitions.

  • Slot-Based Footer: By default, a close button is rendered in the footer. You can customize the footer by passing elements with data-slot="popinFooter":

    <Popin isVisible={isVisible} onClose={onClose} title="Custom Footer">
      <p>Modal content goes here</p>
      <div data-slot="popinFooter">
        <Button onClick={onClose}>Cancel</Button>
        <Button onClick={handleConfirm}>Confirm</Button>
      </div>
    </Popin>
  • Accessibility: The close button uses the closeLabel prop for aria-label, ensuring screen readers can identify its purpose. The backdrop has role="presentation" and aria-hidden="true".

  • Responsive Design: The modal is responsive with default padding and width that adapts to different screen sizes. The content area has a max-height of 90vh with overflow scrolling.

  • Portal Rendering: The modal is rendered in a React Portal (via the Backdrop component), ensuring it appears above all other page content with proper stacking context.

  • Client Component: This is a client component (marked with "use client") due to interactive state management and animations.

  • Animation Optimization: The component includes logic to prevent initial mount flash when closed, only animating the leave transition if the modal was previously visible.