expandable-screen
cult-ui/expandable-screenUnverifiedComponent
A full-screen expandable component with morphing animations using shared layout IDs for smooth transitions
Install it
npx shadcn@latest add https://raw.githubusercontent.com/nolly-studio/cult-ui/HEAD/apps/www/expandable-screen.jsonSource
1"use client"23import {4 createContext,5 useContext,6 useEffect,7 useState,8 type ReactNode,9} from "react"10import { X } from "lucide-react"11import { AnimatePresence, motion } from "motion/react"1213// Context14interface ExpandableScreenContextValue {15 isExpanded: boolean16 expand: () => void17 collapse: () => void18 layoutId: string19 triggerRadius: string20 contentRadius: string21 animationDuration: number22}2324const ExpandableScreenContext =25 createContext<ExpandableScreenContextValue | null>(null)2627function useExpandableScreen() {28 const context = useContext(ExpandableScreenContext)29 if (!context) {30 throw new Error(31 "useExpandableScreen must be used within an ExpandableScreen"32 )33 }34 return context35}3637// Root Component38interface ExpandableScreenProps {39 children: ReactNode40 defaultExpanded?: boolean41 onExpandChange?: (expanded: boolean) => void42 layoutId?: string43 triggerRadius?: string44 contentRadius?: string45 animationDuration?: number46 lockScroll?: boolean47}4849export function ExpandableScreen({50 children,51 defaultExpanded = false,52 onExpandChange,53 layoutId = "expandable-card",54 triggerRadius = "100px",55 contentRadius = "24px",56 animationDuration = 0.3,57 lockScroll = true,58}: ExpandableScreenProps) {59 const [isExpanded, setIsExpanded] = useState(defaultExpanded)6061 const expand = () => {62 setIsExpanded(true)63 onExpandChange?.(true)64 }6566 const collapse = () => {67 setIsExpanded(false)68 onExpandChange?.(false)69 }7071 useEffect(() => {72 if (lockScroll) {73 if (isExpanded) {74 document.body.style.overflow = "hidden"75 } else {76 document.body.style.overflow = "unset"77 }78 }79 }, [isExpanded, lockScroll])8081 return (82 <ExpandableScreenContext.Provider83 value={{84 isExpanded,85 expand,86 collapse,87 layoutId,88 triggerRadius,89 contentRadius,90 animationDuration,91 }}92 >93 {children}94 </ExpandableScreenContext.Provider>95 )96}9798// Trigger Component99interface ExpandableScreenTriggerProps {100 children: ReactNode101 className?: string102}103104export function ExpandableScreenTrigger({105 children,106 className = "",107}: ExpandableScreenTriggerProps) {108 const { isExpanded, expand, layoutId, triggerRadius } = useExpandableScreen()109110 return (111 <AnimatePresence initial={false}>112 {!isExpanded && (113 <motion.div className={`inline-block relative ${className}`}>114// … truncated
What it pulls in
npm packages
Files it writes
More from cult/ui
All 157 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| ai-instructionsai-instructions | cult/ui | Components | Unverified | 2 deps | |
| ai-instructions-demoai-instructions-demo | cult/ui | Components | Unverified | no deps | |
| animated-numberanimated-number | cult/ui | Components | Unverified | 1 dep | |
| animated-number-demoanimated-number-demo | cult/ui | Components | Unverified | no deps | |
| bg-animate-buttonbg-animate-button | cult/ui | Components | Unverified | no deps | |
| bg-animate-button-demobg-animate-button-demo | cult/ui | Components | Unverified | no deps | |
| bg-animated-fractal-dot-gridbg-animated-fractal-dot-grid | cult/ui | Components | Unverified | 1 dep | |
| bg-animated-fractal-dot-grid-demobg-animated-fractal-dot-grid-demo | cult/ui | Components | Unverified | no deps |
