Coupon Input

Pro

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.

Preview

Installation

npx @lumioui/cli add pro/coupon-input

Usage

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

Also exported: CouponTicket.

Examples

Cart inline

The bottom of a clothing cart in neutral ink.

Checkout sheet

The confirm sheet for an annual note-taking plan, orange.

Gift card balance

Paying for houseplants with a gift card, green.

Coupon wallet

A food app's coupon wallet, orange.

API reference

CouponTicket

Prop Type Default
code* string —
saving* string —
caption string "off"
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.

false
lit boolean

Whether the stub is lit in the accent. Off dims it to grey without dimming the ticket. Default true.

true
revealKey number

Bump to play the applied moment: the perforation punches and the saving switches on.

0
notchClassName string

Colour of the surface under the ticket, so the punched notches read as holes. Default "bg-background".

"bg-background"
className string —

CouponInput

Prop Type Default
onApply*
(code: string) => CouponApplyResult … (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 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".

"Promo code"
applyLabel string

Default "Apply".

"Apply"
invalidMessage string

Message when onApply returns false. Default "That code isn't valid".

"That code isn't valid"
collapsible boolean

Start as a "Have a code?" link that opens the field. Default false.

false
collapsedLabel string

Collapsed link copy. Default "Have a promo code?".

"Have a promo code?"
format (raw: string) => string

Normalise typing — default trims nothing and uppercases. Gift cards can group digits here.

(raw) => raw.toUpperCase()
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".

"bg-background"
removable boolean

Allow removing the applied coupon. Default true.

true
className string —