Media & effects
Wallet Card
Dark wallet card with pointer-driven cyan shine
detent-wallet-card
Port status
- Catalog status
- implemented
- Origin
- upstream
- Phase
- 2
- Wave
- phase-2-cards
- Group
- Media & effects
4.2 KB gzip for the class module
Variants
Move the pointer over a card to see the cyan shine follow it. Tab reaches the action button and Enter or Space activates it. The last card is disabled: the label stays at full opacity and only the button surface is muted. With reduced motion the shine is never tracked.
Recorded states
disabledrecorded state; no setterreduced motionrecorded state; no setter
Usage
Import
import '/components/wallet-card/define.js';
// or register it yourself
import { DetentWalletCard } from '/components/wallet-card/wallet-card.js';
Attributes
balancebalance-labelbutton-labelcard-last-fourcard-typedisabled
Properties
balancebalanceLabelbuttonLabelcardLastFourcardTypedisabledonUseWallet
Slots
No slots are recorded for this component.
Events
detent-use-wallet— {}
Example
Runnable example: site/examples/wallet-card.ts. The snippet below is generated from the catalogued attributes.
<detent-wallet-card
balance="$4,566.00"
balance-label="Total Balance"
button-label="Use Wallet"
card-last-four="3040"
card-type="Mastercard"
disabled
></detent-wallet-card>
Property-only values
const element = document.querySelector('detent-wallet-card');
if (element !== null) {
// onUseWallet: () => void
element.onUseWallet = () => {};
}
Source
The pinned upstream source for this row:
src/components/ui/WalletCard.tsxsha256 6f6338bd0227…
Native files
The native module and its artifacts:
src/components/wallet-card/wallet-card.tssrc/components/wallet-card/styles.csssrc/components/wallet-card/define.tsdocs/components/wallet-card.mdsite/examples/wallet-card.tstests/browser/wallet-card.spec.tsevidence/components/wallet-card.md
API
Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.
Attributes
| Attribute | Property | Type | Default | Notes |
|---|---|---|---|---|
balance | balance | string | '$4,566.00' | Kebab-case attribute; camelCase property. |
balance-label | balanceLabel | string | 'Total Balance' | Kebab-case attribute; camelCase property. |
button-label | buttonLabel | string | 'Use Wallet' | Kebab-case attribute; camelCase property. |
card-last-four | cardLastFour | string | '3040' | Kebab-case attribute; camelCase property. |
card-type | cardType | string | 'Mastercard' | Kebab-case attribute; camelCase property. |
disabled | disabled | boolean | false | Presence semantics: present means true, absent means false. |
Properties
| Property | Type | Default | Notes |
|---|---|---|---|
balance | string | '$4,566.00' | Property-only: assign from script; not accepted as an attribute. |
balanceLabel | string | 'Total Balance' | Property-only: assign from script; not accepted as an attribute. |
buttonLabel | string | 'Use Wallet' | Property-only: assign from script; not accepted as an attribute. |
cardLastFour | string | '3040' | Property-only: assign from script; not accepted as an attribute. |
cardType | string | 'Mastercard' | Property-only: assign from script; not accepted as an attribute. |
disabled | boolean | false | Property-only: assign from script; not accepted as an attribute. |
onUseWallet | () => void | undefined | Property-only: assign from script; not accepted as an attribute. |
Events
| Event | Upstream prop | Payload type | Notes |
|---|---|---|---|
detent-use-wallet | onUseWallet | () => void | Composed, bubbles; fires only for a user action. |
Slots
No slots are recorded for this component.
CSS customisation
- `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
- React callback props become typed composed CustomEvents; programmatic state assignment emits none.
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- Framer useMotionValue/useMotionTemplate become CSS custom properties written from a coalesced rAF (one write per paint, none while document.hidden) and a CSS radial gradient (220px cyan circle at 18%, matching the upstream stops).
- whileTap becomes CSS :active 0.97 and the hover lift becomes a CSS transform.
- The palette derives from --detent-color-* tokens instead of hard-coded dark Tailwind gradients (hex fallbacks reproduce upstream).
- The decorative iOS-style toggle stays purely decorative (aria-hidden div, not focusable, no role) and is documented as artwork, not a control.
- Upstream tagline says dark; the native card follows the Detent theme (light by default).
What it does
A painted wallet card: a blue radial-gradient surface with a diagonal specular sweep and outer glow, a pointer-driven cyan shine, a live balance, a decorative iOS-style toggle and a native action button.
Upstream behaviour
- Live balance figure with iOS-style toggle and primary action button
- Painted blue radial-gradient surface with diagonal specular sweep and outer glow
- Pointer-driven cyan shine — same MotionValue architecture as SpotlightCard
- Spring-tap response on the action button (0.97 scale)
- Full keyboard support and visible focus outline on the button
- Respects prefers-reduced-motion — shine is skipped, button tap is disabled
- Responsive aspect ratio; surface adapts without layout shift
Differences from upstream
- `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
- React callback props become typed composed CustomEvents; programmatic state assignment emits none.
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- Framer useMotionValue/useMotionTemplate become CSS custom properties written from a coalesced rAF (one write per paint, none while document.hidden) and a CSS radial gradient (220px cyan circle at 18%, matching the upstream stops).
- whileTap becomes CSS :active 0.97 and the hover lift becomes a CSS transform.
- The palette derives from --detent-color-* tokens instead of hard-coded dark Tailwind gradients (hex fallbacks reproduce upstream).
- The decorative iOS-style toggle stays purely decorative (aria-hidden div, not focusable, no role) and is documented as artwork, not a control.
- Upstream tagline says dark; the native card follows the Detent theme (light by default).