Skip to main content

Quick Reference

Quick reference for all portal methods, properties, and patterns.

Factory Functions

import { modal, drawer, bottomSheet } from '@codeleap/portals'

// Create portals
const MyModal = modal()
const MyDrawer = drawer()
const MyBottomSheet = bottomSheet()

// With ID
const UserModal = modal({ id: 'USER_MODAL' })

// With configuration
const ConfiguredModal = modal({
id: 'CONFIGURED',
initialParams: { theme: 'dark' },
startsOpen: false,
independent: false,
rendersWhenHidden: false,
resetParamsOnClose: true,
transitionDuration: 300,
metadata: { category: 'user' }
})

Core Methods

// Define content (required)
MyModal.content((props) => <div>Content</div>)

// Configure wrapper properties
MyModal.props({ title: 'Title', style: ['modal'] })

// Dynamic props
MyModal.props((params) => ({ title: `Editing ${params.name}` }))

// Open portal
MyModal.open()
MyModal.open({ userId: '123' })

// Close portal
MyModal.close()

// Toggle visibility
MyModal.toggle()

// Request with promise
const result = await MyModal.request({ param: 'value' })

// Update parameters
MyModal.setParams({ theme: 'dark' })
MyModal.setParams((prev) => ({ count: prev.count + 1 }))

// Reset parameters
MyModal.resetParams()

// Get parameters
const params = MyModal.getParams()

// Lifecycle hooks
MyModal.onOpen((portal) => console.log('Opened!'))
MyModal.onClose((portal) => console.log('Closed!'))

React Hooks

// Access state
function MyComponent() {
const { visible, params } = UserModal.useState()

return (
<div>
<p>Modal is {visible ? 'open' : 'closed'}</p>
<p>User: {params.username}</p>
</div>
)
}

// Dynamic props
function MyComponent({ theme }) {
UserModal.useProps({
theme: theme,
title: 'User Modal'
}, [theme])

return <button onClick={UserModal.open}>Open</button>
}

Read-Only Properties

// Visibility
console.log(MyModal.isVisible) // boolean

// Current params
console.log(MyModal.currentParams) // Params

// Stack position (z-index)
console.log(MyModal.stackIndex) // number (-1 if not in stack)

// Pending request
console.log(MyModal.hasPendingRequest) // boolean

// Portal ID
console.log(MyModal.id) // string

// Wrapper ref
console.log(MyModal.ref.current) // RefType

Content Props

MyModal.content((props) => {
const {
// State
visible, // boolean
params, // current parameters

// Control
toggle, // () => Promise<void>
close, // () => Promise<void>
open, // (params?) => Promise<void>
setParams, // (next) => void

// Request
request, // { resolve, reject } | null

// Ref
ref, // React.RefObject<RefType>

// Custom parameters
...yourParams // from .open() or .request()

} = props

return <div>Content</div>
})

Portal Types

// Modal - centered overlay
import { modal } from '@codeleap/portals'
const MyModal = modal()

// Drawer - side panel
import { drawer } from '@codeleap/portals'
const MyDrawer = drawer()

// BottomSheet - bottom panel
import { bottomSheet } from '@codeleap/portals'
const MySheet = bottomSheet()

// Alert - utility for typed alerts
import { alert } from '@codeleap/portals'
alert.error({ title: 'Error', body: 'Message' })
alert.warn({ title: 'Warning', body: 'Message' })
alert.info({ title: 'Info', body: 'Message' })
alert.ask({ title: 'Question', body: 'Message' })
alert.custom({ title: 'Custom', customData: {} })

Global Configuration

import { Modal, Drawer, BottomSheet, Alert } from '@codeleap/portals'

// Set wrapper components
Modal.WrapperComponent = MyModalWrapper
Drawer.WrapperComponent = MyDrawerWrapper
BottomSheet.WrapperComponent = MyBottomSheetWrapper

// Set default transition durations
Modal.DEFAULT_TRANSITION_DURATION = 300
Drawer.DEFAULT_TRANSITION_DURATION = 250
BottomSheet.DEFAULT_TRANSITION_DURATION = 200

// Configure bottom sheet ref methods
BottomSheet.openKeyMethod = 'snapToIndex'
BottomSheet.closeKeyMethod = 'close'

// Set alert modal
Alert.modal = modal({ id: 'ALERT' }).content(...)

Global Outlet

import { Portal } from '@codeleap/portals'

function App() {
return (
<div>
<YourAppContent />
<Portal.GlobalOutlet />
</div>
)
}

Portal Registry

import { Portal, Modal } from '@codeleap/portals'

// Access by ID
const portal = Portal.registry.getInstance('USER_MODAL')
const modal = Modal.registry.getInstance('MY_MODAL')

// Get all portals
const all = Portal.registry.getAll()

// Filter portals
const openPortals = Portal.registry.filter(p => p.isVisible)

// Stack operations
Portal.registry.push('MODAL_ID')
Portal.registry.remove('MODAL_ID')
const index = Portal.registry.getStackIndex('MODAL_ID')

// Clear all
Portal.registry.clear()

TypeScript

import { modal } from '@codeleap/portals'

// Define types
interface Params {
userId: string
mode: 'view' | 'edit'
}

interface Result {
saved: boolean
user?: User
}

interface Metadata {
category: string
}

interface RefType {
focus: () => void
}

interface WrapperProps {
title: string
theme: 'light' | 'dark'
}

// Create typed portal
const TypedModal = modal<Params, Result, Metadata, RefType, WrapperProps>()
.content((props) => {
// Fully typed props
const { userId, mode, request } = props

return <div>Content</div>
})

// Type-safe usage
const result = await TypedModal.request({
userId: '123',
mode: 'edit'
})

if (result.saved) {
console.log('User saved')
}

Configuration Options

OptionTypeDefaultDescription
idstringautoUnique identifier
initialParamsParams | () => Promise<Params>{}Initial parameters
startsOpenboolean | () => Promise<boolean>falseOpen on mount
independentbooleanfalseDon't use global stack
rendersWhenHiddenbooleanfalseRender when not visible
resetParamsOnClosebooleantrueReset params on close
transitionDurationnumberclass defaultAnimation duration (ms)
metadataMetadata{}Additional metadata