Made of something. Blackened steel, chipped oxblood enamel, a fractured ruby inset and a bolt that enters its receiving socket.

The moment. Holding charges the ruby and advances the bolt. Releasing early cancels from the current position. Completion locks once; a confirmation dialog offers an alternative to holding.

Yours to adapt. Copy the component source, styles and materials. Functional text stays live, effects respect reduced motion, and the artwork requires no remote hosting.

Try it

Hold to seal, or use the confirmation alternative below it.

Install

Add it with the shadcn CLI, or copy the source manually.

Release candidate: public installation becomes available after deployment. Use an existing React 19 project with shadcn initialized and a components.json file. The CLI installs the source, CSS, embedded materials, MIT licence and font notices together.

Terminal
npx shadcn@latest add https://seanportfol.io/r/grimkit-vow-confirm.json
Prefer a namespace? Register the registry once.
Terminal
npx shadcn@latest registry add @seanlynch=https://seanportfol.io/r/{name}.json
Terminal
npx shadcn@latest add @seanlynch/grimkit-vow-confirm

Usage

Copy this example into a separate file, not over the installed component. The @/ alias points to your source root. In Next.js this is a Client Component; Vite also accepts the directive. Replace demonstration actions with your application logic.

components/examples/vow-confirm-demo.tsx
"use client";

import { useState } from "react";
import { VowConfirm } from "@/components/grimkit/vow-confirm";

export default function Example() {
  const [confirmed, setConfirmed] = useState(false);
  return <>
    <VowConfirm label="Seal the vow" holdDuration={1400} onConfirm={() => setConfirmed(true)} />
    <p role="status">{confirmed ? "Confirmed." : "Hold to confirm, or use the alternative confirmation."}</p>
  </>;
}

API Reference

Props on Oath Lock. Consult the included TypeScript source for supported native attributes.

PropTypeDefault
onConfirmRequired callback, called once on completed hold or alternative confirmation. Completion stays locked until the component is remounted (for example with a new key). Releasing early or Escape cancels an active hold.() => void
holdDurationHold duration in milliseconds, with a minimum of 600ms. Non-finite values use 1400ms.number1400
label / confirmedLabelResting and completed labels.stringSeal the vow / Vow sealed
disabledDisables confirmation and cancels any active hold.booleanfalse
classNameAdditional class on the control surface; does not replace the material styles.string
effectsAuto honours reduced motion; off disables decorative motion and particles."auto" | "off""auto"

Information

Category
GrimKit
Files
  • components/grimkit/vow-confirm.tsx
  • components/grimkit/modern-vow-seal.tsx
  • components/grimkit/modern-foundation.css
  • components/grimkit/modern-vow-seal.css
  • components/grimkit/modern-vow-seal-materials.css
  • components/grimkit/LICENSE.txt
  • components/grimkit/Saira-OFL.txt
  • components/grimkit/JetBrainsMono-OFL.txt
Dependencies
React 19 and React DOM 19; no additional runtime packages
Compatibility
React 19, TypeScript, CSS imports, Modern browsers
Version
0.2.0
Updated
Sep 22, 2026
Registry
grimkit-vow-confirm