component

Door

Door panel within a frame.

⌖ Explore the library in 3D → · View as Markdown

Tune every prop in the workshop →

Add it

npx @runek/cli add door

Pulls @react-three/rapier@^2.2.0, @runek/core@^0.15.0.

Use it

import { Door } from './runek/Door'

<Door position={[0, 0, 0]} />

Or as a node in a world file (worlds as data):

{ "type": "Door", "props": { "position": [0, 0, 0] } }

Props

Prop Type Default Description
position [x, y, z] [0, 0, 0] Position [x, y, z] in units (1 unit = 1 m, Y-up).
rotation [x, y, z] [0, 0, 0] Euler rotation [x, y, z] in radians.
seed number Accepted for the component contract; this component has no seeded variation yet.
width number 0.9 Width, in units.
height number 2 Height, in units.
thickness number 0.05 Thickness, in units.
openAngle number 0 Hinge angle in radians; 0 is closed.
color color palette wood Defaults to the world palette’s wood slot.

Registry manifest

registry manifest /r/components/door.json Self-contained JSON: inlined source plus resolved dependencies, exactly what runek add door fetches.

Browse the whole catalog in the gallery →.

Source (Door.tsx)
import { RigidBody } from '@react-three/rapier'
import { useWorld, type Vec3 } from '@runek/core'

export interface DoorProps {
  position?: Vec3
  rotation?: Vec3
  /** Accepted for the component contract; this component has no seeded variation yet. */
  seed?: number
  width?: number
  height?: number
  thickness?: number
  /** Hinge angle in radians; 0 is closed. */
  openAngle?: number
  /** Defaults to the world palette's `wood` slot. */
  color?: string
}

export function Door({
  position = [0, 0, 0],
  rotation = [0, 0, 0],
  width = 0.9,
  height = 2,
  thickness = 0.05,
  openAngle = 0,
  color,
}: DoorProps) {
  const { unit, palette } = useWorld()
  const woodColor = color ?? palette.wood
  const w = width * unit
  const h = height * unit
  const t = thickness * unit

  return (
    <RigidBody type="fixed" colliders="cuboid" position={position} rotation={rotation}>
      <group position={[-w / 2, 0, 0]} rotation={[0, openAngle, 0]}>
        <mesh castShadow receiveShadow position={[w / 2, h / 2, 0]}>
          <boxGeometry args={[w, h, t]} />
          <meshStandardMaterial color={woodColor} />
        </mesh>
        <mesh position={[w - 0.08 * unit, h / 2, t]}>
          <sphereGeometry args={[0.03 * unit, 12, 12]} />
          <meshStandardMaterial color={palette.accent} metalness={0.6} roughness={0.3} />
        </mesh>
      </group>
    </RigidBody>
  )
}