import { NAME, pattern, UI, type VNode, Writable } from "commonfabric"; import { Controls, SelectControl } from "../ui/controls/index.ts"; // Self-contained avatar image (data-URI SVG) — no network / CSP needed. const svgAvatar = (rgb: string, label: string): string => "data:image/svg+xml," + encodeURIComponent( `` + `` + `${label}`, ); // A profile cell, as presented to . The badge // reads the cell's [NAME] (person's name under the multi-profile model) and // falls back to `name`, plus `avatar`. `bio` + `elements` (pinned pieces) feed // the hover/focus tooltip (CT-1648); items only need a `title` for the count. type ProfileValue = { [NAME]: string; name: string; avatar: string; bio?: string; elements?: Array<{ title: string }>; }; const makeProfile = ( display: string, avatar: string, extra: { bio?: string; elements?: Array<{ title: string }> } = {}, ) => new Writable({ [NAME]: display, name: display, avatar, ...extra, }); const sizeItems = [ { label: "xs", value: "xs" }, { label: "sm", value: "sm" }, { label: "md", value: "md" }, { label: "lg", value: "lg" }, { label: "xl", value: "xl" }, ]; const sectionLabel = { fontSize: "0.75rem", fontWeight: "600", textTransform: "uppercase", letterSpacing: "0.04em", color: "#6b7280", margin: "0 0 8px", }; // Fixed-width monospace tag so the three variant rows line up. const variantTag = { fontFamily: "monospace", fontSize: "0.75rem", color: "#9ca3af", width: "3.5rem", flex: "0 0 auto", }; const variantRow = { display: "flex", gap: "12px", alignItems: "center", flexWrap: "wrap", }; // deno-lint-ignore no-empty-interface interface ProfileBadgeStoryInput {} export interface ProfileBadgeStoryOutput { [NAME]: string; [UI]: VNode; controls: VNode; } export default pattern(() => { // Three profiles exercising each avatar render path: image, emoji, initials — // and each tooltip state (CT-1648): bio + pins, bio only, and none. const ada = makeProfile("Ada Lovelace", svgAvatar("rgb(99,102,241)", "AL"), { bio: "Mathematician & writer; first to see that a computing engine could go beyond pure calculation.", elements: [ { title: "Analytical Engine notes" }, { title: "Bernoulli generator" }, { title: "Note G" }, ], }); const grace = makeProfile("Grace Hopper", "🦊", { bio: "Rear admiral and compiler pioneer; popularized the term “debugging.”", }); const alan = makeProfile("Alan Turing", ""); const size = new Writable<"xs" | "sm" | "md" | "lg" | "xl">("md"); return { [NAME]: "cf-profile-badge Story", [UI]: (

Trusted identity — avatar + name from a profile cell

Variants (CT-1761) — full · chip · circle · hero

full
chip
circle
hero
Avatar paths shown: image (Ada), emoji (Grace), initials (Alan). The verification signal is the generative seal — a DID-derived aura ring plus a cursor-reactive glint (there is no shield icon). It only renders for a runtime-attested profile (a “represents-principal” CFC label), which this story can’t mint, so these badges stay in the plain “presented” state. Hover or focus a badge to see its tooltip (CT-1648): Ada has a bio + 3 pinned pieces, Grace has a bio only, and Alan — with neither — shows no tooltip. The variants (CT-1761) all carry the same seal: full is an avatar + name pill;{" "} chip is a compact name + seal dot for inline use;{" "} circle{" "} is avatar + seal ring only (name on hover / for screen readers);{" "} hero{" "} is a large avatar-over-name for a profile page header.
), controls: ( ), }; });