Gift Card

Pro

A premium gift-card / e-gift visual: a locale-formatted denomination or remaining balance, a redeemable code that is masked, gated behind the host's own authorization and re-hidden on a timer, plus redeemed / void / expired states, a zone-aware expiry, recipient, sender and an optional greeting. Five gradient themes with a decorative ribbon and shimmer.

</>sv-gift-card gift carde-giftvoucherrewardecommercecheckoutbalanceexpiry

Complexity tier: Interactive The primitive bar, plus declared async states, a keyboard model, focus restoration and undo for destructive actions.

import { SvGiftCardComponent } from '@styloviz-pro/commerce';

Demo & usage

Basic usage

Pro

Usage example — open the gallery for the full interactive demo.

Pro

An interactive demo for this component lives in the gallery.

Open live demo

More examples

Reveal the code (two-way)

Pro

Recipient and message

Pro

Answer the reveal gate with your own step-up

Pro

Audit a copy without logging the code

Pro

Remaining balance and a zone-aware expiry

Pro

A spent or cancelled card

Pro

When to use

  • A live preview beside a gift-card purchase or gifting form.
  • An e-gift confirmation email or order receipt.
  • The account wallet, showing a redeemable balance and code.
  • A support console, where the last four identifies the card and nobody needs the code.

Async states

None — this component has nothing to load, so it has no loading, empty or error state to drive.

Inputs

NameTypeDefaultDescription
brandstring'Styloviz'Brand / store name shown top-left.
amountnumber0Gift-card value.
currencystring'USD'ISO 4217 currency code.
localestring'en-US'BCP-47 locale for number formatting.
codestring''Redeemable code. Grouped into blocks of 4 when it has no separators of its own; a punctuated code like `FRESH-GIFT-2K` is printed as written.
recipientstring''Recipient name (To).
senderstring''Sender name (From).
messagestring''Optional greeting / message.
expirystring''Validity line as free text, e.g. "Valid through 12/28". Display only: it carries no expiry logic, so a card whose text has gone stale still reads as active. Pass `expiresAt` to have the card actually expire, and this is used only as the fallback when `expiresAt` is null.
expiresAtDate | string | nullnullWhen the card stops being redeemable. A `Date`, or an ISO string. A string with `Z` or an offset names an instant and is taken as-is; a bare `2028-12-31` or an offsetless `2028-12-31T18:00` is read as wall-clock time in `timeZone`, and a bare date means the END of that day there. See `wallClockToInstant`.
timeZonestring | nullnullThe zone `expiresAt` is written in — the merchant's, normally, since that is whose midnight the terms mean. IANA name, e.g. `'Europe/Berlin'`. Falls back to UTC, never to the reader's own zone: a card must not expire at a different moment for each customer.
nowDate | number | nullnullThe clock expiry is measured against — for tests, and for a host that wants the card to flip while it is on screen by feeding its own tick. Left null it reads `Date.now()` when the inputs change, which is right for a card the reader opens and closes; it does NOT tick on its own, because a permanent interval in a display component costs more than it buys.
statusGiftCardStatus'active'What the host knows about the card. `expired` is not accepted here — it is derived from `expiresAt` — and a declared status wins over both expiry and a zero balance, because "redeemed" says more than "expired" about a card that is both.
balancenumber | nullnullAmount still on the card, when it differs from the face value. Null means the card is worth its face value — not that the balance is unknown, which is indistinguishable to a reader and so is not offered.
requireAuthorizationbooleantrueWhether pressing Reveal needs the host's say-so. On by default: the caller who has already re-authenticated the user says so by setting `revealAuthorized`, and the caller who has not gets an event to act on instead of a code on screen.
revealAuthorizedbooleanfalseThe host has verified the person in front of the screen recently enough to show them the code. Set it after a password prompt, a step-up, a fresh login.
revealTimeoutnumber20000How long a revealed code stays on screen, in ms. 0 disables the auto-hide. A code revealed on a screen someone else can see is a code spent by whoever is behind you, and the reader who reveals it has no reason to remember to hide it again. 20 seconds is long enough to read twelve characters aloud.
allowCopybooleantrueOffer a copy button once the code is actually visible.
variantGiftCardVariant'aurora'Gradient theme.
showCodebooleantrueShow the redeem-code row.
maskCodebooleantrueMask all but the last four of the code until revealed.
privacybooleanfalseDeclare that this session is recorded, screen-shared or replayed. While set, the code stays masked to its last four whatever `maskCode` or `revealed` say, the reveal and copy controls go away, and the card says why. An app-wide `provideSvSensitivePrivacy()` does the same while this is left unset. A declaration, not a detection — a page cannot observe a capture it did not start itself.
withheldLabelstring'Hidden while this screen may be shared'Shown in place of the reveal control while `privacy` withholds the code.
showAmountbooleantrueShow the denomination.
labelstring'Gift Card'Small caption above the amount.
redeemedLabelstring'Redeemed'State chip for a spent card.
expiredLabelstring'Expired'State chip for a card past its expiry.
voidLabelstring'Void'State chip for a cancelled card.
remainingLabelstring'remaining of'Caption on the remaining balance.
revealLabelstring'Reveal'Reveal button, when the code is hidden.
hideLabelstring'Hide'Reveal button, when the code is on screen.
verifyLabelstring'Verify'Reveal button, when the host has still to authorize.
copyLabelstring'Copy code'Copy button.
copiedLabelstring'Copied'Confirmation after a copy.
copyFailedLabelstring'Copy the code manually'Shown when the clipboard is unavailable or refused.
revealedboolean (two-way)falseWhether the masked code is revealed (two-way: `[(revealed)]`). A host writing this is authorization by definition — it is the host's own code making the decision — so the gate applies only to the user-initiated path.

Outputs

EventPayload typeDescription
revealRequestvoidThe user asked to see the code while `requireAuthorization` was on and `revealAuthorized` was off. Step up, then set `revealAuthorized` — or set `revealed` directly once the challenge passes.
codeCopiedGiftCardCopyEventThe code was copied. Log it: see `GiftCardCopyEvent` for what it carries.
revealedChangebooleanEmits the new `revealed` whenever it changes — the output half of `[(revealed)]`.

Customization & theming

  • Five gradient themes (aurora, gold, rose, midnight, mint).
  • Toggle the amount, redeem-code row, code masking and the copy button.
  • Reveal gate: requireAuthorization, revealAuthorized, revealRequest, and revealTimeout for the auto-hide (0 disables it).
  • balance renders what is left against the face value, with a bar; 0 reads as redeemed.
  • status of active / redeemed / void, plus expired derived from expiresAt and timeZone.
  • now injects the clock, for tests or for a card that should flip while it is open.
  • Every label is an input: redeemedLabel, expiredLabel, voidLabel, remainingLabel, revealLabel, hideLabel, verifyLabel, copyLabel, copiedLabel, copyFailedLabel.
  • Recipient, sender, greeting and a validity line.
  • Custom brand name and amount caption.

Best practices

  • Do: Bind the same signals to the card and to your gifting form for a live preview.
  • Do: Answer revealRequest with a real step-up — a password prompt, a passkey, an OTP — then set revealAuthorized.
  • Do: Log codeCopied as it arrives: it carries the last four and the time, which is what an auditor needs.
  • Do: Pass expiresAt with the merchant timeZone rather than a free-text expiry, so the card actually expires — and expires at one moment for every customer.
  • Do: Pass the status your API returned; the card derives expired and treats a zero balance as redeemed on its own.
  • Do: Set a currency and locale so the amount formats correctly for the buyer.
  • Don't: Do not switch requireAuthorization off just to save a click. Leave it on unless the screen is already behind a fresh re-authentication.
  • Don't: Do not put the code in your own audit payload alongside the event — that is exactly the leak the event was shaped to avoid.
  • Don't: Do not rely on the free-text expiry for anything but display; it carries no logic, so a stale line still reads as an active card.
  • Don't: Do not treat this as an input — it is a display; collect the amount and message with your own form controls.

Accessibility

  • The reveal control is a real button whose label says what pressing it will do — verify, reveal, or hide — and it activates on Enter and Space.
  • The copy button is a real button with its own label; the outcome is announced once through a status region, not on every tick.
  • The auto-hide countdown is hidden from assistive tech, since the button label already carries the fact and a per-second live figure would repeat itself.
  • The state chip is text, not a colour: Redeemed, Void and Expired are read out, and the chip declares its own background and ink so the pair is contrast-checkable on all five gradients.
  • A spent card is desaturated with a luminance-preserving grayscale filter rather than dimmed with opacity, so the measured ink still clears AA.
  • The ribbon, gift mark, shimmer and balance bar are decorative and hidden from assistive tech.
  • Each theme carries the one ink measured against all three of its own gradient stops, so contrast holds in light and dark mode.

Feedback on Gift Card

Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.

Loads giscus.app and GitHub — nothing is fetched until you click.