# Coupon Input

Promo and gift code field that turns into a perforated ticket showing your saving when the code works, and explains why when it doesn’t. The ticket also works on its own for coupon wallets.

> Composed · Pro · Forms & Inputs — React Native, Expo Go compatible.

## Install

```bash
npx @lumioui/cli add pro/coupon-input
```

## Import

```tsx
import { CouponTicket, CouponInput } from "@/components/ui/coupon-input/coupon-input";
```

## Variants

- `cart-inline` — Cart inline: `npx @lumioui/cli add pro/coupon-input-cart-inline`
- `checkout-sheet` — Checkout sheet: `npx @lumioui/cli add pro/coupon-input-checkout-sheet`
- `gift-card` — Gift card balance: `npx @lumioui/cli add pro/coupon-input-gift-card`
- `wallet` — Coupon wallet: `npx @lumioui/cli add pro/coupon-input-wallet`

## Props

### CouponTicket

| Prop | Type | Notes |
| --- | --- | --- |
| `code` | `string` | — |
| `saving` | `string` | — |
| `caption?` | `string` | — |
| `title?` | `string` | Bold line above the code — "Spring sale". Falls back to the code alone. |
| `description?` | `string` | — |
| `expires?` | `string` | Expiry or condition line — "Ends Sunday". |
| `onRemove?` | `() => void` | Shows a remove (×) button. |
| `action?` | `{ label: string` | A trailing text action — "Apply", "Applied". |
| `onPress?` | `() => void` | — |
| `active?` | `boolean }` | — |
| `disabled?` | `boolean` | Greys the stub and dims the ticket — expired or ineligible. |
| `lit?` | `boolean` | Whether the stub is lit in the accent. Off dims it to grey without dimming the ticket. Default true. |
| `revealKey?` | `number` | Bump to play the applied moment: the perforation punches and the saving switches on. |
| `notchClassName?` | `string` | Colour of the surface under the ticket, so the punched notches read as holes. Default "bg-background". |
| `className?` | `string` | — |

### CouponInput

| Prop | Type | Notes |
| --- | --- | --- |
| `onApply` | `(code: string) => CouponApplyResult | Promise<CouponApplyResult>` | Validate a code. Return the applied coupon, a rejection message, or false. May be async. |
| `applied?` | `AppliedCoupon | null` | Applied coupon (controlled). |
| `defaultApplied?` | `AppliedCoupon | null` | — |
| `onAppliedChange?` | `(coupon: AppliedCoupon | null) => void` | — |
| `onResolved?` | `(coupon: AppliedCoupon | null) => void` | Fires after an accepted code has become the ticket and held — the moment to roll totals. Also fires with null on remove. |
| `placeholder?` | `string` | Default "Promo code". |
| `applyLabel?` | `string` | Default "Apply". |
| `invalidMessage?` | `string` | Message when onApply returns false. Default "That code isn't valid". |
| `collapsible?` | `boolean` | Start as a "Have a code?" link that opens the field. Default false. |
| `collapsedLabel?` | `string` | Collapsed link copy. Default "Have a promo code?". |
| `format?` | `(raw: string) => string` | Normalise typing — default trims nothing and uppercases. Gift cards can group digits here. |
| `maxLength?` | `number` | — |
| `ticketTitle?` | `string` | Bold line on the applied ticket — "Spring sale", "Gift card". |
| `notchClassName?` | `string` | Surface colour under the ticket (for the notches). Default "bg-background". |
| `removable?` | `boolean` | Allow removing the applied coupon. Default true. |
| `className?` | `string` | — |

## Icons rendered

- `check` — /icons.html?i=check
- `x` — /icons.html?i=x
- `tag` — /icons.html?i=tag
- `alert-triangle` — /icons.html?i=alert-triangle

Source: https://lumioui.com/components/coupon-input