Evan Yudistira

Receipt Printer

Component

About

Thermal receipt printer that feeds any receipt out of its slot in 12px steps, with body shake, skip, haptics and reduced-motion support.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Receipt Printer to your project and fits it to your theme.

Code

How Receipt Printer is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";

import { ReceiptPrinter } from "@/components/ui/receipt-printer";

const people = [
  { name: "Evan", item: "1/2 Nasi goreng", subtotal: 40000 },
  { name: "Dita", item: "1/2 Nasi goreng", subtotal: 40000 },
  { name: "Rio", item: "Sate ayam", subtotal: 50000 },
];

const amount = (value: number) =>
  new Intl.NumberFormat("id-ID", { style: "currency", currency: "IDR", maximumFractionDigits: 0 }).format(value);

const total = (subtotal: number) => subtotal * 1.05 * 1.1;

export default function Demo() {
  return (
    <div className="flex min-h-screen w-full justify-center bg-background px-4 py-10">
      <ReceiptPrinter className="w-full max-w-[420px]">
        <header className="thermal-header">
          <span className="thermal-mark" aria-hidden="true" />
          <h3>Patungan</h3>
          <p className="thermal-place">Dinner</p>
          <div className="thermal-meta">
            <span>Date</span>
            <span>Oct 12, 2026 · 7:30 PM</span>
          </div>
          <div className="thermal-divider thermal-divider-double" aria-hidden="true" />
        </header>
        {people.map((person) => (
          <section key={person.name} className="thermal-person">
            <h4>{person.name}</h4>
            <div className="thermal-column-labels">
              <span>Item</span>
              <span>Qty</span>
              <span>Amount</span>
            </div>
            <div className="thermal-item">
              <span title={person.item}>
                {person.item.startsWith("1/2 ") ? (
                  <>
                    <span className="thermal-fraction">1/2 </span>
                    {person.item.slice(4)}
                  </>
                ) : (
                  person.item
                )}
              </span>
              <span className="thermal-qty">1</span>
              <span>{amount(person.subtotal)}</span>
            </div>
            <div className="thermal-breakdown">
              <div className="thermal-line thermal-secondary">
                <span>Subtotal</span>
                <i />
                <span>{amount(person.subtotal)}</span>
              </div>
              <div className="thermal-line thermal-secondary">
                <span>Service 5%</span>
                <i />
                <span>{amount(person.subtotal * 0.05)}</span>
              </div>
              <div className="thermal-line thermal-secondary">
                <span>Tax 10%</span>
                <i />
                <span>{amount(person.subtotal * 1.05 * 0.1)}</span>
              </div>
              <p className="thermal-note">Tax not included — added on top of menu prices</p>
            </div>
            <div className="thermal-line thermal-total">
              <span>Total</span>
              <i />
              <span className="thermal-person-amount">{amount(total(person.subtotal))}</span>
            </div>
          </section>
        ))}
        <footer className="thermal-footer">
          <div className="thermal-divider" aria-hidden="true" />
          <div className="thermal-line thermal-grand-total">
            <span>Grand total</span>
            <i />
            <span className="thermal-amount">
              {amount(people.reduce((sum, person) => sum + total(person.subtotal), 0))}
            </span>
          </div>
          <div className="thermal-meta">
            <span>Paid by</span>
            <span className="thermal-payer">Evan</span>
          </div>
          <div className="thermal-divider thermal-divider-double" aria-hidden="true" />
          <div className="thermal-meta">
            <span>Receipt</span>
            <span className="thermal-receipt-id">#DEMO-012</span>
          </div>
          <p className="thermal-thanks">
            Thank you
            <br />
            See you at the next meal.
          </p>
        </footer>
      </ReceiptPrinter>
    </div>
  );
}