Iso Priority
IllustrationsIsometric illustration — a stack of iso cards with the top (priority) card lifting off and pinned, signalling a selection. Themeable accent via `brand`; reduced-motion aware.
components/ui/iso-priority.tsx
"use client";
import { motion, useReducedMotion } from "motion/react";
/**
* Isometric illustration — a stack of iso cards with the top (priority) card
* lifting off and pinned, signalling a selection. Themeable accent via `brand`;
* animation stills under reduced-motion.
*/
export function IsoPriority({
brand = "#FF4701",
className,
}: {
brand?: string;
className?: string;
}) {
const reduce = useReducedMotion();
const card = (cx: number, cy: number, highlight = false, key: string) => (
<g key={key}>
<path
d={`M${cx} ${cy - 8} L${cx + 32} ${cy + 6} L${cx} ${cy + 20} L${cx - 32} ${cy + 6} Z`}
fill={highlight ? "var(--brand)" : "white"}
stroke={highlight ? "var(--brand)" : "rgba(0,0,0,0.12)"}
strokeWidth="1"
/>
<path
d={`M${cx} ${cy + 20} L${cx + 32} ${cy + 6} L${cx + 32} ${cy + 12} L${cx} ${cy + 26} Z`}
fill={highlight ? "rgba(217,119,6,0.7)" : "rgba(0,0,0,0.06)"}
/>
<path
d={`M${cx} ${cy + 20} L${cx - 32} ${cy + 6} L${cx - 32} ${cy + 12} L${cx} ${cy + 26} Z`}
fill={highlight ? "rgba(217,119,6,0.55)" : "rgba(0,0,0,0.04)"}
/>
{!highlight && (
<>
<line x1={cx - 14} y1={cy + 2} x2={cx + 6} y2={cy + 10} stroke="rgba(0,0,0,0.18)" strokeWidth="0.8" />
<line x1={cx - 10} y1={cy + 6} x2={cx + 2} y2={cy + 12} stroke="rgba(0,0,0,0.12)" strokeWidth="0.8" />
</>
)}
</g>
);
return (
<svg viewBox="0 0 200 210" className={className} style={{ ["--brand" as string]: brand }}>
<IsoPlatform />
{card(100, 158, false, "b")}
{card(100, 138, false, "m")}
<motion.g
initial={{ y: 0 }}
animate={reduce ? undefined : { y: [-2, -8, -2] }}
transition={{ duration: 2.6, repeat: Infinity, ease: "easeInOut" }}
>
{card(100, 110, true, "t")}
<circle cx="100" cy="86" r="3.5" fill="var(--brand)" />
<line x1="100" y1="89" x2="100" y2="100" stroke="var(--brand)" strokeWidth="1.4" strokeDasharray="2 2" />
</motion.g>
</svg>
);
}
/** Shared isometric floor tile — keeps the diorama on a consistent plane. */
function IsoPlatform() {
return (
<g>
<path
d="M100 138 L168 168 L100 198 L32 168 Z"
fill="rgba(217,119,6,0.05)"
stroke="rgba(217,119,6,0.18)"
strokeWidth="0.8"
/>
<path
d="M100 138 L168 168 M100 138 L32 168 M100 198 L32 168 M100 198 L168 168"
stroke="rgba(0,0,0,0.05)"
strokeWidth="0.6"
/>
{[0.25, 0.5, 0.75].map((t) => (
<g key={t} stroke="rgba(0,0,0,0.05)" strokeWidth="0.5">
<line x1={100 - 68 * t} y1={138 + 30 * t} x2={168 - 68 * t} y2={168 + 30 * t} />
<line x1={100 + 68 * t} y1={138 + 30 * t} x2={32 + 68 * t} y2={168 + 30 * t} />
</g>
))}
</g>
);
}Installation
Terminal
npx shadcn@latest add https://ui.saumyarex.xyz/r/iso-priority.json1. Install dependencies
Terminal
npm install motion2. Copy the source into your project
components/ui/iso-priority.tsx
"use client";
import { motion, useReducedMotion } from "motion/react";
/**
* Isometric illustration — a stack of iso cards with the top (priority) card
* lifting off and pinned, signalling a selection. Themeable accent via `brand`;
* animation stills under reduced-motion.
*/
export function IsoPriority({
brand = "#FF4701",
className,
}: {
brand?: string;
className?: string;
}) {
const reduce = useReducedMotion();
const card = (cx: number, cy: number, highlight = false, key: string) => (
<g key={key}>
<path
d={`M${cx} ${cy - 8} L${cx + 32} ${cy + 6} L${cx} ${cy + 20} L${cx - 32} ${cy + 6} Z`}
fill={highlight ? "var(--brand)" : "white"}
stroke={highlight ? "var(--brand)" : "rgba(0,0,0,0.12)"}
strokeWidth="1"
/>
<path
d={`M${cx} ${cy + 20} L${cx + 32} ${cy + 6} L${cx + 32} ${cy + 12} L${cx} ${cy + 26} Z`}
fill={highlight ? "rgba(217,119,6,0.7)" : "rgba(0,0,0,0.06)"}
/>
<path
d={`M${cx} ${cy + 20} L${cx - 32} ${cy + 6} L${cx - 32} ${cy + 12} L${cx} ${cy + 26} Z`}
fill={highlight ? "rgba(217,119,6,0.55)" : "rgba(0,0,0,0.04)"}
/>
{!highlight && (
<>
<line x1={cx - 14} y1={cy + 2} x2={cx + 6} y2={cy + 10} stroke="rgba(0,0,0,0.18)" strokeWidth="0.8" />
<line x1={cx - 10} y1={cy + 6} x2={cx + 2} y2={cy + 12} stroke="rgba(0,0,0,0.12)" strokeWidth="0.8" />
</>
)}
</g>
);
return (
<svg viewBox="0 0 200 210" className={className} style={{ ["--brand" as string]: brand }}>
<IsoPlatform />
{card(100, 158, false, "b")}
{card(100, 138, false, "m")}
<motion.g
initial={{ y: 0 }}
animate={reduce ? undefined : { y: [-2, -8, -2] }}
transition={{ duration: 2.6, repeat: Infinity, ease: "easeInOut" }}
>
{card(100, 110, true, "t")}
<circle cx="100" cy="86" r="3.5" fill="var(--brand)" />
<line x1="100" y1="89" x2="100" y2="100" stroke="var(--brand)" strokeWidth="1.4" strokeDasharray="2 2" />
</motion.g>
</svg>
);
}
/** Shared isometric floor tile — keeps the diorama on a consistent plane. */
function IsoPlatform() {
return (
<g>
<path
d="M100 138 L168 168 L100 198 L32 168 Z"
fill="rgba(217,119,6,0.05)"
stroke="rgba(217,119,6,0.18)"
strokeWidth="0.8"
/>
<path
d="M100 138 L168 168 M100 138 L32 168 M100 198 L32 168 M100 198 L168 168"
stroke="rgba(0,0,0,0.05)"
strokeWidth="0.6"
/>
{[0.25, 0.5, 0.75].map((t) => (
<g key={t} stroke="rgba(0,0,0,0.05)" strokeWidth="0.5">
<line x1={100 - 68 * t} y1={138 + 30 * t} x2={168 - 68 * t} y2={168 + 30 * t} />
<line x1={100 + 68 * t} y1={138 + 30 * t} x2={32 + 68 * t} y2={168 + 30 * t} />
</g>
))}
</g>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
brand | string | "#FF4701" | Accent color; drives `--brand` inside the SVG. |
className | string | — | Classes for the <svg> (size it here). |
Dependencies
motion