nyuchimzizi
Mzizi — an open-architecture project of the Bundu Foundation, operated and developed by Nyuchi. Built on the Five African Minerals palette.
Built by Nyuchi Africav4.0.39
Shopping cart line item with quantity controls and remove action.
View the full component source code below.
"use client"
import * as React from "react"
import { Minus, Plus, Trash2 } from "@/lib/icons"
import { cn } from "@/lib/utils"
function CartItem({ loading = false,
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 })
if (loading) return (<div data-slot="cart-item" data-portal="https://design.nyuchi.com/components/cart-item" data-loading className="animate-pulse rounded-[var(--radius-lg,14px)] bg-card p-4 ring-1 ring-foreground/10 space-y-3"><div className="h-4 w-2/3 rounded bg-muted" /><div className="h-3 w-full rounded bg-muted" /><div className="h-3 w-1/2 rounded bg-muted" /></div>)
return (
<div
data-slot="cart-item"
className={cn(
"flex items-center gap-4 border-b border-border py-4 last:border-b-0",
className
)}
{...props}
>
<div className="size-16 shrink-0 overflow-hidden rounded-[var(--radius-lg,14px)] bg-muted">
<img src={image} alt={title} className="size-full object-cover" />
</div>
<div className="flex min-w-0 flex-1 flex-col gap-1">
<h4 className="truncate text-sm font-medium text-foreground">{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-[var(--radius-lg,14px)] border border-border text-muted-foreground transition-colors hover:bg-muted 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-[var(--radius-lg,14px)] border border-border text-muted-foreground transition-colors hover:bg-muted"
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 rounded-[var(--radius-md,12px)] p-1.5 text-muted-foreground transition-colors hover:text-destructive"
aria-label={`Remove ${title}`}
>
<Trash2 className="size-4" />
</button>
</div>
)
}
export { CartItem }
npx shadcn@latest add https://mzizi.dev/api/v1/ui/cart-itemFetch this component's metadata and source code from the registry API.
/api/v1/ui/cart-itemcomponents/ui/cart-item.tsx