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.
No interactive demo is registered for this component yet — the source is shown directly.
"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 }
The variants, sizes, and props surfaced by the registry. Each is sourced from the Supabase component_docs table.
Hit the registry API live and see the JSON the shadcn CLI consumes when it installs this component.
/api/v1/ui/cart-itemnpx shadcn@latest add https://mzizi.dev/api/v1/ui/cart-itemcomponents/ui/cart-item.tsx