1+ <div align =" center " >
2+
13# react-driftkit
24
3- A lightweight, draggable floating widget wrapper for React — snap to corners or drag anywhere.
5+ ** A lightweight, draggable floating widget wrapper for React.**
6+ Snap to corners, drag anywhere, stay in bounds — all under 3KB.
47
58[ ![ npm version] ( https://img.shields.io/npm/v/react-driftkit )] ( https://www.npmjs.com/package/react-driftkit )
9+ [ ![ npm downloads] ( https://img.shields.io/npm/dm/react-driftkit )] ( https://www.npmjs.com/package/react-driftkit )
10+ [ ![ bundle size] ( https://img.shields.io/bundlephobia/minzip/react-driftkit )] ( https://bundlephobia.com/package/react-driftkit )
611[ ![ license] ( https://img.shields.io/npm/l/react-driftkit )] ( ./LICENSE )
712
13+ [ Live Demo] ( https://react-driftkit.saktichourasia.dev/ ) · [ NPM] ( https://www.npmjs.com/package/react-driftkit ) · [ GitHub] ( https://github.com/shakcho/react-drift )
14+
15+ </div >
16+
17+ ---
18+
19+ ## Why react-driftkit?
20+
21+ Building a chat widget, floating toolbar, or debug panel? You need it to be draggable, stay on screen, and not fight your existing styles. Most draggable libraries are either too heavy, too opinionated, or don't handle edge cases like viewport resizing and touch input.
22+
23+ ** react-driftkit** solves exactly this — one component, zero config, works everywhere.
24+
825## Features
926
10- - ** Drag anywhere** — smooth pointer-based dragging (mouse, touch, pen)
11- - ** Snap to corners** — optional snapping to the nearest viewport corner on release
12- - ** Flexible positioning** — named corners or custom ` { x, y } ` coordinates
13- - ** Viewport-aware** — auto-repositions on window resize, stays within bounds
14- - ** Zero styling opinions** — fully customizable via ` className ` and ` style ` props
15- - ** Tiny footprint** — under 3KB gzipped, zero dependencies beyond React
27+ - ** Drag anywhere** — smooth pointer-based dragging with mouse, touch, and pen support
28+ - ** Snap to corners** — optional bounce-animated snapping to the nearest viewport corner
29+ - ** Smart positioning** — named corners (` top-left ` , ` bottom-right ` , ...) or custom ` { x, y } ` coordinates
30+ - ** Viewport-aware** — auto-repositions on window resize and content size changes
31+ - ** 5px drag threshold** — distinguishes clicks from drags, so child buttons still work
32+ - ** Zero dependencies** — only React as a peer dependency
33+ - ** Tiny bundle** — under 3KB gzipped
34+ - ** TypeScript-first** — fully typed props and exports
35+ - ** Works with React 18 and 19**
1636
1737## Installation
1838
1939``` bash
2040npm install react-driftkit
2141```
2242
43+ <details >
44+ <summary >yarn / pnpm / bun</summary >
45+
2346``` bash
2447yarn add react-driftkit
2548```
@@ -28,6 +51,12 @@ yarn add react-driftkit
2851pnpm add react-driftkit
2952```
3053
54+ ``` bash
55+ bun add react-driftkit
56+ ```
57+
58+ </details >
59+
3160## Quick Start
3261
3362``` tsx
@@ -36,37 +65,66 @@ import { MovableLauncher } from 'react-driftkit';
3665function App() {
3766 return (
3867 <MovableLauncher defaultPosition = " bottom-right" >
39- <button >💬 Chat</button >
68+ <button >Chat with us </button >
4069 </MovableLauncher >
4170 );
4271}
4372```
4473
74+ That's it. Your button is now a draggable floating widget pinned to the bottom-right corner.
75+
76+ ## Examples
77+
4578### Snap to Corners
4679
80+ Release the widget and it bounces to the nearest corner:
81+
4782``` tsx
4883<MovableLauncher defaultPosition = " bottom-right" snapToCorners >
4984 <div className = " my-widget" >Drag me!</div >
5085</MovableLauncher >
5186```
5287
53- ### Custom Position
88+ ### Free Positioning
89+
90+ Place the widget at exact coordinates:
5491
5592``` tsx
5693<MovableLauncher defaultPosition = { { x: 100 , y: 200 }} >
5794 <div className = " toolbar" >Toolbar</div >
5895</MovableLauncher >
5996```
6097
61- ## API
98+ ### Styled Widget
99+
100+ Combine with your own styles and classes:
101+
102+ ``` tsx
103+ <MovableLauncher
104+ defaultPosition = " top-right"
105+ snapToCorners
106+ className = " my-launcher"
107+ style = { { borderRadius: 12 , boxShadow: ' 0 4px 20px rgba(0,0,0,0.15)' }}
108+ >
109+ <div className = " floating-panel" >
110+ <h3 >Quick Actions</h3 >
111+ <button >New Task</button >
112+ <button >Settings</button >
113+ </div >
114+ </MovableLauncher >
115+ ```
116+
117+ ## API Reference
118+
119+ ### ` <MovableLauncher> `
62120
63121| Prop | Type | Default | Description |
64122| ------| ------| ---------| -------------|
65- | ` children ` | ` ReactNode ` | — | Content to render inside the draggable wrapper |
66- | ` defaultPosition ` | ` Corner \| { x: number , y: number } ` | ` 'bottom-right' ` | Initial position of the widget |
67- | ` snapToCorners ` | ` boolean ` | ` false ` | Snap to the nearest corner when released |
68- | ` style ` | ` CSSProperties ` | ` {} ` | Inline styles for the wrapper |
69- | ` className ` | ` string ` | ` '' ` | CSS class for the wrapper |
123+ | ` children ` | ` ReactNode ` | * required * | Content to render inside the draggable wrapper |
124+ | ` defaultPosition ` | ` Corner \| { x, y } ` | ` 'bottom-right' ` | Initial position — a named corner or pixel coordinates |
125+ | ` snapToCorners ` | ` boolean ` | ` false ` | Snap to the nearest viewport corner on release |
126+ | ` style ` | ` CSSProperties ` | ` {} ` | Inline styles merged with the wrapper |
127+ | ` className ` | ` string ` | ` '' ` | CSS class added to the wrapper |
70128
71129### Types
72130
@@ -79,10 +137,40 @@ interface Position {
79137}
80138```
81139
82- ## Requirements
140+ ### CSS Classes
141+
142+ The wrapper element exposes these classes for styling:
143+
144+ | Class | When |
145+ | -------| ------|
146+ | ` movable-launcher ` | Always present |
147+ | ` movable-launcher--dragging ` | While the user is actively dragging |
83148
84- - React 18+ or 19+
149+ ## Use Cases
150+
151+ - ** Chat widgets** — floating support/chat buttons that stay accessible
152+ - ** Floating toolbars** — draggable formatting bars or quick-action panels
153+ - ** Debug panels** — dev tools overlays that can be moved out of the way
154+ - ** Media controls** — picture-in-picture style video or audio controls
155+ - ** Notification centers** — persistent notification panels users can reposition
156+ - ** Accessibility helpers** — movable assistive overlays
157+
158+ ## How It Works
159+
160+ Under the hood, react-driftkit uses the [ Pointer Events API] ( https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events ) for universal input handling and a ` ResizeObserver ` to keep the widget positioned correctly when its content changes size. The widget renders as a ` position: fixed ` div at the highest possible z-index (` 2147483647 ` ), so it floats above everything without interfering with your layout.
161+
162+ ## Contributing
163+
164+ Contributions are welcome! Feel free to open an issue or submit a pull request.
165+
166+ ``` bash
167+ git clone https://github.com/shakcho/react-drift.git
168+ cd react-drift
169+ npm install
170+ npm run dev # Start the demo app
171+ npm test # Run the test suite
172+ ```
85173
86174## License
87175
88- MIT © Sakti Kumar Chourasia
176+ MIT © [ Sakti Kumar Chourasia] ( https://github.com/shakcho )
0 commit comments