@vashudev/sense-ui
v0.1.1
Published
Touchless web control with MediaPipe Hands — scroll, zoom, and history navigation using your camera.
Maintainers
Readme
@vashudev/sense-ui
SenseUI is a React component library for touchless web control using the camera and MediaPipe Hands. It maps hand gestures to scroll, zoom, and history (back / forward) so users can navigate without touching the screen.
Install
npm install @vashudev/sense-uiPeer dependencies:
npm install react react-domThe package ships compiled JS and TypeScript types. Styles are injected once at runtime (see injectStyles), or you can rely on the default behavior.
Quick start
import { SenseButton } from '@vashudev/sense-ui';
export function App() {
return (
<SenseButton
variant="fab"
position="bottom-right"
offset={24}
showPreview
/>
);
}variant:inline|topbar|fab— layout preset (see below).position/offset: corner placement forfab(and related preview positioning).showPreview: small camera preview when gestures are active.
Components
SenseButton
Convenience wrapper that maps variant to internal SenseGestureToggle layouts:
| variant | Behavior |
|-----------|----------|
| inline | Row: title + hint + circular toggle (good inside your own navbar). |
| topbar | Fixed header bar with brand + toggle. |
| fab | Floating action button + optional SenseUI label (see branding). |
SenseGestureToggle
Lower-level API with layout: toggle | inline | topbar | fab.
import { SenseGestureToggle } from '@vashudev/sense-ui';
export function NavbarSlot() {
return (
<SenseGestureToggle
layout="toggle"
showPreview
className="my-sense-slot"
/>
);
}Placement (where the control sits)
layout="topbar"— the bar isposition: fixed; top: 0; left: 0; right: 0. UsetopOffsetif something else is already fixed at the top (e.g. another bar).layout="fab"— the cluster usesposition: fixedwithposition(bottom-right,bottom-left,top-right,top-left) andoffset(pixels from edges).layout="toggle"/inline— the root is not full-viewport fixed by default. Wrap it in your own positioned container:
<div
style={{
position: 'fixed',
bottom: 16,
right: 16,
zIndex: 50,
}}
>
<SenseGestureToggle layout="toggle" showPreview />
</div>Use className on the component (or the wrapper) to align with your design system.
Theming with theme and CSS variables
Pass theme (React CSSProperties) to set CSS custom properties on the component root. These merge before style, so style wins for duplicate keys.
Example — custom on/off colors for the circle toggle:
<SenseGestureToggle
layout="toggle"
theme={{
['--sense-ui-toggle-off-border' as string]: 'rgba(148, 163, 184, 0.6)',
['--sense-ui-toggle-off-bg' as string]: 'rgba(15, 23, 42, 0.5)',
['--sense-ui-toggle-on-border' as string]: 'rgba(34, 211, 238, 1)',
['--sense-ui-toggle-on-bg' as string]: 'rgba(34, 211, 238, 0.15)',
['--sense-ui-toggle-on-glow' as string]: 'rgba(34, 211, 238, 0.5)',
['--sense-ui-toggle-on-inset' as string]: 'rgba(56, 189, 248, 0.2)',
}}
/>(TypeScript may require as string for custom property keys, depending on your CSSProperties definition.)
Variables you can override
| Variable | Purpose |
|----------|---------|
| --sense-ui-toggle-off-border | Circle toggle border when off. |
| --sense-ui-toggle-off-bg | Circle toggle background when off. |
| --sense-ui-toggle-off-border-hover | Border on hover when off. |
| --sense-ui-toggle-on-border | Border when on (idle glow state). |
| --sense-ui-toggle-on-bg | Background when on. |
| --sense-ui-toggle-on-glow | Outer glow when on. |
| --sense-ui-toggle-on-inset | Inner highlight when on. |
| --sense-ui-focus-ring | Focus-visible outline color (toggle + FAB). |
| --sense-ui-brand-from / --sense-ui-brand-to | Gradient endpoints for the SenseUI label text. |
| --sense-ui-toggle-gap | Space between label and toggle in toggle layout. |
| --sense-ui-fab-off-border | FAB border when idle. |
| --sense-ui-fab-off-bg | FAB background (supports linear-gradient(...)). |
| --sense-ui-fab-color | FAB icon / glyph color. |
| --sense-ui-fab-brand-gap | Space between FAB label and button. |
Tracking modes (scroll / zoom / ready / not ready) still apply layered colors on top of the on state for live feedback.
Brand label (SenseUI)
For layout="toggle" and layout="fab", a short SenseUI label is shown beside the control by default (to the left of the circular toggle / FAB in LTR).
| Prop | Default | Description |
|------|---------|-------------|
| brandLabel | 'SenseUI' | Text to show. Set to '' to hide. |
| showBrandLabel | true for toggle / fab | Set false to hide the label. |
inline and topbar layouts use children for the title area instead.
<SenseButton variant="fab" brandLabel="My App" />
<SenseGestureToggle layout="toggle" showBrandLabel={false} />Camera and permissions
- Gesture control needs camera access; the browser will prompt the user.
- HTTPS (or
localhost) is required forgetUserMediain production.
API summary
Exported hooks and engine utilities (useGesture, useCamera, GestureEngine, etc.) are available for advanced integration; see TypeScript types in the package for full option lists.
License
MIT
