Skip to content
WANCRAFT

H.2123D & Experimental

Door Reveal

Doors that swing open in CSS 3D around their hinges, with shading and a slight overshoot, to reveal the content behind.

NewReactMotionCSSTailwindintermediate

Overview

Door Reveal hides content behind doors and opens them in CSS 3D. Choose a double door that parts in the middle, a single door hinged on the left, or louvred shutters whose slats turn one after another. Each leaf is a small solid: a front with raised panels, hinges and a handle, a lighter inside face you see once it swings past 90°, and an edge that shows the door's thickness. It turns around its hinge on a spring that overshoots slightly, and darkens as it turns away from the light. Closing reuses the spring's stiffness but is critically damped, so the doors never swing through the frame. A real button with aria-expanded opens and closes them, and a click on the doors opens them too. Doors can also open on their own when they scroll into view. Until the doors open, the content behind is inert: no focus, no clicks, hidden from assistive tech. With reduced motion the doors crossfade instead of swinging.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/door-reveal.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/door-reveal.json

Method 02 · Copy and paste

  1. 1. Install the dependencies below.
  2. 2. Copy the source from the Code tab into components/ui/door-reveal.tsx.
  3. 3. Import it and adjust props.
npm install motion
Dependencies
motion
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { DoorReveal } from "@/components/ui/door-reveal";

export function DoorRevealExample() {
  return (
    <DoorReveal>
      <div className="grid h-full place-items-center bg-stone-100 p-6 text-center">
        <p className="text-2xl font-semibold">You're invited</p>
      </div>
    </DoorReveal>
  );
}

03Props

PropTypeDefaultDescription
childrenReactNode—Required. The content behind the doors (fills the opening); inert until open.
variant"double" | "single" | "shutters""double"Two leaves, one leaf hinged left, or louvred shutters.
trigger"click" | "view""click"Open by button / click only, or also when 60% of the doorway is on screen (once).
open / defaultOpen / onOpenChangeboolean / boolean / (open) => void— / false / —Controlled or uncontrolled open state.
anglenumber105Swing angle in degrees (shutters turn to about 90°).
spring{ stiffness: number; damping: number; mass: number }{ stiffness: 40, damping: 9, mass: 1 }Opening spring; closing is critically damped.
perspectivenumber1400CSS perspective in px.
shadingnumber0.6How much the panels darken as they turn, 0–1.
doorColorstring"#23282F"Door colour (panels, inside face and edge are derived from it).
accentstring"#FF7448"Handles and focus ring.
width / heightnumber300 / 380Opening size in px; scales down to fit narrow containers.
slatsnumber6Number of louvres (shutters variant, 2–12).
openLabel / closeLabelstring"Open the doors" / "Close the doors"Button text.

04Features

  • 01Double doors, a single door or staggered louvred shutters
  • 02Solid leaves: panelled front, inside face, edge thickness, hinges and handles, all CSS
  • 03Spring swing with a slight overshoot; critically damped close that never passes the frame
  • 04Angle-driven shading on every face and a soft inner shadow in the opening
  • 05Open by button, by clicking the doors, or on view; closing supported; controlled or uncontrolled
motion · springinput · clickinput · keyboardinput · viewport

05Accessibility

  • A native <button> with aria-expanded and aria-controls opens and closes the doors (Enter / Space).
  • The content behind is inert until the doors open: it can't be focused or clicked and is hidden from assistive tech.
  • The doors themselves are aria-hidden decoration; clicking them is a pointer convenience for the same action.
  • trigger="view" opens the doors once, without moving focus.
  • prefers-reduced-motion replaces the swing with a short crossfade.

06Limitations

  • Open doors swing out towards the viewer and extend beyond the frame; leave some room around the component.