COMPONENT / access-card
Access/ID Card_
Ink ID badge with a hazard band, access level chip, photo slot, name, ID line and barcode. Requires @cybr/tokens and @cybr/effects.
Install
1. Map the
@cybrnamespace, once per project. Add this inside yourcomponents.json, or into its existing"registries"object. Nocomponents.jsonyet? Runnpx shadcn@latest initfirst to create one."registries": { "@cybr": "https://cybr-ui.com/r/{name}.json" }2. Add components:
$ npx shadcn@latest add @cybr/access-card
If shadcn reports Unknown registry "@cybr", step 1 is missing from that project's components.json.
Preview
ACCESS LVL03
[Operator name]
ID 0x4F2A-91 · EXP 2099
registry/ui/access-card.tsx
import type { ComponentProps, ReactNode } from "react";
import { cn } from "@/lib/utils";
// Ink ID badge: hazard band, access level chip, photo slot, name, ID line and a
// decorative barcode. With no photo, the slot shows a crosshair placeholder.
export function AccessCard({
name,
level,
levelLabel = "ACCESS LVL",
idLine,
photo,
className,
...props
}: Omit<ComponentProps<"div">, "children"> & {
name: ReactNode;
level: ReactNode;
levelLabel?: ReactNode;
idLine?: ReactNode;
photo?: ReactNode;
}) {
return (
<div
className={cn(
"flex flex-col border-(length:--border-base) border-solid border-ink bg-ink font-mono text-ground-deep",
className,
)}
{...props}
>
<div aria-hidden="true" className="h-3.5 hazard-stripes" />
<div className="flex flex-col gap-2.5 px-3.5 py-3">
<div className="flex items-center justify-between gap-4 text-micro font-bold tracking-label">
<span>{levelLabel}</span>
<span className="bg-ground-deep px-1.5 py-0.5 text-ink">{level}</span>
</div>
<div className="relative h-24 overflow-hidden bg-surface">
{photo ? (
<div className="size-full [&>*]:size-full [&>img]:object-cover">{photo}</div>
) : (
<>
<span aria-hidden="true" className="pointer-events-none absolute top-2 bottom-2 left-1/2 w-px bg-dim" />
<span aria-hidden="true" className="pointer-events-none absolute top-1/2 right-2 left-2 h-px bg-dim" />
</>
)}
</div>
<p className="font-display text-xl [line-height:1] uppercase">{name}</p>
{idLine ? <p className="text-micro tracking-[0.12em]">{idLine}</p> : null}
<div
aria-hidden="true"
className="h-6.5 bg-[repeating-linear-gradient(90deg,var(--ground-deep)_0_2px,transparent_2px_4px,var(--ground-deep)_4px_7px,transparent_7px_8px,var(--ground-deep)_8px_9px,transparent_9px_12px)]"
/>
</div>
</div>
);
}
Repo source. The shadcn CLI rewrites import aliases to match your project.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| name | ReactNode | — | Card holder name, set in the display face. |
| level | ReactNode | — | Access level, shown in the dark chip. |
| levelLabel | ReactNode | "ACCESS LVL" | Text before the level chip. |
| idLine | ReactNode | — | Small mono line under the name, such as an ID and expiry. |
| photo | ReactNode | — | Image for the photo slot. It fills the slot with object-fit: cover. Without it, the slot shows a crosshair. |
| ...props | Omit<ComponentProps<"div">, "children"> | — | Every other native <div> attribute is forwarded; className is merged last with cn(). Set the width here. |
Usage
Needs both stylesheets from @cybr/tokens and @cybr/effects. After the install, import them in app/globals.css:
@import "tailwindcss";
@import "../styles/cybr-tokens.css";
@import "../styles/cybr-effects.css";
import Image from "next/image";
import { AccessCard } from "@/components/ui/access-card";
export function Badge() {
return (
<AccessCard
className="w-64"
level="03"
name="K. Morrow"
idLine="ID 0x4F2A-91 · EXP 2099"
photo={<Image src="/morrow.jpg" alt="K. Morrow" width={256} height={96} />}
/>
);
}
Anatomy
- Card:
--inkfill,--ground-deeptext and a 2px--inkborder. The width comes from you. - Hazard band: a 14px strip of the shared
hazard-stripesutility. Its stripes are 12px, a little wider than the artboard's 8px, so a palette swap stays in one place. - Level row: 10px bold label and a
--ground-deepchip. - Photo slot: 96px
--surfacebox. Without a photo, a--dimcrosshair marks it. - Name, ID line, barcode: display name, small mono ID line, and a decorative 26px barcode.
Accessibility
- The hazard band, crosshair and barcode are decorative and hidden from assistive tech.
- Give the photo real
alttext, usually the person's name. - Text is
--ground-deepon--ink, and the level chip is--inkon--ground-deep. If you override colours withclassName, keep text contrast at 4.5:1 or above.