Trust stripDesign system
Site

Trust strip

Linked security cards with a mark, title, description, and action.

npx context-ds add trust-strip
On the site

Usage

Use it for

Compliance, policies and controls near the bottom of the home page, linking to the trust center.

Avoid

  • Gray line icons in place of the dot marks
  • Colored badges or seals
  • A black pill per card
  • More than one link per card

Dependencies: button, dot-glyph

Example

examples/trust-strip.tsx
import { SiteSection } from "@/components/site/section";import { TrustMark, TrustStrip } from "@/components/site/trust-strip";const TRUST_CENTER = "https://trust.context.dev/";export function Site() {  return (<SiteSection>    <TrustStrip      className="w-full"      items={[        { mark: <TrustMark mark="compliance" />, label: "SOC 2 Type 1 & Type 2", description: "Review our compliance status and request access to security information through the trust center.", linkLabel: "View compliance", href: TRUST_CENTER },        { mark: <TrustMark mark="policies" />, label: "Security policies", description: "Review the policies covering data handling, access control, and incident response.", linkLabel: "Review policies", href: TRUST_CENTER },        { mark: <TrustMark mark="controls" />, label: "Security controls", description: "Explore published controls for encryption at rest, security monitoring, and supplier security.", linkLabel: "Review controls", href: TRUST_CENTER },      ]}    />  </SiteSection>);}

Source

components/site/trust-strip.tsx
import * as React from "react";import { buttonVariants } from "@/components/ui/button";import { DotGlyph } from "@/components/ui/dot-glyph";import { cn } from "@/lib/utils";// The home page's security row: three white cards in the soft blue ring, each with a blue dot mark, a title, a sentence// and an outline pill. The whole card is the link (the pill's hit area stretches over it), so hovering the card tints// the pill the way hovering the pill does. On phones the mark sits beside the text, scaled down; from tablet up, above.// The brand's three trust marks on its 15 by 15 dot grid, as the site draws them: `#` a solid dot, `o` a ring.const TRUST_MARKS = {  compliance: ["     #####     ", "   ##ooooo##   ", "  ##ooooooo##  ", " ##ooooooooo## ", " #ooooooooooo# ", "#o###o###o###o#", "#o#ooo#o#o#ooo#", "#o###o#o#o#ooo#", "#ooo#o#o#o#ooo#", "#o###o###o###o#", " #ooooooooooo# ", " ##ooooooooo## ", "  ##ooooooo##  ", "   ##ooooo##   ", "     #####     "],  policies: ["   #########   ", "  #ooooooooo#  ", "  #ooooooooo#  ", "  #oo#####oo#  ", "  #ooooooooo#  ", "  #oo#####oo#  ", "  #ooooooooo#  ", "  #oo#####oo#  ", "  #ooooooooo#  ", "  #oo#####oo#  ", "  #ooooooooo#  ", "  #oo###oooo#  ", "  #ooooooooo#  ", "  #ooooooooo#  ", "   #########   "],  controls: [" ############# ", "#ooooooooooooo#", "#ooooooooooooo#", "#ooooo#ooooooo#", "#ooooo#ooooooo#", "#oooo#o#oooooo#", "#oooo#o#oooooo#", "#####oo#oo#####", "#oooooo#oo#ooo#", "#ooooooo##oooo#", "#ooooooo##oooo#", "#ooooooo#ooooo#", "#ooooooooooooo#", "#ooooooooooooo#", " ############# "],} as const;// The library's DotGlyph reads 2 as a solid dot and 1 as a ring.const toGlyphRows = (rows: readonly string[]) => rows.map((row) => row.replace(/#/g, "2").replace(/o/g, "1"));type TrustMarkId = keyof typeof TRUST_MARKS;/** A trust card's dot mark in brand blue. The hover morph is a visual of its own; this is its resting picture. */function TrustMark({ mark, rows, className }: { mark?: TrustMarkId; rows?: readonly string[]; className?: string }) {  return <DotGlyph rows={toGlyphRows(rows ?? TRUST_MARKS[mark ?? "compliance"])} className={cn("size-18.75 text-fg-brand", className)} />;}export type TrustItem = { mark?: React.ReactNode; label: string; description: string; linkLabel: string; href: string };function TrustCard({ mark, label, description, linkLabel, href, external = true, className }: TrustItem & { external?: boolean; className?: string }) {  return (    <div data-slot="trust-card" data-hover-morph="" className={cn("rounded-card bg-ring-tint p-2", className)}>      <div className="group/trust relative grid h-full grid-cols-[4rem_minmax(0,1fr)] items-start gap-x-5 rounded-card bg-surface p-6 ring-1 ring-hairline md:flex md:flex-col md:p-8">        <div aria-hidden="true" className="row-span-3 size-16 md:mb-6 md:h-22 md:w-auto">          <div className="origin-top-left scale-72 md:scale-100">{mark}</div>        </div>        <h3 className="col-start-2 text-body-lg leading-snug font-medium text-fg">{label}</h3>        <p className="col-start-2 mt-3 mb-6 max-w-sm text-body leading-relaxed text-fg-muted">{description}</p>        <a          href={href}          {...(external ? { target: "_blank", rel: "noopener noreferrer" } : {})}          className={cn(buttonVariants({ variant: "pill-outline" }), "col-start-2 w-fit group-hover/trust:bg-tint after:absolute after:inset-0 after:rounded-card md:mt-auto")}        >          {linkLabel}        </a>      </div>    </div>  );}function TrustStrip({ items, className }: { items: TrustItem[]; className?: string }) {  return (    <ul data-slot="trust-strip" className={cn("grid grid-cols-1 gap-10 md:grid-cols-3 lg:gap-16", className)}>      {items.map((item) => (        <li key={item.label} className="-m-2 flex">          <TrustCard className="flex-1" {...item} />        </li>      ))}    </ul>  );}export { TrustStrip, TrustCard, TrustMark, TRUST_MARKS, type TrustMarkId };

Reference: src/components/sections/home/trust-strip.tsx; src/components/sections/home/trust-mark.tsx; src/components/sections/home/trust-marks.ts.