Lab results band

Full width lab results band: a third-party test report as letterhead beside the case for testing every batch.

blockcoasupplementswellnesstrust
$npx shadcn@latest add @storekit/pdp-coa-band
pdp-coa-band

Live and interactive. Switch the brand in the frame header to see the same source under another token file.

Installation

$npx shadcn@latest add @storekit/pdp-coa-band
$pnpm dlx shadcn@latest add @storekit/pdp-coa-band
$yarn dlx shadcn@latest add @storekit/pdp-coa-band
$bunx --bun shadcn@latest add @storekit/pdp-coa-band

Source

components/storekit/pdp/pdp-coa-band.tsx
166 lines
"use client"

import { motion, useReducedMotion } from "motion/react"
import { Check, Download, FlaskConical, X } from "lucide-react"
import { cn } from "@/components/storekit/lib/cn"
import { Button } from "@/components/storekit/ui/button"

/* A lab results band: a third-party test report styled as letterhead next
   to the case for testing every batch. Result rows enter in sequence. */

type Result = { analyte: string; spec: string; result: string; pass?: boolean }

const EASE = [0.23, 1, 0.32, 1] as const

const DEFAULT_RESULTS: Result[] = [
  { analyte: "Label claim", spec: "Matches label", result: "Matches", pass: true },
  { analyte: "Lead", spec: "< 0.5 mcg", result: "ND", pass: true },
  { analyte: "Arsenic", spec: "< 10 mcg", result: "1.2 mcg", pass: true },
  { analyte: "Pesticides", spec: "None detected", result: "ND", pass: true },
  { analyte: "Microbials", spec: "Within limits", result: "Pass", pass: true },
]

export function PdpCoaBand({
  product = "Daily Greens",
  lab = "Independent third-party lab",
  lot = "DG-2409-117",
  date = "2026-09-14",
  method = "ICP-MS, micro panel",
  results = DEFAULT_RESULTS,
  headline = "Every batch, tested",
  bullets = ["Tested by a third-party lab, not by us", "Heavy metals, pesticides and microbials on every batch", "The batch code on your pouch matches the report"],
  coaHref,
  className,
}: {
  product?: string
  lab?: string
  lot?: string
  date?: string
  method?: string
  results?: Result[]
  headline?: string
  bullets?: string[]
  coaHref?: string
  className?: string
}) {
  const reduce = useReducedMotion()
  const rise = (i: number) => ({
    initial: { opacity: 0, y: reduce ? 0 : 8 },
    whileInView: { opacity: 1, y: 0 },
    viewport: { once: true, amount: 0 },
    transition: { duration: reduce ? 0 : 0.5, ease: EASE, delay: reduce ? 0 : 0.15 + i * 0.05 },
  })

  return (
    <section data-sk-section="pdp" data-sk-variant="pdp-coa-band" className={cn("w-full overflow-hidden border-y border-sk-line bg-sk-surface py-16 sm:py-24", className)}>
      <div className="mx-auto grid max-w-6xl items-center gap-10 px-4 sm:px-8 md:grid-cols-[minmax(0,1.15fr)_minmax(0,1fr)] md:gap-16">
        <motion.article
          initial={{ opacity: 0, y: reduce ? 0 : 8 }}
          whileInView={{ opacity: 1, y: 0 }}
          viewport={{ once: true, amount: 0.2 }}
          transition={{ duration: reduce ? 0 : 0.5, ease: EASE }}
          className="min-w-0 rounded-sk-card border border-sk-line bg-sk-card p-4 sm:p-6"
          aria-label={`Lab results for ${product}`}
        >
          <header className="flex items-start justify-between gap-4 border-b border-sk-line pb-4">
            <div className="flex min-w-0 flex-col gap-1">
              <span className="font-sk-mono text-[11px] uppercase tracking-[0.14em] text-sk-muted">Lab results</span>
              <span className="font-sk-display text-lg font-semibold tracking-[-0.02em] text-sk-ink">{product}</span>
              <span className="text-[13px] text-sk-muted">{lab}</span>
            </div>
            <FlaskConical size={20} className="mt-1 shrink-0 text-sk-accent" aria-hidden />
          </header>
          <dl className="grid grid-cols-2 gap-3 border-b border-sk-line py-4 font-sk-mono sm:grid-cols-3 text-[11px] uppercase tracking-[0.08em]">
            {[
              ["Batch", lot],
              ["Date", date],
              ["Method", method],
            ].map(([k, v], i) => (
              <div key={k} className={cn("flex min-w-0 flex-col gap-1", i === 2 && "col-span-2 sm:col-span-1")}>
                <dt className="text-sk-muted">{k}</dt>
                <dd className="break-words normal-case tracking-normal text-sk-ink">{v}</dd>
              </div>
            ))}
          </dl>
          <div className="-mx-1 min-w-0 overflow-x-auto">
            <table className="w-full text-left text-[13px]">
              <thead>
                <tr className="font-sk-mono text-[11px] uppercase tracking-[0.08em] text-sk-muted">
                  <th className="px-1 py-3 font-normal">Test</th>
                  <th className="px-1 py-3 font-normal">Spec</th>
                  <th className="px-1 py-3 font-normal">Result</th>
                  <th className="px-1 py-3 text-right font-normal">
                    <span className="sr-only sm:not-sr-only">Status</span>
                  </th>
                </tr>
              </thead>
              <tbody>
                {results.map((r, i) => (
                  <motion.tr
                    key={r.analyte}
                    variants={{ hidden: { opacity: 0, y: reduce ? 0 : 8 }, shown: { opacity: 1, y: 0 } }}
                    initial="hidden"
                    whileInView="shown"
                    viewport={{ once: true, amount: 0 }}
                    transition={{ duration: reduce ? 0 : 0.45, ease: EASE, delay: reduce ? 0 : 0.15 + i * 0.05 }}
                    className="border-t border-sk-line"
                  >
                    <td className="px-1 py-2.5 text-sk-ink">{r.analyte}</td>
                    <td className="px-1 py-2.5 font-sk-mono text-sk-muted">{r.spec}</td>
                    <td className="px-1 py-2.5 font-sk-mono text-sk-ink">{r.result}</td>
                    <td className="px-1 py-2.5 text-right">
                      <span
                        className={cn(
                          "inline-flex items-center gap-1 rounded-sk-chip px-2 py-0.5 text-[11px] font-semibold uppercase tracking-[0.06em]",
                          r.pass === false ? "bg-sk-sale/[0.12] text-sk-sale" : "bg-sk-savings/[0.12] text-sk-savings"
                        )}
                      >
                        {r.pass === false ? <X size={11} strokeWidth={3} aria-hidden /> : <Check size={11} strokeWidth={3} aria-hidden />}
                        <span className="sr-only sm:not-sr-only">{r.pass === false ? "Fail" : "Pass"}</span>
                      </span>
                    </td>
                  </motion.tr>
                ))}
              </tbody>
            </table>
          </div>
        </motion.article>

        <div className="flex min-w-0 flex-col gap-5">
          <motion.span {...rise(0)} className="font-sk-mono text-[11px] uppercase tracking-[0.14em] text-sk-muted">
            Third-party tested
          </motion.span>
          <motion.h2 {...rise(1)} className="font-sk-display text-3xl font-semibold leading-[1.1] tracking-[-0.02em] text-sk-ink sm:text-4xl">
            {headline}
          </motion.h2>
          <ul className="flex flex-col gap-3">
            {bullets.map((b, i) => (
              <motion.li key={b} {...rise(i + 2)} className="flex items-start gap-3 text-[15px] leading-[1.5] text-sk-muted">
                <span className="mt-0.5 grid h-5 w-5 shrink-0 place-items-center rounded-full bg-sk-accent/[0.12] text-sk-accent">
                  <Check size={12} strokeWidth={3} aria-hidden />
                </span>
                {b}
              </motion.li>
            ))}
          </ul>
          <motion.div {...rise(bullets.length + 2)}>
            {coaHref ? (
              <a
                href={coaHref}
                download
                className="sk-btn inline-flex h-11 items-center gap-2 rounded-sk-btn border border-sk-line px-5 text-sm font-medium text-sk-ink outline-none transition-colors duration-200 hover:bg-sk-ink/[0.04] focus-visible:ring-2 focus-visible:ring-sk-accent focus-visible:ring-offset-2 focus-visible:ring-offset-sk-paper active:scale-[0.97]"
              >
                <Download size={16} aria-hidden /> Download lab report
              </a>
            ) : (
              <Button variant="outline">
                <Download size={16} aria-hidden /> Download lab report
              </Button>
            )}
          </motion.div>
        </div>
      </div>
    </section>
  )
}

Usage

Import from "@/components/storekit/pdp/pdp-coa-band" and pass your product data. The demo above exercises the full prop surface with sample values.

Lab results band, StoreKit