content-drawer
Slide-in drawers and sheets for nav menus, filters, confirmations, and side panels — any edge, with peek stages.
Features
- Any edge Bottom (default), top, left, or right via
from-side - Peek stages Full, half, or peek via
open-stage - Command-driven
--open/--close/--togglefrom any<button command commandfor> - Dismissal Outside click + Escape via
<dismiss-watcher> - Backdrop Valence.css dimmer — sibling
[role="presentation"]/.tag-backdrop - Auto-dismiss
disappear-afterfor toast-style confirmations - Singleton groups One open drawer per
singleton-name - Layout modes Viewport sheet (default,
position: fixed),.absolute(inside its parent),.relative, or.sticky - Scrubbable Wrap in
: the sheet follows the finger viagesture-handleris-scrubbing+--content-drawer-open-progress
Installation
This package is available in the
<script src="https://unpkg.com/@excom/kit-utils@0.3.0/dist/index.umd.min.js"></script>
<script src="https://unpkg.com/@excom/neutron@0.2.0/dist/index.umd.min.js"></script>
<script src="https://unpkg.com/@excom/content-drawer@0.2.3/dist/index.umd.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@excom/content-drawer@0.2.3/dist/index.css">npm install @excom/content-drawer<!-- import path to `node_modules` will depend on your build setup -->
<script type="module" src="/node_modules/@excom/content-drawer"></script>
<link rel="stylesheet" href="/node_modules/@excom/content-drawer">import "@excom/content-drawer";@import "@excom/content-drawer/index.css";Peer dependencies (0)
Packages a consumer must install alongside this one. Workspace deps are bundled.
| Package | Version |
|---|---|
|
Usage
Put content inside <content-drawer> and invoke --open, --close, or --toggle on it — a native <button command commandfor>, or <event-handler command-name target-ref> when the invoker is not a button. The parent of an .absolute drawer becomes position: relative; overflow: clip, so give that parent a real size along the drawer's axis.
<button type="button" command="--toggle" commandfor="sheet">Toggle sheet</button>
<content-drawer id="sheet" class="absolute">
<h2>Saved!</h2>
</content-drawer>
<event-handler class="tag-backdrop" role="presentation" target-ref="content-drawer:has(+ :scope)" command-name="--close"></event-handler><button type="button" command="--toggle" commandfor="sheet">Toggle sheet</button>
<content-drawer id="sheet" class="absolute">
<h2>Saved!</h2>
</content-drawer>
<event-handler class="tag-backdrop" role="presentation" target-ref="content-drawer:has(+ :scope)" command-name="--close"></event-handler>The backdrop never reads the drawer's own variables: set --content-drawer-transition-duration, --content-drawer-transition-ease and --content-drawer-overlay-z-index on the parent, the backdrop or :root. After its slide-out a closed drawer is visibility: hidden, so a custom transition on it must keep visibility 0s <duration>.
API Reference
Attributes
Role —option is configurable, state
is managed by the element (read-only), or hybrid which is both.
Provision
Thisprovision property lives on the DOM node.
Read / watch it with Quark’s prop("provision"), or listen
for the neutron-provision event from app JS.
Events
Type
command event (HTML Command API): from a
<button command commandfor>, an <event-handler
command-name>, or a CommandEvent.
Recognized Elements
Child or descendant elements are recognized by and relevant to its functionality.Styles
@custom-selector synonyms so custom elements can share
semantic styles. Element aliases match the host tag / .tag-* class; state
aliases match attributes (nested under the element alias).
content-drawer
Attributes (5)
Role —option is configurable, state
is managed by the element (read-only), or hybrid which is both.
disappear-after
disappearAfter
number
nullfrom-side
fromSide
string
"bottom" | "top" | "left" | "right""bottom"singleton-name
singletonName
string
nullis-open
--open / --close / --toggle commands. For Escape / outside-click dismissal pair with <dismiss-watcher command-name="--close">.
isOpen
boolean
falseopen-stage
0 full, 1 half, 2 peek. Unset = full. Set statically, or per open through data-open-stage on the --open / --toggle invoker.
openStage
number
"0" | "1" | "2"nullProvision (0)
Thisprovision property lives on the DOM node.
Read / watch it with Quark’s prop("provision"), or listen
for the neutron-provision event from app JS.
Events (5)
e.preventDefault() is not
synchronously called on the event.
Type
content-drawer-closed
is-open unset), detail is the drawer.
Type
ContentDrawerClosedEvent
content-drawer-opened
is-open set), detail is the drawer. When singleton-name is set it is also broadcast so drawers sharing that name close.
Type
ContentDrawerOpenedEvent
command event (HTML Command API): from a
<button command commandfor>, an <event-handler
command-name>, or a CommandEvent.
--closeis-open unset).
--openis-open set). data-* attributes on the invoker that name a declared prop (data-open-stage, data-from-side, …) are applied first; unknown, private and isOpen keys are ignored.
--toggledata-* like --open.
Recognized Elements (0)
Child or descendant elements are recognized by content-drawer and relevant to its functionality.Styles (25)
.absoluteposition: absolute instead of the default fixed placement — a sheet inside its parent, which becomes position: relative; overflow: clip..close.close / [rel="prev"] button or link (theme close icon)..relativemax-width instead of overlaying via position, pushing sibling content aside as it opens. Currently only affects from-side="left"..stickyposition: sticky instead of the default fixed placement.all: revert-layer.
Valence.css ships this as .unstyled and .unstyled-all for the entire tree.
--content-drawer-closed<percentage>101%--content-drawer-max-width<length>--content-drawer-open-full<percentage>0%--content-drawer-open-half<percentage>50%--content-drawer-open-peek<percentage>75%--content-drawer-open-progress<number>var(--gesture-progress, 0)--content-drawer-overlay-z-index<integer>2--content-drawer-relative-max-width<length>200px--content-drawer-transition-duration<time>0.25s--content-drawer-transition-ease<easing-function>ease-out--content-drawer-z-index<integer>3@custom-selector synonyms so custom elements can share
semantic styles. Element aliases match the host tag / .tag-* class; state
aliases match attributes (nested under the element alias).
:--content-drawercontent-drawer, .tag-content-drawer:--content-drawer--from-side[from-side], [data-placement]:--content-drawer--from-side-bottom[from-side="bottom"], [data-placement="bottom"]:--content-drawer--from-side-left[from-side="left"], [data-placement="left"]:--content-drawer--from-side-right[from-side="right"], [data-placement="right"]:--content-drawer--from-side-top[from-side="top"], [data-placement="top"]:--content-drawer--is-open[is-open], [aria-expanded="true"]:--content-drawer--is-scrubbing[is-scrubbing][is-scrubbing], [data-scrubbing][data-scrubbing]:--content-drawer--open-stage-1[open-stage="1"], [data-open="1"]:--content-drawer--open-stage-2[open-stage="2"], [data-open="2"]Release notes (2)
0.2.0
- Update
content-drawerso only an.absolutedrawer styles its parent, asposition: relative; overflow: clip(was every drawer, withoverflow: hidden): a fixed or sticky drawer no longer clips its parent, and sticky descendants keep working - Update a closed
content-drawerto bevisibility: hiddenonce its slide-out ends, taking it out of the tab order and the accessibility tree: a customtransitionon a closed drawer must keepvisibility 0s <duration>, and a closed drawer shown in the layout needsvisibility: visible
0.1.1
- Ship only dist (and declared extras) in the npm tarball; drop build logs, tests and sources
Release notes
e.preventDefault() is not
synchronously called on the event.
all: revert-layer.
Valence.css ships this as .unstyled and .unstyled-all for the entire tree.
Examples
Peek stages
--open with data-open-stage on the button sets the stage — 0 full, 1 half, 2 peek. The exact heights of each stage are configurable through CSS variables.
Dismissal
<dismiss-watcher command-name="--close"> as the drawer's first child closes it on outside click or Escape / back gesture; the sheet gates its is-active on content-drawer[is-open] (with the inverse rule). Open with --open, not --toggle — an outside mouseup on the button closes first, the click then re-opens. Immediate next sibling [role="presentation"] / .tag-backdrop is the Valence.css modal dimmer; <event-handler command-name="--close"> on that node closes on click.
Side drawer
from-side slides from left / right / top instead of the default bottom.
Auto-dismiss
disappear-after closes the drawer after N seconds — useful for success toasts.
Singleton group
Drawers sharing singleton-name — opening one closes the other.