Made of something. Pitted gunmetal, rivets and chipped hazard paint surrounding a recessed green display key.

The moment. Only the action key moves. Its connected vent opens and emits a short release after activation; results remain caller-owned.

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

Release the stores to seat the display key and open its connected vent.

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-siege-card.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-siege-card

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/siege-card-demo.tsx
"use client";

import { useState } from "react";
import { SiegeCard } from "@/components/grimkit/siege-card";

export default function Example() {
  const [released, setReleased] = useState(false);
  return <SiegeCard title="Reserve stores" actionLabel="Release stores" status={released ? "Stores released." : "Stores secured."} actionResultLabel={released ? "Stores released" : undefined} onAction={() => setReleased(true)}><p>Field supplies held for the next watch.</p></SiegeCard>;
}

API Reference

Props on Siege Card. Consult the included TypeScript source for supported native attributes.

PropTypeDefault
titleLive heading and accessible name.string–
childrenLive React content, never baked into artwork.ReactNode–
actionLabelOptional action label.string"Release stores"
actionResultLabelOptional action result label.string–
onActionOptional on action.(event: MouseEvent<HTMLButtonElement>) => void–
disabledDisables user interaction and cancels transient effects.booleanfalse
busyOptional busy.booleanfalse
statusCaller-owned status. Visual motion does not imply a successful operation.string""
effectsAuto honours reduced motion; off suppresses decorative motion without changing values."auto" | "off""auto"
actionPropsOptional action props.Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "onClick" | "disabled">–
Native attributesUnclaimed native attributes, event handlers and aria-* attributes are forwarded. Inputs can be named with a surrounding label or aria-label.HTMLAttributes<HTMLElement>–

Information

Category
GrimKit
Files
  • components/grimkit/siege-card.tsx
  • components/grimkit/siege-card.css
  • components/grimkit/siege-card-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.3.0
Updated
Sep 24, 2026
Registry
grimkit-siege-card