Dots

Card Peek

The top half of a dark payment card with its mark, network, label and last four digits.

Virtual · USDCard ending in 4242
import { CardPeek } from "@/components/ui/card-peek"

/** A neutral issuer mark for the demo. Pass your own logo in a product. */

The CardPeek component shows the top half of a payment card, as if it were sliding out of a pocket: the issuer mark, the network, a label and the last four digits. It stays dark in both themes. Use it to show which card a screen is about, under a balance or at the top of a card page, without a full card face. For a general content surface, use Card.

Installation

pnpm dlx shadcn@latest add @dots/card-peek

Usage

import { CardPeek } from "@/components/ui/card-peek"
<CardPeek
  last4="4242"
  label="Virtual · USD"
  mark={<IssuerLogo />}
  network={<NetworkLogo />}
/>

Features

  • A single component: no parts to compose
  • Issuer mark and network logo slots; the card draws no logo of its own
  • The last four digits with a full screen-reader phrase
  • A frozen state that dims the face and says "Frozen" in words
  • Static by default, or one link with href, or one button with onPress
  • Dark in both themes

Frozen

Set frozen to dim the face and show a "Frozen" badge. Change the badge text with frozenLabel.

Virtual · USDCard ending in 4242Frozen
"use client"

import * as React from "react"

Pressable

Pass onPress to make the whole peek one button, such as opening the card details sheet. Pass href instead to make it one link to the card page. Use one or the other, not both.

Press the card to see its details

"use client"

import * as React from "react"
<CardPeek last4="0917" label="USD" mark={<IssuerLogo />} href="/cards/0917" />

Before the card has a number

Leave out last4 while the card is being ordered. The peek shows the label and logos without a number.

Virtual · USD
import { CardPeek } from "@/components/ui/card-peek"

/** A neutral issuer mark for the demo. Pass your own logo in a product. */

Accessibility

A static CardPeek is a <div>. With href it renders a React Aria Link, and with onPress a React Aria Button, so it works with a keyboard, a pointer and touch.

The number

The masked number is hidden from assistive tech and replaced by a full phrase, "Card ending in 4242" by default. Use numberLabel to change the phrase, for example to translate it.

<CardPeek last4="4242" numberLabel={(digits) => `Card ending in ${digits}`} />

Logos

Pass decorative logos with aria-hidden="true". If the network matters, name it in label or in the peek's aria-label.

Pressable peeks

When the peek is a link or a button, its name comes from its text. Pass aria-label when the action needs saying too, such as "Card ending in 0917, open details".

Frozen

The frozen state is shown as the word "Frozen" with an icon, not by dimming alone.

API Reference

CardPeek

The card peek. Without href or onPress it accepts all <div> props. With href it accepts React Aria Link props, and with onPress React Aria Button props.

PropTypeDefaultDescription
last4string-Last four digits of the card number. Leave it out before the card has a number.
numberLabel(digits: string) => string-Screen-reader text for the number. Reads "Card ending in" and the digits by default.
labelReact.ReactNode-What the card is, shown above the number, e.g. "Virtual · USD".
markReact.ReactNode-Issuer mark, top start.
networkReact.ReactNode-Payment network logo, top end.
frozenbooleanfalseDims the face and shows the frozen badge.
frozenLabelstring"Frozen"Text of the frozen badge.
hrefstring-Makes the peek one link. Cannot be used with onPress.
onPress(e: PressEvent) => void-Makes the peek one button. Cannot be used with href.
classNamestring-Additional classes to apply to the root.