components / agent
Artifact
Side pane for generated content with Preview and Code tabs.
previewartifact
Hello.tsx
Hello, world
install
bash
npx shadcn@latest add https://turnui.xyz/r/artifact.jsonprops
| prop | type | default | description |
|---|---|---|---|
| title | string | — | Header title. |
| preview / code | ReactNode | — | Tab contents. |
| onClose | () => void | — | Shows a close button when set. |
accessibility
- Tabs follow the WAI-ARIA pattern: Arrow keys move focus between tabs, Enter or Space activates, and the panel is focusable.
- The close button is labelled "Close artifact".
source
tsx
"use client";
import * as React from "react";
import { Tabs } from "@base-ui/react/tabs";
import { cn } from "@/lib/utils";
import { Button } from "./button";
/** Side pane for generated content, with Preview and Code tabs. */
export function Artifact({
title,
preview,
code,
onClose,
className,
}: {
title: string;
preview: React.ReactNode;
code: React.ReactNode;
onClose?: () => void;
className?: string;
}) {
return (
<Tabs.Root defaultValue="preview" className={cn("flex h-full flex-col overflow-hidden rounded border bg-background", className)}>
<div className="flex h-11 items-center gap-3 border-b px-3 pt-1">
<span className="truncate font-mono text-[13px]">{title}</span>
<Tabs.List className="ml-auto flex gap-1 text-xs">
{(["preview", "code"] as const).map((v) => (
<Tabs.Tab
key={v}
value={v}
className="-mb-px rounded-sm border-b-2 border-transparent px-2.5 py-1.5 font-mono capitalize text-muted-foreground outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring data-[active]:border-foreground data-[active]:text-foreground"
>
{v}
</Tabs.Tab>
))}
</Tabs.List>
{onClose && (
<Button variant="ghost" size="icon" onClick={onClose} aria-label="Close artifact">
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"><path d="m4 4 8 8M12 4l-8 8" /></svg>
</Button>
)}
</div>
<Tabs.Panel value="preview" className="min-h-0 flex-1 overflow-auto p-4">{preview}</Tabs.Panel>
<Tabs.Panel value="code" className="min-h-0 flex-1 overflow-auto p-4">{code}</Tabs.Panel>
</Tabs.Root>
);
}