{"id":14922,"library":"solid-dismissible","title":"SolidJS Dismissible Layers Utility","description":"solid-dismissible is a foundational utility for SolidJS applications, designed to manage the dismissal behavior of UI layers such as dialogs, dropdowns, or tooltips. It provides a headless API, allowing developers to integrate dismissible logic without imposing specific styling or DOM structure. Key features include support for arbitrarily nested dismissible layers, where only the topmost active layer responds to dismiss actions, and multiple dismissal strategies such as outside pointer events (down/up), loss of focus outside the component, and the Escape key. Each strategy can be individually enabled, disabled, or customized. The current version is 0.1.1, and its last publish date was 2 years ago, indicating it is an early-stage library, part of the broader @corvu UI primitives ecosystem for SolidJS. Due to its early version, the API is subject to potential breaking changes in future minor releases, though its core functionality for handling dismissal logic is well-defined. This utility differentiates itself by offering robust nesting capabilities and fine-grained control over dismissal events, making it a powerful tool for complex interactive UIs.","status":"active","version":"0.1.1","language":"javascript","source_language":"en","source_url":"https://github.com/corvudev/corvu","tags":["javascript","solid","solidjs","dismissible","dismiss","layers","close","escape","typescript"],"install":[{"cmd":"npm install solid-dismissible","lang":"bash","label":"npm"},{"cmd":"yarn add solid-dismissible","lang":"bash","label":"yarn"},{"cmd":"pnpm add solid-dismissible","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"SolidJS is the peer dependency for the library's components and reactivity system.","package":"solid-js","optional":false}],"imports":[{"note":"Dismissible is the default export of the package, providing the core component for managing dismissible layers.","wrong":"import { Dismissible } from 'solid-dismissible'","symbol":"Dismissible","correct":"import Dismissible from 'solid-dismissible'"},{"note":"This is a named export, a SolidJS signal that tracks the IDs of currently active dismissible layers for advanced management.","wrong":"import activeDismissibles from 'solid-dismissible'","symbol":"activeDismissibles","correct":"import { activeDismissibles } from 'solid-dismissible'"},{"note":"Import the TypeScript type for the Dismissible component's props for type-safe usage.","symbol":"DismissibleProps","correct":"import type { DismissibleProps } from 'solid-dismissible'"}],"quickstart":{"code":"import { createSignal, Show, type Component } from 'solid-js';\nimport Dismissible from 'solid-dismissible';\n\nconst DialogContent: Component<{ open: boolean; setOpen: (open: boolean) => void }> = (props) => {\n  const [contentRef, setContentRef] = createSignal<HTMLElement | null>(null);\n\n  return (\n    <Dismissible\n      element={contentRef}\n      enabled={props.open()}\n      onDismiss={() => props.setOpen(false)}\n      // Optional: Prevent dismissal on outside focus\n      // dismissOnOutsideFocus={false}\n      // Optional: Prevent dismissal on escape key\n      // dismissOnEscape={false}\n    >\n      <Show when={props.open()}>\n        <div\n          ref={setContentRef}\n          tabIndex={-1} // Make div focusable for testing focus dismissal\n          style={{\n            border: '1px solid gray',\n            padding: '20px',\n            background: 'white',\n            position: 'fixed',\n            top: '50%',\n            left: '50%',\n            transform: 'translate(-50%, -50%)',\n            zIndex: 1000\n          }}\n        >\n          <h2>Dismissible Dialog</h2>\n          <p>Click outside or press Escape to dismiss.</p>\n          <button onClick={() => props.setOpen(false)}>Close</button>\n        </div>\n      </Show>\n    </Dismissible>\n  );\n};\n\nconst App: Component = () => {\n  const [dialogOpen, setDialogOpen] = createSignal(false);\n\n  return (\n    <div>\n      <button onClick={() => setDialogOpen(true)}>Open Dialog</button>\n      <DialogContent open={dialogOpen} setOpen={setDialogOpen} />\n      <p>This is content behind the dialog.</p>\n      <p>Try opening the dialog and clicking outside or pressing Escape.</p>\n    </div>\n  );\n};\n\nexport default App;","lang":"typescript","description":"This example demonstrates how to create a basic dismissible dialog component using `solid-dismissible`, managing its open state and dismissal logic."},"warnings":[{"fix":"Review the package's changelog or GitHub releases for specific breaking changes when upgrading to new minor versions. Update your component implementations accordingly.","message":"As a package in early development (version 0.1.1), `solid-dismissible` may introduce breaking changes in future minor versions (e.g., 0.2.0, 0.3.0) without adhering strictly to semantic versioning until version 1.0.0 is reached.","severity":"breaking","affected_versions":"<1.0.0"},{"fix":"Ensure the `element` prop is always set to a `Signal<HTMLElement | null>` that will eventually resolve to a valid DOM element ref, usually via `ref={setElementRef}`.","message":"Incorrectly configuring the `element` prop or allowing it to be `null` or `undefined` can lead to the dismissible component not functioning, as it relies on a valid DOM element to track outside interactions.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Always ensure the `enabled` prop accurately reflects the current visibility/interactability of a dismissible layer. Use the `onDismiss` callback to update the state that controls `enabled`, and consider how nested components' `onDismiss` might affect their parents.","message":"When nesting `Dismissible` components, improper management of the `enabled` prop or `onDismiss` callbacks can lead to unintended dismissal of parent layers or prevent deeper layers from dismissing correctly. The library is designed to support nesting, but careful state management is required.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure the DOM element for `Dismissible` is rendered and its ref (`element` prop) is available before `Dismissible` attempts to initialize. Use SolidJS's `createSignal` for the ref and conditionally render the dismissible content with `Show` or `onMount` to guarantee the element exists.","cause":"The `element` prop passed to `Dismissible` was null or undefined when the component attempted to register global event listeners.","error":"TypeError: Cannot read properties of null (reading 'ownerDocument')"},{"fix":"Verify that `enabled={true}` when the dismissible layer should be active. Confirm that the `onDismiss` callback correctly updates the state variable (e.g., `setOpen(false)`) that controls the `enabled` prop, causing the component to react and dismiss.","cause":"The `enabled` prop is `false`, or the `onDismiss` callback does not correctly update the state controlling the `enabled` prop.","error":"Dismissible layer not closing when expected (e.g., clicking outside or pressing Escape)"},{"fix":"Ensure that when a child dismissible layer is `enabled`, any parent dismissible layers have their `enabled` prop dynamically set to `false` or leverage the `activeDismissibles` signal to prevent parent dismissal logic from firing until the child is dismissed. The library handles the core nesting logic, but your state management must reflect the active layer hierarchy.","cause":"While `solid-dismissible` supports nesting, the parent layers might not be correctly 'disabled' or 'paused' when a child layer is active, causing parent dismissal events to propagate.","error":"Nested dismissible layers close prematurely or in the wrong order."}],"ecosystem":"npm"}