Full-page Cart
A two-column cart page with line items and an order summary that drops below the items on mobile.
3 个框架中级
A right-anchored cart panel over a dimmed backdrop, with line items, a subtotal and a checkout button.
<!--
The panel is scoped to its own relative container (absolute inset-0), not
fixed to the viewport - this is a demo drawer, not a global one. In production
swap the wrapper for a fixed overlay and move focus into the panel on open.
The backdrop is a real <button> so a click OR a keypress closes the drawer;
a bare <div> onClick is a mouse-only affordance.
-->
<div class="relative h-[30rem] w-full overflow-hidden rounded-xl border border-gray-200 bg-gray-50 dark:border-gray-800 dark:bg-gray-950">
<button type="button" class="absolute inset-0 z-10 bg-black/40" aria-label="Close cart"></button>
<aside
class="absolute inset-y-0 right-0 z-20 flex w-full max-w-sm flex-col bg-white shadow-xl dark:bg-gray-900"
role="dialog"
aria-label="Shopping cart"
>
<header class="flex items-center justify-between border-b border-gray-200 px-4 py-3 dark:border-gray-800">
<h2 class="text-sm font-semibold text-gray-900 dark:text-gray-100">Your cart (2)</h2>
<button
type="button"
class="-mr-1 flex h-9 w-9 items-center justify-center rounded-md text-gray-500 hover:bg-gray-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 dark:text-gray-400 dark:hover:bg-gray-800"
aria-label="Close cart"
>
<svg viewBox="0 0 20 20" fill="none" class="h-5 w-5" aria-hidden="true"><path d="M6 6l8 8M14 6l-8 8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
</button>
</header>
<ul class="flex-1 divide-y divide-gray-100 overflow-y-auto dark:divide-gray-800">
<li class="flex gap-3 p-4">
<div class="h-16 w-16 flex-none rounded-lg bg-gradient-to-br from-sky-400 to-indigo-500" aria-hidden="true"></div>
<div class="min-w-0 flex-1">
<p class="truncate text-sm font-medium text-gray-900 dark:text-gray-100">Aero Runner</p>
<p class="text-xs text-gray-500 dark:text-gray-400">Qty 1</p>
</div>
<div class="text-right text-sm font-semibold tabular-nums text-gray-900 dark:text-gray-100">$120.00</div>
</li>
<li class="flex gap-3 p-4">
<div class="h-16 w-16 flex-none rounded-lg bg-gradient-to-br from-rose-400 to-orange-500" aria-hidden="true"></div>
<div class="min-w-0 flex-1">
<p class="truncate text-sm font-medium text-gray-900 dark:text-gray-100">Trail Cap</p>
<p class="text-xs text-gray-500 dark:text-gray-400">Qty 2</p>
</div>
<div class="text-right text-sm font-semibold tabular-nums text-gray-900 dark:text-gray-100">$50.00</div>
</li>
</ul>
<footer class="border-t border-gray-200 p-4 dark:border-gray-800">
<div class="flex items-center justify-between text-sm">
<span class="text-gray-600 dark:text-gray-400">Subtotal</span>
<span class="font-semibold tabular-nums text-gray-900 dark:text-gray-100">$170.00</span>
</div>
<a href="#" class="mt-3 flex w-full items-center justify-center rounded-lg bg-blue-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-blue-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-900">Checkout</a>
</footer>
</aside>
</div>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
items必填 | CartLine[] | - | 要渲染的项目数组。 |
open | boolean | true | 组件当前是否显示。 |
currency | string | '$' | Currency |
onClose | () => void | - | 当组件请求关闭时调用 -- Escape 键、遮罩层或关闭按钮。 |
className | string | - | 合并到根元素上的额外类名。 |
The panel is scoped to its own relative container in this demo rather than fixed to the viewport - swap the wrapper for a fixed overlay and move focus into the panel on open for production. Feed `items` and the count, subtotal and prices are all derived; the backdrop is a real `<button>` so a keypress closes it too.