Skip to Content

cart-item

ui

Shopping cart line item with quantity controls and remove action.

Source Code

View the full component source code below.

"use client"

import * as React from "react"
import { Minus, Plus, Trash2 } from "lucide-react"

import { cn } from "@/lib/utils"

function CartItem({
  title,
  image,
  price,
  currency = "USD",
  quantity,
  onQuantityChange,
  onRemove,
  className,
  ...props
}: {
  title: string
  image: string
  price: number
  currency?: string
  quantity: number
  onQuantityChange: (quantity: number) => void
  onRemove: () => void
} & React.ComponentProps<"div">) {
  const formatter = new Intl.NumberFormat(undefined, { style: "currency", currency })

  return (
    <div
      data-slot="cart-item"
      className={cn("flex items-center gap-4 py-4 border-b border-border last:border-b-0", className)}
      {...props}
    >
      <div className="size-16 shrink-0 overflow-hidden rounded-lg bg-muted">
        <img src={image} alt={title} className="size-full object-cover" />
      </div>
      <div className="flex flex-1 flex-col gap-1 min-w-0">
        <h4 className="text-sm font-medium text-foreground truncate">{title}</h4>
        <span className="text-sm text-muted-foreground">{formatter.format(price)} each</span>
      </div>
      <div className="flex items-center gap-1.5">
        <button
          type="button"
          onClick={() => onQuantityChange(Math.max(1, quantity - 1))}
          disabled={quantity <= 1}
          className="flex size-8 items-center justify-center rounded-lg border border-border text-muted-foreground hover:bg-muted transition-colors disabled:opacity-50"
          aria-label="Decrease quantity"
        >
          <Minus className="size-3.5" />
        </button>
        <span className="w-8 text-center text-sm font-medium tabular-nums">{quantity}</span>
        <button
          type="button"
          onClick={() => onQuantityChange(quantity + 1)}
          className="flex size-8 items-center justify-center rounded-lg border border-border text-muted-foreground hover:bg-muted transition-colors"
          aria-label="Increase quantity"
        >
          <Plus className="size-3.5" />
        </button>
      </div>
      <span className="w-20 text-right text-sm font-semibold tabular-nums">{formatter.format(price * quantity)}</span>
      <button
        type="button"
        onClick={onRemove}
        className="shrink-0 p-1.5 text-muted-foreground hover:text-destructive rounded-md transition-colors"
        aria-label={`Remove ${title}`}
      >
        <Trash2 className="size-4" />
      </button>
    </div>
  )
}

export { CartItem }

Installation

npx shadcn@latest add https://registry.mukoko.com/api/v1/ui/cart-item

API

Fetch this component's metadata and source code from the registry API.

GET/api/v1/ui/cart-item

Source

components/ui/cart-item.tsx