import { snippetOf } from '~/chrome/lib/codegen'; import { CopyButton } from '~/chrome/ui/copy'; import { ErrorBoundary } from '~/chrome/ui/error-boundary'; import { decodeProps } from '~/chrome/lib/prop-params'; import { useMessages } from '../i18n'; import { findEntry } from '../registry'; import { Link, useRoute } from '../router'; /** * One component, alone on a page. * * The share button's second link lands here. It exists because the audience for * a shared link is usually not the audience for the gallery: a designer or a PM * asked "what does the outline green large one look like", and a rail, a * breadcrumb, a props table and a Figma parity panel are all answers to a * different question. * * It reads the same `p.*` params the playground writes (`chrome/lib/prop-params.ts`), * so the two views cannot disagree, and it honours `?theme` and `?lang` because * those are applied above it — `app.tsx` sets the theme class before it branches * here, and `I18nProvider` is above `App` in `main.tsx`. * * The preview is wrapped in `ErrorBoundary` like every other one on the site. * That matters more here than anywhere: this page *is* the preview, so a * component that throws would otherwise hand the recipient a blank document. */ export function EmbedPage({ slug }: { slug: string }) { const m = useMessages(); const { params } = useRoute(); const entry = findEntry(slug); if (!entry?.render) { return (

{m.embed.notFound}

{m.embed.openInShowcase}
); } /* Rendered once and used twice, the same rule the playground follows: what the copy button serialises is the element on screen, never a second tree built to look like it. */ const instance = entry.render(decodeProps(entry.axes, entry.defaults, params)); return (
{instance}
{/* Deliberately below the fold of attention: a thin bar, not a header. The component is the page; this is the way back into the site. */}
); }