tiny-drawer-react
v1.2.0
Published
React and Next.js wrapper for tiny-drawer.
Maintainers
Readme
tiny-drawer-react
tiny-drawer-react is a React 18/19 and Next.js-friendly wrapper around tiny-drawer. It keeps the original drawer behavior and API surface, while letting you drive it with React props, refs, and hooks.
tiny-drawer is installed internally as a runtime dependency, so app developers only need to add tiny-drawer-react.
This 1.2.0 release adds support for the latest tiny-drawer scroll-full options object API.
Install Dependencies
npm
npm install tiny-drawer-reactyarn
yarn add tiny-drawer-reactpnpm
pnpm add tiny-drawer-reactCSS Import
Import the packaged CSS once in your app:
import "tiny-drawer-react/styles.css";For Next.js App Router, import it in app/layout.tsx or another client-side entry that is loaded globally.
Basic Uncontrolled Example
"use client";
import { TinyDrawer } from "tiny-drawer-react";
import "tiny-drawer-react/styles.css";
export default function DrawerDemo() {
return (
<TinyDrawer defaultOpen position="right" size="360px" draggable>
<div>
<h2>Drawer Title</h2>
<p>This content is rendered with React children.</p>
</div>
</TinyDrawer>
);
}Controlled Example
"use client";
import { useState } from "react";
import { TinyDrawer } from "tiny-drawer-react";
import "tiny-drawer-react/styles.css";
export default function DrawerDemo() {
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(true)}>Open drawer</button>
<TinyDrawer
open={open}
onOpenChange={setOpen}
position="bottom"
size="40%"
minSize="20%"
maxSize="90%"
draggable
appendToBody
>
<div>
<h2>Drawer Title</h2>
<p>This is rendered with React children.</p>
<button onClick={() => setOpen(false)}>Close</button>
</div>
</TinyDrawer>
</>
);
}Next.js App Router
Use the wrapper from a client component:
"use client";
import { useState } from "react";
import { TinyDrawer } from "tiny-drawer-react";
import "tiny-drawer-react/styles.css";
export default function DrawerDemo() {
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(true)}>Open drawer</button>
<TinyDrawer
open={open}
onOpenChange={setOpen}
position="bottom"
size="40%"
minSize="20%"
maxSize="90%"
draggable
appendToBody
>
<div>
<h2>Drawer Title</h2>
<p>This is rendered with React children.</p>
<button onClick={() => setOpen(false)}>Close</button>
</div>
</TinyDrawer>
</>
);
}Imperative Ref Example
"use client";
import { useRef } from "react";
import { TinyDrawer, type TinyDrawerRef } from "tiny-drawer-react";
import "tiny-drawer-react/styles.css";
export default function DrawerWithRef() {
const drawerRef = useRef<TinyDrawerRef>(null);
return (
<>
<button onClick={() => drawerRef.current?.open()}>Open</button>
<button onClick={() => drawerRef.current?.close()}>Close</button>
<TinyDrawer ref={drawerRef} position="left" size="320px">
<div>Imperative drawer content</div>
</TinyDrawer>
</>
);
}useTinyDrawer Hook Example
"use client";
import { useTinyDrawer } from "tiny-drawer-react";
import "tiny-drawer-react/styles.css";
export default function HookExample() {
const drawer = useTinyDrawer({
position: "bottom",
size: "40%",
defaultOpen: false,
content: "<div>Hook-driven drawer content</div>"
});
return (
<>
<div ref={drawer.containerRef} />
<button onClick={drawer.open}>Open</button>
<button onClick={drawer.close}>Close</button>
</>
);
}Props
| Prop | Type | Default | Notes |
| -------------------- | ------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
| open | boolean | undefined | Controlled open state. |
| defaultOpen | boolean | false | Initial uncontrolled open state. |
| onOpenChange | (open: boolean) => void | undefined | Called when the drawer opens or closes through user interaction or imperative APIs. |
| position | DrawerPosition | vanilla default | Calls instance.setPosition() after mount when changed. |
| size | DrawerSizeValue | vanilla default | Calls instance.setSize() after mount when changed. |
| minSize | DrawerSizeValue | vanilla default | Passed through to tiny-drawer. |
| maxSize | DrawerSizeValue | vanilla default | Passed through to tiny-drawer. |
| parentContainer | string \| HTMLElement \| null | null | Optional parent mount target passed to the vanilla instance. |
| themePrefix | string | undefined | Passed through. |
| backdrop | boolean | undefined | Passed through. |
| closeButton | boolean | undefined | Passed through. |
| closeOnBackdrop | boolean | undefined | Passed through. |
| outSideClickClose | boolean | undefined | Closes the drawer when clicking outside its boundary. |
| closeOnEscape | boolean | undefined | Passed through. |
| draggable | boolean | undefined | Passed through. |
| onScrollFull | boolean \| DrawerScrollFullOptions | undefined | Enables scroll-to-full behavior and supports nested backDrop, drawer, and scrollTarget options in tiny-drawer 1.2.0. |
| fullScreenGap | DrawerSizeValue | undefined | Controls the gap when the drawer expands to its full scroll state. |
| animation | boolean | undefined | Passed through. |
| appendToBody | boolean | undefined | Passed through. |
| lastDragLocation | boolean | undefined | Passed through. |
| className | string | undefined | Drawer class passed through to the vanilla instance. |
| zIndex | number | undefined | Passed through. |
| ariaLabel | string | undefined | Passed through. |
| children | React.ReactNode | undefined | Rendered inside an internal portal-backed content element. |
| container | string \| HTMLElement \| null | null | External host container. If omitted, an internal zero-footprint host div is rendered. |
| containerClassName | string | undefined | Applied to the internal host div when container is omitted. |
| containerStyle | React.CSSProperties | undefined | Applied to the internal host div when container is omitted. |
| destroyOnUnmount | boolean | true | Controls whether the wrapper destroys the drawer during normal unmount. |
| restoreFocus | boolean | true | Restores focus to the previously active element after close when possible. |
| onOpen | (instance) => void | undefined | Vanilla open callback. |
| onClose | (instance) => void | undefined | Vanilla close callback. |
| onDragStart | (instance) => void | undefined | Vanilla drag start callback. |
| onDrag | (size, instance) => void | undefined | Vanilla drag callback. |
| onDragEnd | (size, instance) => void | undefined | Vanilla drag end callback. |
| onDestroy | (instance) => void | undefined | Vanilla destroy callback. |
Ref API
| Method | Description |
| ----------------------- | ------------------------------------------------- |
| open() | Opens the drawer. |
| close() | Closes the drawer. |
| toggle() | Toggles the drawer. |
| destroy() | Destroys the underlying vanilla instance. |
| setPosition(position) | Calls instance.setPosition(position). |
| setSize(size) | Calls instance.setSize(size). |
| getSize() | Returns instance.getSize(). |
| isOpen() | Returns instance.isOpen(). |
| getInstance() | Returns the raw tiny-drawer instance or null. |
SSR and Hydration Notes
- Importing the package is SSR-safe because it does not touch
windowordocumentduring render. - The actual
tiny-drawerinstance is created only inside effects on the client. - For Next.js App Router, add
"use client";to components that renderTinyDraweror calluseTinyDrawer. - React children are portaled into an internal DOM node that is handed off to
tiny-drawer, so you keep React rendering without duplicating the drawer implementation.
Events and Vanilla Behavior
The wrapper uses the original TinyDrawer class from tiny-drawer, so vanilla callbacks and custom events such as tiny-drawer:open, tiny-drawer:close, and drag events are preserved.
Link Back
This package is a thin React wrapper around tiny-drawer.
