## Coupon Field (S—100)

A promo-code row: Apply shows a spinner, a valid code becomes a removable chip and the total counts down.

- URL: https://sundaeui.dev/components/coupon-field
- Category: Checkout & payments · Art direction: Refined
- Access: Free (no account needed)
- Stack: React 18+, TypeScript, plain CSS; dependencies: none
- Install: `npx shadcn@latest add https://sundaeui.dev/r/coupon-field.json`
- Tags: coupon, cart, code, checkout, promo, discount

Collapsed it is a single “Have a code?” link. Open, the code is upper-cased as you type; Apply checks it with your async validator.
A valid code turns into a chip with the saving, and the order total animates to its new value. An invalid one shakes the field and says why.

### Usage

```tsx
import { CouponField } from '@/components/sundae/coupon-field'

<CouponField />
```

### Props

- `subtotal` (`number`, required): Subtotal in cents.
- `validate` (`(code: string) => Promise<{ ok: true; percent: number } | { ok: false; error: string }>`, required): Checks a code.
- `currency` (`string`, default `'USD'`): ISO currency.
- `fill` (`'dark' | 'light'`, default `'dark'`): Surface: dark or light.

### When to use

- Checkout summaries and cart drawers.

### When not to use

- Where codes are rare: an exposed field invites people to go hunting for one.

### Accessibility

- The code field is labelled and errors use role="alert".
- The applied chip’s remove button names the code.
- Reduced motion removes the movement and keeps every state change.
