- Accordion
- Advanced Toast
- AlertMessage
- ArrowButton
- Arrows
- Avatar
- Backdrop
- Basic Toast
- Breadcrumb
- Button
- CardBackground
- Card
- Carousel
- Chapters
- ChatBody
- ChatButton
- ChatHeader
- ChatInput
- ChatMessageActions
- ChatMessageEditor
- ChatMessage
- ChatTypingIndicator
- ChatWindowCsatPrompt
- ChatWindowQuote
- ChatWindow
- CheckboxSelect
- Checkbox
- Checkboxes
- Chip
- ChoiceExpander
- Clickable
- ContentReview
- Countdown
- CriteriaDates
- CriteriaParticipants
- CriteriaTransports
- Date Field
- Datepicker
- Dropdown
- ElasticHeight
- ExpandableCard
- ExpandableText
- Filter
- FloatingLabelTextField
- Form Control
- Form Label
- Frame
- HamburgerIcon
- Heading
- Image
- JourneyCard
- LayerHeader
- Layer
- Link
- Loader
- Number Field
- PageNavigation
- Pagination
- Paragraph
- Password
- Phone Field
- Popin
- Portal
- ProductThumbnail
- Promises
- Prose
- Radio Group
- RadioSelect
- Radio
- Range
- Scrollbar
- Select
- SidebarLayout
- SliderFrame
- SparkleWrapper
- Spinner
- Switch
- Table
- Tabs
- Tag
- TextField
- Toggle
- Tooltip
- ValidationMessage
'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
| Prop | Type | Default | Description |
|---|---|---|---|
isVisible | boolean | (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. |
title | ReactNode | undefined | Optional title displayed at the top of the modal. Can be a string or any React element. |
closeLabel | string | undefined | Accessible label for the close button, used for aria-label attribute. Important for screen readers. |
className | string | "sm:w-360" | Custom CSS classes for the modal container. The default width is 360px on small screens and above. |
bodyClassName | string | undefined | Custom CSS classes for the modal body container that wraps the title, content, and footer. |
target | HTMLElement | undefined | Optional portal target element where the modal should be rendered. Uses document.body by default. |
dismissable | boolean | true | When false, prevents the modal from being closed via ESC key, backdrop click, or close button. Only programmatic closing via onClose is allowed. |
children | ReactNode | undefined | Content to display inside the modal. Supports slot-based footer customization via data-slot="popinFooter". |
Notes
-
Backdrop Integration: The Popin component uses the
Backdropcomponent internally to provide a fullscreen overlay. Clicking the backdrop will trigger theonClosecallback (unlessdismissable={false}). -
Dismissable Control: Use the
dismissableprop to control whether users can close the modal. Whendismissable={false}, the modal cannot be closed via ESC key, backdrop click, or the close button, forcing programmatic closure via theonClosecallback. -
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 (when
dismissable={true}). You can customize the footer by passing elements withdata-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
closeLabelprop foraria-label, ensuring screen readers can identify its purpose. The backdrop hasrole="presentation"andaria-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.