Skip to content

Defining Drawers ​

Every drawer has a set of built-in options: drawerKey, placement, the close behaviors (closeOnEscapeKey, closeOnBackdropClick), the ARIA attributes, and dataAttributes.

Real applications usually need more than that: product data, user information, callbacks. Instead of storing that data somewhere else and keeping it in sync, extend the drawer options and let the drawer carry it.

Extending the Options ​

Create an interface that extends DrawerOptions and pass it to the manager:

ts
import type { DrawerOptions } from '@drawerly/core'
import { createDrawerManager } from '@drawerly/core'

interface ProductDrawerOptions extends DrawerOptions {
  productId: string
  productName: string
  price: number
  onAddToCart?: (productId: string) => void
}

const manager = createDrawerManager<ProductDrawerOptions>()

TypeScript now enforces the custom fields everywhere:

ts
manager.open({
  drawerKey: 'product-456',
  productId: '456',
  productName: 'Smart Watch',
  price: 199.99,
})

const drawer = manager.getDrawerInstance('product-456')
console.log(drawer?.price) // typed as number | undefined

manager.updateOptions('product-456', {
  price: 149.99, // validated against the interface
})

Default Options ​

Defaults can be configured per manager and apply to every opened drawer:

ts
const manager = createDrawerManager<ProductDrawerOptions>({
  defaultOptions: {
    placement: 'left', // overrides the built-in default
    price: 0, // custom fields can have defaults too
  },
})

Fields you omit fall back to defaultOptions, so you only pass what differs from the default. Passing undefined or null for a field is treated the same as omitting it, which lets you forward an optional prop as-is (placement: props.placement) without an extra check.

Dynamic Predicates ​

closeOnEscapeKey and closeOnBackdropClick also accept a function that receives the drawer instance, including your custom fields. This enables conditional close behavior:

ts
manager.open({
  drawerKey: 'checkout',
  productId: '999',
  productName: 'Premium Laptop',
  price: 2499.99,

  // Don't let an expensive checkout close by accident
  closeOnBackdropClick: drawer => drawer.price < 1000,
})

Adapters evaluate these predicates with the resolveDrawerPredicate helper exported from @drawerly/core.

Released under the MIT License.