import type { Meta, StoryObj } from 'storybook-solidjs-vite'; import { CodeBlock, CodeBlockCode, CodeBlockGroup } from './code-block'; import { Button } from '../ui/button'; import { componentDescription } from '../stories/docs/element-controls'; const tsCode = `interface User { id: string; name: string; email: string; } function greet(user: User): string { return \`Hello, \${user.name}!\`; }`; const pythonCode = `def fibonacci(n: int) -> list[int]: """Generate fibonacci sequence up to n numbers.""" if n <= 0: return [] sequence = [0, 1] while len(sequence) < n: sequence.append(sequence[-1] + sequence[-2]) return sequence[:n] print(fibonacci(10))`; const cssCode = `:root { --primary: hsl(240 5.9% 10%); --background: hsl(0 0% 100%); } .button { background: var(--color-primary); color: white; border-radius: 0.5rem; padding: 0.5rem 1rem; }`; /** * Story for the compound `CodeBlock` family. The root `CodeBlock` is a bordered * card container; `CodeBlockCode` does the (on-demand, Shiki) syntax * highlighting; `CodeBlockGroup` is a flex header/footer row. The controllable * props live on `CodeBlockCode`, so `Playground` drives that piece directly. */ const meta = { title: 'Solid (Advanced)/Elements/CodeBlock', component: CodeBlockCode, tags: ['autodocs'], parameters: { layout: 'padded', docs: { description: componentDescription([ 'A bordered code card with optional syntax highlighting. `CodeBlock` is the container, `CodeBlockCode` renders the (Shiki-)highlighted source, and `CodeBlockGroup` is a flex row for a header/footer (filename + copy button).', '**When to use:** to display code snippets in chat messages, documentation, or anywhere fenced code appears — typically emitted by the Markdown renderer for ``` blocks.', '**How to use:** wrap one or more children in ``. Pass the source string and a `language` to ``; optionally override the `theme`. Add a `` for a filename row and copy action.', '**Placement:** inside assistant message content, README/docs panes, and tool-output views.', ]), controls: { exclude: ['use:eventListener'] }, }, }, argTypes: { code: { control: 'text', description: 'The source code string to render.', }, language: { control: 'text', description: 'Language id for syntax highlighting (e.g. `typescript`, `python`, `css`).', table: { defaultValue: { summary: 'tsx' } }, }, theme: { control: 'text', description: 'Shiki theme id. Falls back to the active ChatConfig `codeTheme`.', }, }, args: { code: tsCode, language: 'typescript', }, render: (args) => (
), } satisfies Meta; export default meta; type Story = StoryObj; const IMPORT = `import { CodeBlock, CodeBlockCode, CodeBlockGroup } from '@kitn.ai/chat';`; const src = (code: string) => ({ parameters: { docs: { source: { code: `${IMPORT}\n\n${code}`, language: 'tsx' } } }, }); /** Interactive playground — edit the code, language, or theme via controls. */ export const Playground: Story = { ...src(` `), }; export const TypeScript: Story = { args: { code: tsCode, language: 'typescript' }, ...src(` `), }; export const Python: Story = { args: { code: pythonCode, language: 'python' }, ...src(` `), }; export const CSS: Story = { args: { code: cssCode, language: 'css' }, ...src(` `), }; /** A header row (`CodeBlockGroup`) with a filename and a copy button — showcase. */ export const WithHeader: Story = { render: () => (
user.ts
), ...src(` user.ts `), };