BlockDex

Components

Registries

Free blocks

Method

BlockDex

Components

Registries

Free blocks

Method

Open API

BlockDex

Components

Registries

Free blocks

Method

Open API

Components/ns-ui/confirm-dial-align

Confirm Dial Align

ns-ui/confirm-dial-align
FreeComponent

Destructive-action confirm gated on precision, not patience: rotate an SVG dial's notch to within 3deg of a fixed index, hold it there 400ms, and the dial snaps home and arms the confirm button — overshoot and it springs back like a slipping safe tumbler.

Live preview

live · rendered by the registry
Rendered by ns-ui on their own page — this is the component running, not a screenshot of it.

Install it

npx shadcn@latest add https://design.helpmarq.com/r/confirm-dial-align.json

Source

registry/core/confirm-dial-align/component.tsxdesign.helpmarq.com/r/confirm-dial-align.json · first 6 KB
1"use client";
2
3import { useEffect, useRef, useState, type ReactNode } from "react";
4
5// TumblerGate — a destructive-action confirm gated on ACCURACY, the third
6// axis besides confirm-hold-ink's time and confirm-slide-shatter's distance. An
7// SVG dial carries one rotating notch; it must be turned (drag, wheel, or
8// arrow keys) until the notch sits within 3deg of the fixed index mark and
9// HELD there for a 400ms dwell — leaving the band before the dwell completes
10// is a failed catch: the dial springs out to +8deg like a safe tumbler that
11// almost caught and slipped. Completing the dwell spring-snaps to exact
12// zero, both ticks thicken to --foreground, and the destructive button arms
13// (its one legitimate use of --accent). Because fine-motor precision is
14// hostile to some users, an always-visible "type to confirm" disclosure
15// offers an equivalent path, and two failed catches auto-expand it. Direct-
16// DOM writes on the drag/spring hot path, React state only at the rare
17// armed/failed/fallback transitions. Zero deps.
18
19const TOL = 3; // deg — dwell capture band around the index mark
20const DWELL_MS = 400;
21const STEP = 2; // deg per wheel tick / arrow key
22const FRICTION = 0.6; // drag angular delta damping
23const SLIP_TARGET = 8; // deg — where a failed catch springs out to
24const SNAP_K = 260;
25const SNAP_ZETA = 0.85; // one tiny overshoot settling to exact zero
26const SLIP_K = 380;
27const SLIP_ZETA = 0.55; // stiffer, snappier "give"
28const SETTLE_EPS = 0.05; // deg
29const V_EPS = 0.3; // deg/s
30const FORCE_SETTLE_MS = 700;
31
32function wrapDeg(a: number) {
33 let r = a % 360;
34 if (r > 180) r -= 360;
35 if (r <= -180) r += 360;
36 return r;
37}
38
39export function TumblerGate({
40 destructiveLabel = "Delete organization",
41 doneLabel = "Deleted",
42 confirmWord = "delete",
43 initialAngle = 150,
44 onConfirm,
45 className = "",
46}: {
47 destructiveLabel?: ReactNode;
48 doneLabel?: ReactNode;
49 /** word the type-to-confirm fallback checks against, case-insensitive */
50 confirmWord?: string;
51 /** starting dial offset in degrees from the index mark */
52 initialAngle?: number;
53 onConfirm?: () => void;
54 className?: string;
55}) {
56 const knobRef = useRef<HTMLDivElement>(null);
57 const inputRef = useRef<HTMLInputElement>(null);
58 const notchGroupRef = useRef<SVGGElement>(null);
59 const notchLineRef = useRef<SVGLineElement>(null);
60 const indexLineRef = useRef<SVGLineElement>(null);
61
62 const [armed, setArmed] = useState(false);
63// … truncated

Files it writes

  • registry/core/confirm-dial-align/component.tsx

Facts

Registry
ns-ui
Type
registry:ui
Access
Free
Files written
1
Licence
MIT
First indexed
2026-08-02
Last confirmed
yesterday

Go to the source

Docs on ns-ui design.helpmarq.com nikolas-sapa/ns-ui on GitHub Raw registry item This item as JSON

More from ns-ui

All 228 items
Same registry, same kind — the ones you would have found next
ComponentRegistryKindAccessInstallsCommand
Accordion Latchaccordion-latchns-uiComponentsFreeno deps
Approval Inline Diffapproval-inline-diffns-uiComponentsFreeno deps
ASCII Engraving Contourascii-engraving-contourns-uiComponentsFreeno deps
ASCII Globe Spinascii-globe-spinns-uiComponentsFreeno deps
ASCII Torus Donutascii-torus-donutns-uiComponentsFreeno deps
Autosave Ratchetautosave-ratchetns-uiComponentsFreeno deps
Avatar Stack Flockavatar-stack-flockns-uiComponentsFreeno deps
Background ASCII Ditherbackground-ascii-ditherns-uiComponentsFreeno deps
BlockDex

Built by

Kynth Studio

Index

Components
Registries
Method
Open API

Guides

shadcn component libraries
Best shadcn registries
Free shadcn blocks

Reference

Corpus counts
Crawl health
hello@kynth.studio
Privacy
Terms

BlockDex

BlockDex

Built by

Kynth Studio

Index

Components
Registries
Method
Open API

Guides

shadcn component libraries
Best shadcn registries
Free shadcn blocks

Reference

Corpus counts
Crawl health
hello@kynth.studio
Privacy
Terms

BlockDex

BlockDex

Built by

Kynth Studio

Index

Components
Registries
Method
Open API

Guides

shadcn component libraries
Best shadcn registries
Free shadcn blocks

Reference

Corpus counts
Crawl health
hello@kynth.studio
Privacy
Terms

BlockDex