DKProductCard
diklein/dk-product-cardFreeComponent
A product card for MDX blogs. Title, description, image, status strip, and note-style bodies. Pairs with the @diklein/dkproductcard remark plugin, which turns bare Amazon URLs into cards automatically.
Install it
npx shadcn@latest add https://diklein.com/r/dk-product-card.jsonSource
1import type { ReactNode } from 'react'23export interface DKProductCardProps {4 /** Product name, set in a medium weight above the description. */5 title?: string6 /** One-line supporting copy, muted. */7 description?: string8 /** Where the card links. Omit it (and asin) for a card that is not clickable. */9 href?: string10 /** Amazon ASIN. Builds the href (amazon.com/dp/ASIN) and switches the label to "Amazon". */11 asin?: string12 /** Link label. Defaults to "Amazon" for Amazon links, "View" otherwise. */13 label?: string14 /** Product image URL, rendered in a fixed square slot on the left. */15 image?: string16 /** Alt text for the product image. Falls back to the title. */17 imageAlt?: string18 /** Sugar for strip="Retired". */19 retired?: boolean20 /** Status-strip text across the top of the card, e.g. "Retired" or "Updated". */21 strip?: string22 /** Rich body content for note-style cards (a strip plus a sentence, no image or title).23 * Markdown links inside survive from MDX and pick up the accent treatment. */24 children?: ReactNode25 /** Render the product image yourself (e.g. with next/image). Apply ctx.className26 * and ctx.alt to the element you return. */27 renderImage?: (src: string, ctx: { alt: string; className: string }) => ReactNode28}2930export function DKProductCard({31 title,32 description,33 href,34 asin,35 label,36 image,37 imageAlt,38 retired,39 strip,40 children,41 renderImage,42}: DKProductCardProps) {43 const url = href ?? (asin ? `https://www.amazon.com/dp/${asin}` : undefined)44 const isAmazon = !!asin || (url?.includes('amazon.com') ?? false)45 const displayLabel = label ?? (isAmazon ? 'Amazon' : 'View')4647 /* Some products cannot be linked (discontinued, page gone). A card with a dead48 "View" pointing at "#" is worse than a card that simply does not claim to be49 clickable, so with no href and no asin this renders as a plain div: no link,50 no label, none of the hover affordances that would promise one. */51 const Shell = url ? 'a' : 'div'52 const shellProps = url ? { href: url, target: '_blank', rel: 'noopener noreferrer' } : {}5354 const stripText = strip ?? (retired ? 'Retired' : null)55 const isNote = !image && !title && !!children56 const alt = imageAlt ?? title ?? ''5758 return (59 <div className="dkpc-scope dkpc-root">60 <Shell {...shellProps} className={`dkpc-card${url ? ' dkpc-linked' : ''}`}>61 {/* The state belongs to the whole card, not to the title, so it reads better62// … truncated
What it pulls in
npm packages
Files it writes
More from diklein
All 3 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| DKBezelerdk-bezeler | diklein | Components | Free | no deps · 2 files | |
| DKMediaViewerdk-media-viewer | diklein | Components | Free | 1 dep · 5 files |
