Cart Item

Commerce

Shopping cart line item with quantity controls.

Preview

1
$0.00

1
$0.00

Usage

example.jsx
import { CartItem } from "@/components/ui/cart-item";

export default function Example() {
  return <CartItem />;
}

Source Code

Copy this file into components/ui/cart-item.jsx in your project.

cart-item.jsx
import { forwardRef } from "react";
import { cn } from "@/lib/utils";

const CartItem = forwardRef(({ className, item = {}, onUpdateQty, onRemove, ...props }, ref) => (
  <div ref={ref} className={cn("flex items-center gap-4 border-b py-4", className)} {...props}>
    <div className="h-16 w-16 shrink-0 overflow-hidden rounded-md bg-muted">
      {item.image && <img src={item.image} alt={item.name} className="h-full w-full object-cover" />}
    </div>
    <div className="flex-1 min-w-0">
      <h4 className="truncate font-medium">{item.name}</h4>
      {item.variant && <p className="text-xs text-muted-foreground">{item.variant}</p>}
      <div className="mt-1 flex items-center gap-2">
        <button onClick={() => onUpdateQty?.(item, Math.max(0, (item.qty || 1) - 1))} className="flex h-6 w-6 items-center justify-center rounded border text-xs hover:bg-accent">−</button>
        <span className="text-sm font-medium">{item.qty || 1}</span>
        <button onClick={() => onUpdateQty?.(item, (item.qty || 1) + 1)} className="flex h-6 w-6 items-center justify-center rounded border text-xs hover:bg-accent">+</button>
      </div>
    </div>
    <div className="text-right">
      <div className="font-semibold">${((item.price || 0) * (item.qty || 1)).toFixed(2)}</div>
      {onRemove && <button onClick={() => onRemove(item)} className="mt-1 text-xs text-destructive hover:underline">Remove</button>}
    </div>
  </div>
));
CartItem.displayName = "CartItem";

export { CartItem };

Quick Install

Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.

npm install clsx tailwind-merge