Componentticket-stub0.74 KB gzipZero dependencies
Passport
Double-frame passport cover with monogram, holder fields and staggered visa stamp marks.
Preview
Live Preview
J
NAME
John Doe
NATIONALITY
US Citizen
C
M
U
Installation
Tokens guide →Add to your project via CLI (zero dependencies, code you own):
npx bigbullui add passportOr install the full npm package:
npm install bigbulluiUsage
Open in StackBlitzimport { Passport } from "@/components/ui/passport";
<Passport holderName="John Doe" nationality="US CITIZEN" visaCountries={["Canada", "Mexico"]} />Usage guidance
Use Passport when a ticket stub surface needs Double-frame passport cover with monogram, holder fields and staggered visa stamp marks. Keep props minimal and prefer composition with sibling stubs.
Avoid Passport for long form flows or dense data grids where a dedicated layout block fits better.
Source code
passport.tsxZero dependencies (only React + utils). Copy and paste directly into your project:
"use client";
import * as React from "react";
import { cn } from "./lib/utils";
export interface PassportProps {
holderName?: string;
nationality?: string;
visaCountries?: string[];
className?: string;
}
export function Passport({ holderName, nationality, visaCountries = [], className }: PassportProps) {
return (
<div
className={cn(
"relative size-96 rounded-lg border border-border bg-card p-6 motion-reduce:transition-none",
className
)}
>
<div className="relative rounded-2xl border border-border bg-secondary p-2">
<div className="relative">
<div
className="absolute -top-2 -right-2 size-6 rounded-full border border-border/20 flex items-center justify-center text-[8px] font-bold">
{holderName ? holderName.charAt(0) : "H"}
</div>
<div className="absolute inset-1 rounded-lg border border-dashed border-border/40" />
</div>
</div>
<div className="mt-4 grid rows-2 gap-4">
<div>
<div className="font-mono text-[9px] uppercase tracking-[0.15em] text-muted-foreground">NAME</div>
<div className="font-mono text-[11px] font-medium">{holderName || "HOLDER NAME"}</div>
</div>
<div>
<div className="font-mono text-[9px] uppercase tracking-[0.15em] text-muted-foreground">NATIONALITY</div>
<div className="font-mono text-[11px]">{nationality || "NATIONALITY"}</div>
</div>
</div>
<div className="mt-6 grid grid-cols-3 gap-2">
{visaCountries.map((country, i) => (
<VisaStamp key={i} country={country} index={i} />
))}
</div>
</div>
);
}
function VisaStamp({ country, index }: { country: string; index: number }) {
return (
<div
className={cn(
"aspect-square rounded-md border border-dashed border-border/50 flex items-center justify-center text-[7px] font-bold",
index % 2 === 0 && "animate-stamp"
)}
>
{country.charAt(0).toUpperCase()}
</div>
);
}Props
| Prop | Type | Description |
|---|---|---|
| holderName? | string | |
| nationality? | string | |
| visaCountries? | string[] | |
| className? | string |