bigbullui logobigbullui
Componentdata

Receipt

Thermal receipt with zigzag tear edge, mono lines and barcode footer.

Preview

Live Preview
Premium Headphones
25%

Premium Headphones

$299$399

Jordan Daisy

Product Designer

AvailableRemote
The Future of Design Systems

The Future of Design Systems

Alex Rivera8 min read
Oc
t 14

Tech Conference 2026

21:00
Berlin Arena
Invoice #INV-2026-0987draft
Date: 2026-09-15Due: 2026-10-15
ItemQtyPrice
Design Services1$150
Development Hours5$100
SubtotalNaN
Tax (10%)NaN
TotalNaN
THERMAL RECEIPT#8R7G2X
Design Consultation$150
Development Hours$200
Total$385.00
Thank you for your purchase!
Premium Headphones
1
Phone Case
2
Subtotal$377.00
Tax$30.16
Total$407.16
Color
Size
Order #102938Processing
Design Services1x
Development5x
VIP

LOYALTY TIER

$100

Jordan Daisy

Happy Birthday!

J

Jordan Daisy

Product Designer

UX

Badge: EMP-8942

Wedding Reception

Please confirm your attendance

Installation

Tokens guide →

Add to your project via CLI (zero dependencies, code you own):

npx bigbullui add receipt

Or install the full npm package:

npm install bigbullui

Usage

import { Receipt } from "@/components/ui/receipt";

<Receipt />

Source code

receipt.tsx

Zero 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 ReceiptProps {
  items: { label: string; price: string }[];
  taxRate?: number;
  total: string;
  className?: string;
}

const FadeIn = "receipt-fade-in";
const ZigZag = "receipt-zig-zag";

export function Receipt({
  items,
  taxRate = 0.1,
  total,
  className,
}: ReceiptProps) {
  const subtotal = items.reduce((sum, it) => sum + parseFloat(it.price), 0);
  const tax = subtotal * taxRate;

  return (
    <div
      className={cn(
        "w-full rounded-lg border border-foreground bg-secondary text-secondary-foreground shadow-sm",
        FadeIn,
        className
      )}
    >
      {/* Receipt header */}
      <div className="border-b border-border/80 pb-4 mb-4">
        <div className="flex items-center justify-between">
          <span className="font-mono text-xs uppercase tracking-widest text-muted-thermal">THERMAL RECEIPT</span>
          <span className="font-mono text-xs uppercase tracking-wider">#{Math.random().toString(36).slice(2, 8).toUpperCase()}</span>
        </div>
      </div>

      {/* Items list with zig-zag bottom */}
      <div className="space-y-2 max-h-96 overflow-y-auto">
        {items.map((it, i) => (
          <div
            key={i}
            className={cn(
              "flex items-baseline py-1.5",
              ZigZag
            )}
          >
            <span className="font-mono text-xs flex-1 line-clamp-1">{it.label}</span>
            <span className="font-mono text-right text-xs opacity-80">{it.price}</span>
          </div>
        ))}
      </div>

      {/* Totals row with dashed separator */}
      <div
        className={cn(
          "flex items-baseline justify-between pt-2 border-t border-dashed border-border/50",
          ZigZag
        )}
      >
        <span className="text-xs font-mono text-muted-foreground">Total</span>
        <span className="font-mono text-right font-bold">{total}</span>
      </div>

      {/* Footer */}
      <div className="mt-3 text-xs uppercase tracking-wider text-muted-foreground">
        Thank you for your purchase!
      </div>
    </div>
  );
}

Props

PropTypeDescription
items{ label: string; price: string }[]Receipt lines (required).
totalstringTotal string (required).
taxRatenumberTax rate decimal.