Center Morph Modal
beui/center-morph-modalFreeComponent
A composable modal whose full-size surface unfolds from its exact center toward every edge, then folds back the same way with an inset close control.
Install it
npx shadcn@latest add https://beui.dev/r/center-morph-modal.jsonSource
1"use client";2// beui.dev/components/motion/center-morph-modal34import { X } from "lucide-react";5import {6 AnimatePresence,7 motion,8 useIsPresent,9 useReducedMotion,10} from "motion/react";11import {12 cloneElement,13 createContext,14 isValidElement,15 type ReactElement,16 type ReactNode,17 useCallback,18 useContext,19 useEffect,20 useId,21 useMemo,22 useRef,23 useState,24} from "react";25import { createPortal } from "react-dom";26import { EASE_OUT } from "@/lib/ease";27import { cn } from "@/lib/utils";2829type CenterMorphModalContextValue = {30 open: boolean;31 setOpen: (open: boolean) => void;32 triggerId: string;33 contentId: string;34};3536const CenterMorphModalContext =37 createContext<CenterMorphModalContextValue | null>(null);3839function useCenterMorphModalContext(component: string) {40 const context = useContext(CenterMorphModalContext);41 if (!context) {42 throw new Error(`${component} must be used within <CenterMorphModal>`);43 }44 return context;45}4647export interface CenterMorphModalProps {48 children: ReactNode;49 /** Controlled open state. */50 open?: boolean;51 /** Initial state when used uncontrolled. */52 defaultOpen?: boolean;53 onOpenChange?: (open: boolean) => void;54}5556/**57 * A modal whose full-size surface unfolds outward from its exact center.58 * Supports controlled and uncontrolled state through composable primitives.59 */60export function CenterMorphModal({61 children,62 open: controlledOpen,63 defaultOpen = false,64 onOpenChange,65}: CenterMorphModalProps) {66 const id = useId();67 const [internalOpen, setInternalOpen] = useState(defaultOpen);68 const controlled = controlledOpen !== undefined;69 const open = controlled ? controlledOpen : internalOpen;7071 const setOpen = useCallback(72 (next: boolean) => {73 if (!controlled) setInternalOpen(next);74 onOpenChange?.(next);75 },76 [controlled, onOpenChange],77 );7879 const value = useMemo<CenterMorphModalContextValue>(80 () => ({81 open,82 setOpen,83 triggerId: `${id}-trigger`,84 contentId: `${id}-content`,85 }),86 [id, open, setOpen],87 );8889 return (90 <CenterMorphModalContext.Provider value={value}>91 {children}92 </CenterMorphModalContext.Provider>93 );94}9596export interface CenterMorphModalTriggerProps {97 children: ReactElement;98}99100/** Wraps one interactive element and opens or closes the modal. */101export function CenterMorphModalTrigger({102 children,103}: CenterMorphModalTriggerProps) {104// … truncated
What it pulls in
npm packages
Files it writes
More from beui
All 104 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Action Swap Bluraction-swap-blur | beui | Components | Free | 3 deps · 4 files | |
| Action Swap Cascadeaction-swap-cascade | beui | Components | Free | 3 deps · 4 files | |
| Action Swap Rollaction-swap-roll | beui | Components | Free | 3 deps · 4 files | |
| Agent Activityagent-activity | beui | Components | Free | 4 deps · 9 files | |
| Agent Loading States Agent Progressagent-progress | beui | Components | Free | 3 deps · 3 files | |
| AI Sidebarai-sidebar | beui | Components | Free | 4 deps · 5 files | |
| Animated Badgeanimated-badge | beui | Components | Free | 4 deps · 3 files | |
| Number Animation Animated Numberanimated-number | beui | Components | Free | 3 deps · 3 files |
