import type { Meta, StoryObj } from 'storybook-solidjs-vite'; import { createSignal, onMount, type JSX } from 'solid-js'; import './register'; // side effect: registers the custom elements import { argTypesFor, specDescription } from '../stories/docs/element-controls'; import type { ArtifactFile } from '../components/artifact'; // Custom DOM elements — declare the tags for JSX. declare module 'solid-js' { // eslint-disable-next-line @typescript-eslint/no-namespace namespace JSX { interface IntrinsicElements { 'kc-artifact': JSX.HTMLAttributes & { src?: string; tab?: string; 'active-file'?: string; sandbox?: string; 'iframe-title'?: string; ref?: (el: HTMLElement) => void; // toolbar composition flags (all boolean attrs) expandable?: boolean | string; 'open-in-tab'?: boolean | string; 'no-nav'?: boolean | string; 'no-reload'?: boolean | string; 'no-home'?: boolean | string; 'no-path-field'?: boolean | string; 'no-tabs'?: boolean | string; standalone?: boolean | string; 'readonly-path'?: boolean | string; }; } } } // Storybook serves examples/artifact-fixtures at /artifact-fixtures (see // .storybook/main.ts staticDirs). These are real, cross-linked pages so // relative-link nav, back/forward and multi-format all work in the iframe. const BASE = new URL('artifact-fixtures', document.baseURI).href; const FILES: ArtifactFile[] = [ { path: 'index.html', url: `${BASE}/index.html`, type: 'html', language: 'html', code: ` Starboard — Home

Starboard

About `, }, { path: 'about.html', url: `${BASE}/about.html`, type: 'html', language: 'html', code: ` Starboard — About

About Starboard

← Home `, }, { path: 'css/site.css', url: `${BASE}/css/site.css`, type: 'other', language: 'css', code: `:root { --accent: #6ea8fe; } body { font-family: system-ui, sans-serif; } .card { border: 1px solid var(--accent); border-radius: 14px; }`, }, { path: 'assets/logo.svg', url: `${BASE}/assets/logo.svg`, type: 'image', }, { path: 'assets/report.pdf', url: `${BASE}/assets/report.pdf`, type: 'pdf', }, ]; /** A bordered, sized box the artifact fills. */ function Frame(props: { children: JSX.Element; height?: string }) { return (
{props.children}
); } const HTML_SNIPPET = ` `; const meta = { title: 'Components/Artifact', tags: ['autodocs'], argTypes: argTypesFor('kc-artifact'), parameters: { layout: 'padded', docs: { description: specDescription('kc-artifact', [ '`` is the framework-agnostic **web component** for a framed, switchable **generated-artifact viewer** — the "canvas / artifacts" pattern (Claude Artifacts, ChatGPT Canvas, V0, bolt). It frames a consumer-served URL in a **sandboxed `