Detent web components
By Shane Logsdon

Media & effects

Wallet Card

Implemented

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

  • disabled recorded state; no setter
  • reduced motion recorded 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

  • balance
  • balance-label
  • button-label
  • card-last-four
  • card-type
  • disabled

Properties

  • balance
  • balanceLabel
  • buttonLabel
  • cardLastFour
  • cardType
  • disabled
  • onUseWallet

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.tsx sha256 6f6338bd0227…

Native files

The native module and its artifacts:

  • src/components/wallet-card/wallet-card.ts
  • src/components/wallet-card/styles.css
  • src/components/wallet-card/define.ts
  • docs/components/wallet-card.md
  • site/examples/wallet-card.ts
  • tests/browser/wallet-card.spec.ts
  • evidence/components/wallet-card.md

API

Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.

Attributes

Attributes
AttributePropertyTypeDefaultNotes
balancebalancestring'$4,566.00'Kebab-case attribute; camelCase property.
balance-labelbalanceLabelstring'Total Balance'Kebab-case attribute; camelCase property.
button-labelbuttonLabelstring'Use Wallet'Kebab-case attribute; camelCase property.
card-last-fourcardLastFourstring'3040'Kebab-case attribute; camelCase property.
card-typecardTypestring'Mastercard'Kebab-case attribute; camelCase property.
disableddisabledbooleanfalsePresence semantics: present means true, absent means false.

Properties

Properties
PropertyTypeDefaultNotes
balancestring'$4,566.00'Property-only: assign from script; not accepted as an attribute.
balanceLabelstring'Total Balance'Property-only: assign from script; not accepted as an attribute.
buttonLabelstring'Use Wallet'Property-only: assign from script; not accepted as an attribute.
cardLastFourstring'3040'Property-only: assign from script; not accepted as an attribute.
cardTypestring'Mastercard'Property-only: assign from script; not accepted as an attribute.
disabledbooleanfalseProperty-only: assign from script; not accepted as an attribute.
onUseWallet() => voidundefinedProperty-only: assign from script; not accepted as an attribute.

Events

Events
EventUpstream propPayload typeNotes
detent-use-walletonUseWallet() => voidComposed, 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).
Previous: Wallet Balance Next: Theme Switcher

Docs

Components

Project