- Accordion
- Action Bar
- Action Toast
- Alert Banner
- Alert Dialog
- Alert
- Alphabet Index
- Amount Field
- Aspect Ratio
- Attachment
- Availability List
- Avatar
- Badge
- Bank Card
- Breadcrumb
- Bubble
- Button Group
- Button
- Calendar
- Camera Frame
- Card Design Picker
- Card Details
- Card Peek
- Card Stack
- Card
- Carousel
- Chart
- Chat Thread
- Checkbox
- Chip Group
- Choice Tile
- Code Block
- Code Dots
- Collapsible
- Combobox
- Command
- Context Menu
- Copy Field
- Countdown
- Country Select
- Data Table
- Date Field
- Date Picker
- Date Range Picker
- Dialog
- Direction
- Document Paper
- Drawer
- Dropdown Menu
- Empty
- Entity Avatar
- Field
- File Trigger
- File Upload Item
- Hover Card
- Input Group
- Input OTP
- Input
- Item
- Kbd
- Key Value
- Keypad
- Label
- Live Region
- Marker
- Message Scroller
- Message
- Money Amount
- Native Select
- Number Field
- Pagination
- Percent Split Editor
- Phone Field
- Popover
- Progress
- QR Code
- Questionnaire
- Radio Group
- Range Histogram
- Rating
- Resizable
- Scroll Area
- Search Field
- Select
- Separator
- Share Bar
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Sortable List
- Spinner
- Status Timeline
- Step Header
- Steps List
- Swipe Row
- Switch
- Table
- Tabs
- Text Field
- Textarea
- Tier Ladder
- Toggle Group
- Toggle
- Token Search Field
- Tooltip
- Trace
- Transaction Row
- Usage Meter
import { BankCard } from "@/components/ui/bank-card"
/** A neutral issuer mark for the demo. Pass your own logo in a product. */The BankCard component draws a payment card at the ISO 1.586:1 ratio: a plastic design with the issuer mark, the last four digits and the network logo, and nothing else on the face. It comes with 24 built-in designs and takes your own skin with SVG artwork. Use it on card pages, in card lists and in design pickers. To show only the top half of a card under a balance, use CardPeek. To pile several cards, use CardStack.
Installation#
pnpm dlx shadcn@latest add @dots/bank-card
Usage#
import { BankCard } from "@/components/ui/bank-card"<BankCard skin="midnight" mark={<IssuerLogo />} network="visa" last4="4242" />Features#
- 24 built-in plastic designs, or your own skin with SVG artwork
- Issuer mark slot; the card draws no logo of its own
- Inline Visa, Mastercard and Mir logos that pick a light or dark print to suit the plastic
- The last four digits with a full screen-reader phrase
- Three sizes: the card, a mini thumbnail and a swatch for pickers
- Scales with its width, so a width class is all you need to resize it
- A back side for your own content
- Looks the same in light and dark themes
Sizes#
size="default" is the card itself, 340px wide, with the mark, the number and the network logo. mini is a 96px thumbnail for lists and headers with the mark and the logo. swatch is a 96px tile with the mark only, for design pickers.
import { BankCard } from "@/components/ui/bank-card"
/** A neutral issuer mark for the demo. Pass your own logo in a product. */Width#
Every size stops at its natural width and never grows wider than its parent. Set a width class, such as w-[220px] or w-14, to change it: the radius, padding, mark, number and logo scale with the card. Set fluid to fill the parent instead. fluid wins over a width class, so use one or the other.
import { BankCard } from "@/components/ui/bank-card"
/** A neutral issuer mark for the demo. Pass your own logo in a product. */In a flex row, align cards with items-start, items-center or items-end. The default stretch makes a card taller than its ratio.
Networks#
Set network to "visa", "mastercard" or "mir". The logo is printed white on dark plastics and in colour or black on light ones. Leave network out to show no logo, for example on an offer.
import { BankCard, type CardNetwork } from "@/components/ui/bank-card"
/** A neutral issuer mark for the demo. Pass your own logo in a product. */Use CardNetworkLogo to show the same logos outside a card. It has no height of its own; size it with a class.
<CardNetworkLogo network="mastercard" className="h-6" />Designs#
Pass a built-in id to skin. cardSkins lists the ids in display order, and getCardSkin(id).name gives the display name.
- Onyx
- Eclipse
- Graphite
- Carbon
- Titanium
- Chrome
- Pearl
- Midnight
- Cobalt
- Wave
- Emerald
- Lime
- Aurora
- Sunset
- Lava
- Gold
- Rose
- Holo
- Prism
- Topo
- Blueprint
- Dune
- Ultraviolet
- Frost
import { BankCard, cardSkins, getCardSkin } from "@/components/ui/bank-card"
/** A neutral issuer mark for the demo. Pass your own logo in a product. */Custom skin#
Pass a CardSkin object to draw your own plastic. background takes any CSS background. art returns SVG children on a 320×202 canvas; prefix every SVG id with the id it receives, so several cards can share a page. Set light for pale plastics, which get dark ink and dark logos, and logos to override a logo print.
import { BankCard, type CardSkin } from "@/components/ui/bank-card"
/** A neutral issuer mark for the demo. Pass your own logo in a product. */const coral: CardSkin = {
id: "coral",
name: "Coral",
ink: "#fff",
background: "linear-gradient(150deg, #ff7a59, #8e2d6f)",
art: (id) => (
<>
<radialGradient id={`${id}-glow`}>…</radialGradient>
<circle cx="250" cy="40" r="120" fill={`url(#${id}-glow)`} />
</>
),
}Design packs#
Ten more series of 20 designs each ship as separate registry items, so an app only carries the ones it uses: card-designs-art, -city, -geo, -grad, -lux, -mono, -nature, -play, -sig and -tech. Each exports one object, such as cardDesignsArt, with an id, a title and its skins, ready for skin and for CardDesignPicker. Import a pack in a client component, because skins carry art functions.
"use client"
import * as React from "react"pnpm dlx shadcn@latest add @dots/card-designs-art
import { cardDesignsArt } from "@/lib/card-designs-art"<BankCard skin={cardDesignsArt.skins[0]} network="visa" last4="4242" />Back side#
Set side="back" to draw the plastic without artwork, mark, number or logo. Its children are laid out in a column with the card's padding and follow the skin's ink. Use it for messages such as a card on its way.
import { BankCard } from "@/components/ui/bank-card"
export function BankCardBack() {Accessibility#
BankCard is a <div> with no role of its own. Wrap it in a link or a button when it opens something, and name that control.
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.
<BankCard last4="4242" numberLabel={(digits) => `Card ending in ${digits}`} />Logos and artwork#
The network logo is an SVG with role="img" and the network's name, so it is read as "Visa", "Mastercard" or "Mir". The artwork and the grain are hidden from assistive tech. Pass your issuer mark with aria-hidden="true" when it is decorative.
Decorative cards#
When a card only repeats what nearby text says, such as a thumbnail next to "Ending in 4242", pass aria-hidden="true" to the card.
API Reference#
BankCard#
The card. Accepts all <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
skin | CardSkinId | CardSkin | "onyx" | A built-in design id or your own skin. |
size | "default" | "mini" | "swatch" | "default" | The card, a thumbnail with mark and logo, or a picker tile with the mark only. |
side | "front" | "back" | "front" | "back" draws the plastic only and lays out children. |
mark | React.ReactNode | - | Issuer logo, top start. It fills the mark height; use currentColor to follow the ink. |
network | "visa" | "mastercard" | "mir" | - | Payment network logo, bottom end. Not shown on swatches. |
last4 | string | - | Last four digits, shown on the default size. Leave it out for offers and previews. |
numberLabel | (digits: string) => string | - | Screen-reader text for the number. Reads "Card ending in" and the digits by default. |
fluid | boolean | false | Fill the parent width. Wins over a width class. |
children | React.ReactNode | - | Content of the back side. |
className | string | - | Additional classes to apply to the root, such as a width. |
CardNetworkLogo#
A network logo as inline SVG. Accepts all <svg> props except children and viewBox.
| Prop | Type | Default | Description |
|---|---|---|---|
network | "visa" | "mastercard" | "mir" | - | Required. Which network. |
variant | "white" | "black" | "color" | "color" | One-colour print or the network's own colours. |
className | string | - | Size it here, e.g. h-6. The logo has no height of its own. |
CardSkin#
The shape of a custom design.
| Field | Type | Description |
|---|---|---|
id | string | Required. Unique key, also the value a design picker reports. |
name | string | Required. Display name, e.g. "Coral". |
ink | string | Required. Colour of the mark, the number and back-side content. |
background | string | Required. Any CSS background: a colour or stacked gradients. |
light | boolean | A pale plastic: dark logos and a lighter edge. |
logos | Partial<Record<CardNetwork, "white" | "black" | "color">> | Logo prints that differ from the ones the tone implies. |
sheen | "spot" | "full" | "none" | "spot" (default) keeps a faint glare in the corner, "full" covers the face and "none" leaves the artwork without glare. |
art | (id: string) => React.ReactNode | SVG children on a 320×202 canvas. Prefix every SVG id with id. |
Helpers#
| Export | Type | Description |
|---|---|---|
cardSkins | CardSkinId[] | Built-in design ids in display order. |
getCardSkin | (skin: CardSkinId | CardSkin) => CardSkin | The full skin for a built-in id; a skin object is returned as is. |
findCardSkin | (id: string, list?: ReadonlyArray<CardSkinId | CardSkin>) => CardSkin | undefined | The skin with this id in a list, all built-ins by default. |