or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdindex.mdtrap-control.mdtrap-creation.md
tile.json

trap-control.mddocs/

Trap Control

Methods for activating, deactivating, pausing, and controlling focus trap behavior. These methods provide fine-grained control over when and how focus trapping occurs.

Capabilities

Activate Method

Activates the focus trap, adding event listeners and beginning focus management.

/**
 * Activates the focus trap
 * @param activateOptions - Override options for this activation
 * @returns The trap instance for method chaining
 */
activate(activateOptions?: ActivateOptions): FocusTrap;

interface ActivateOptions {
  /** Override onActivate callback for this activation */
  onActivate?: () => void;
  /** Override onPostActivate callback for this activation */
  onPostActivate?: () => void;
  /** Check if trap can receive focus before activating */
  checkCanFocusTrap?: (containers: Array<HTMLElement | SVGElement>) => Promise<void>;
}

Activation Behavior:

  1. If already active, returns without changes
  2. Calls onActivate callback (if provided)
  3. Sets trap to active state
  4. Determines initial focus target
  5. Adds event listeners for keyboard/mouse events
  6. Moves focus to initial target
  7. Calls onPostActivate callback (if provided)

Usage Examples:

// Basic activation
trap.activate();

// With override callbacks (these override the base configuration)
trap.activate({
  onActivate: () => console.log('Custom activation logic'),
  onPostActivate: () => console.log('Trap is now active')
});

// With async focus check (for animated elements)
trap.activate({
  checkCanFocusTrap: async (containers) => {
    // Wait for animation to complete
    await new Promise(resolve => setTimeout(resolve, 300));
  }
});

Deactivate Method

Deactivates the focus trap, removing event listeners and optionally restoring focus.

/**
 * Deactivates the focus trap
 * @param deactivateOptions - Override options for this deactivation
 * @returns The trap instance for method chaining
 */
deactivate(deactivateOptions?: DeactivateOptions): FocusTrap;

interface DeactivateOptions {
  /** Whether to return focus to the previously focused element */
  returnFocus?: boolean;
  /** Override onDeactivate callback for this deactivation */
  onDeactivate?: () => void;
  /** Override onPostDeactivate callback for this deactivation */
  onPostDeactivate?: () => void;
  /** Check if focus can be returned before attempting */
  checkCanReturnFocus?: (trigger: HTMLElement | SVGElement) => Promise<void>;
}

Deactivation Behavior:

  1. If not active, returns without changes
  2. Calls onDeactivate callback (if provided)
  3. Removes event listeners
  4. Sets trap to inactive state
  5. Optionally returns focus to previous element
  6. Calls onPostDeactivate callback (if provided)

Usage Examples:

// Basic deactivation (uses default returnFocus setting)
trap.deactivate();

// Force return focus regardless of default setting
trap.deactivate({ returnFocus: true });

// Prevent focus return (overrides returnFocusOnDeactivate configuration)
trap.deactivate({ returnFocus: false });

// With async focus return check
trap.deactivate({
  checkCanReturnFocus: async (trigger) => {
    // Wait for trigger element to be ready
    await waitForElement(trigger);
  }
});

Pause Method

Pauses an active trap without fully deactivating it, temporarily suspending focus management.

/**
 * Pauses an active focus trap
 * @param pauseOptions - Options for this pause operation
 * @returns The trap instance for method chaining
 */
pause(pauseOptions?: PauseOptions): FocusTrap;

interface PauseOptions {
  /** Callback called immediately after pause state is set */
  onPause?: () => void;
  /** Callback called after trap is completely paused */
  onPostPause?: () => void;
}

Pause Behavior:

  • Removes event listeners but keeps trap in active state
  • Sets manually-paused flag (prevents auto-unpause)
  • Does NOT call onDeactivate or restore focus
  • Useful for nested traps or temporary focus release

Usage Examples:

// Basic pause
trap.pause();

// With callbacks
trap.pause({
  onPause: () => console.log('Pausing trap'),
  onPostPause: () => console.log('Trap paused')
});

// Check pause state
if (trap.paused) {
  console.log('Trap is paused');
}

Unpause Method

Resumes a paused trap, restoring focus management without full reactivation.

/**
 * Resumes a paused focus trap
 * @param unpauseOptions - Options for this unpause operation
 * @returns The trap instance for method chaining
 */
unpause(unpauseOptions?: UnpauseOptions): FocusTrap;

interface UnpauseOptions {
  /** Callback called immediately after unpause state is set */
  onUnpause?: () => void;
  /** Callback called after trap is completely unpaused */
  onPostUnpause?: () => void;
}

Unpause Behavior:

  • Only works if trap is active and paused
  • Clears manually-paused flag
  • Re-adds event listeners
  • Restores focus to trap (similar to activation)
  • If not at top of trap stack, remains paused until stack clears

Usage Examples:

// Basic unpause
trap.unpause();

// With callbacks
trap.unpause({
  onUnpause: () => console.log('Resuming trap'),
  onPostUnpause: () => console.log('Trap resumed')
});

Update Container Elements

Updates the elements that serve as containers for the focus trap, even while active.

/**
 * Updates the container elements for this trap
 * @param containerElements - New container elements (same format as createFocusTrap)
 * @returns The trap instance for method chaining
 */
updateContainerElements(
  containerElements: HTMLElement | SVGElement | string | Array<HTMLElement | SVGElement | string>
): FocusTrap;

Usage Examples:

// Update to new container
trap.updateContainerElements('#new-modal');

// Update to multiple containers
trap.updateContainerElements(['.sidebar', '.main-content']);

// Update with DOM elements
const newContainer = document.createElement('div');
trap.updateContainerElements(newContainer);

Trap Stack Management

Multiple traps automatically coordinate through a stack system:

  • Auto-pause: When a new trap activates, previous trap pauses
  • Auto-unpause: When active trap deactivates, previous trap unpauses
  • Manual pause: Manually paused traps won't auto-unpause
// First trap activates normally
const trap1 = createFocusTrap('#modal1');
trap1.activate(); // trap1 is active

// Second trap auto-pauses first
const trap2 = createFocusTrap('#modal2');
trap2.activate(); // trap1 paused, trap2 active

// Deactivating second trap auto-unpauses first
trap2.deactivate(); // trap1 active again, trap2 inactive

// Manual pause prevents auto-unpause
trap1.pause(); // trap1 manually paused
trap2.activate(); // trap2 active
trap2.deactivate(); // trap1 remains paused (manual)
trap1.unpause(); // trap1 active again

Method Chaining

All control methods return the trap instance, enabling method chaining:

// Chain multiple operations
trap
  .activate()
  .pause()
  .unpause()
  .deactivate();

// Conditional chaining
const result = trap.active ? trap.deactivate() : trap.activate();