Web Preview
Superfície de iframe em sandbox para preview de HTML ao vivo. Inclui barra de URL, saída de console opcional e um estado de URL compartilhado por contexto.
Visão geral
WebPreview é a superfície para rodar uma página gerada por IA, snippet ou URL ao vivo dentro do chat. O iframe está em sandbox com allow-scripts allow-same-origin allow-forms allow-popups allow-presentation, então pode executar scripts e forms sem escapar do app pai.
Internamente ele distribui um WebPreviewContext que carrega a url atual, um setter que dispara onUrlChange, e o estado consoleOpen. As peças de composição (WebPreviewUrl, WebPreviewBody, WebPreviewConsole) todas assinam o mesmo contexto, então digitar uma URL na barra reflete no iframe sem prop drilling.
Combine com Artifact quando o preview é parte de um asset gerado, ou use standalone como um tile de preview ao vivo em um workspace.
Preview
Preview básico com barra de URL
'use client';import { WebPreview, WebPreviewBody, WebPreviewNavigation, WebPreviewUrl,} from '@gremorie/rx-artifacts';export function WebPreviewPreview() { return ( <WebPreview defaultUrl="https://gremorie.com" className="max-w-2xl"> <WebPreviewNavigation> <WebPreviewUrl /> </WebPreviewNavigation> <WebPreviewBody src="https://gremorie.com" className="h-[240px]" /> </WebPreview> );}Com saída de console
'use client';import { WebPreview, WebPreviewBody, WebPreviewConsole, WebPreviewNavigation, WebPreviewUrl,} from '@gremorie/rx-artifacts';export function WebPreviewConsolePreview() { return ( <WebPreview defaultUrl="https://gremorie.com" className="max-w-2xl"> <WebPreviewNavigation> <WebPreviewUrl /> </WebPreviewNavigation> <WebPreviewBody src="https://gremorie.com" className="h-[180px]" /> <WebPreviewConsole logs={[ { level: 'log', message: '[ready] dev server on :5020', timestamp: new Date(), }, { level: 'warn', message: 'Slow render on /components/workflow/canvas', timestamp: new Date(), }, ]} /> </WebPreview> );}Anatomia
WebPreview card root + context provider
├─ WebPreviewNavigation top toolbar row
│ ├─ WebPreviewNavigationButton ghost icon button with a tooltip
│ └─ WebPreviewUrl address input (commits on Enter)
├─ WebPreviewBody sandboxed iframe (context URL unless src is set)
└─ WebPreviewConsole collapsible console rendering a logs arrayInstalação
bash npx gremorie@latest add rx-web-preview bash pnpm dlx gremorie@latest add rx-web-preview
bash yarn dlx gremorie@latest add rx-web-preview
bash bunx --bun gremorie@latest add rx-web-preview
Traz rx-display (para Collapsible), rx-forms (para Input e Button) e rx-overlays (para Tooltip) como dependências de registry.
Uso
import {
WebPreview,
WebPreviewBody,
WebPreviewConsole,
WebPreviewNavigation,
WebPreviewUrl,
} from "@gremorie/rx-artifacts";
export function Example({ logs }) {
return (
<WebPreview defaultUrl="https://gremorie.com" onUrlChange={track}>
<WebPreviewNavigation>
<WebPreviewUrl />
</WebPreviewNavigation>
<WebPreviewBody src="https://gremorie.com" />
<WebPreviewConsole logs={logs} />
</WebPreview>
);
}A edição Angular deste componente hoje é distribuída a partir do source (veja o side-by-side no workbench); sua entrada no registry vem a seguir.
API
<WebPreview>
| Prop | Type | Default | Descrição |
|---|---|---|---|
defaultUrl | string | "" | URL inicial. Semeia o estado interno url e o WebPreviewUrl. |
onUrlChange | (url: string) => void | - | Dispara sempre que um child chama setUrl (tipicamente no Enter dentro de WebPreviewUrl). |
className | string | - | Classes extras no div raiz. |
Estende todos os ComponentProps<"div">. Fornece WebPreviewContext a todos os descendentes.
Chrome padrão: flex size-full flex-col rounded-lg border bg-card.
<WebPreviewNavigation>
Linha de header que hospeda a barra de URL e os botões de navegação. Fica no topo com um separador border-bottom.
Estende todos os ComponentProps<"div">.
<WebPreviewNavigationButton>
| Prop | Type | Default | Descrição |
|---|---|---|---|
tooltip | string | - | Label do tooltip. Obrigatório para botões apenas de ícone. |
onClick | () => void | - | Handler de clique. |
disabled | boolean | - | Estado disabled padrão do Button. |
Renderiza um Button ghost 32x32 envolvido em um Tooltip. Use para affordances de voltar / avançar / recarregar.
<WebPreviewUrl>
Input de URL controlado ou não controlado. Lê url do WebPreviewContext e chama setUrl no Enter, o que propaga para onUrlChange.
| Prop | Type | Default | Descrição |
|---|---|---|---|
value | string | url do contexto | Sobrescreve o valor do contexto para tornar o input totalmente controlado. |
onChange | ChangeEventHandler<HTMLInputElement> | - | Sobrescrita opcional do handler de change. |
onKeyDown | KeyboardEventHandler<HTMLInputElement> | - | Chamado junto com o handler interno de Enter. |
Estende todas as props de Input de @gremorie/rx-forms.
<WebPreviewBody>
O iframe em sandbox.
| Prop | Type | Default | Descrição |
|---|---|---|---|
src | string | url do contexto | Sobrescreve a source do iframe. Recai para a URL do contexto. |
loading | ReactNode | - | Skeleton ou spinner opcional renderizado junto ao iframe. |
className | string | - | Classes extras no iframe. |
Sandbox hardcoded: allow-scripts allow-same-origin allow-forms allow-popups allow-presentation. Título: "Preview".
<WebPreviewConsole>
| Prop | Type | Default | Descrição |
|---|---|---|---|
logs | Array<{ level, message, timestamp }> | [] | Entradas de log. level é "log" | "warn" | "error", timestamp é um Date. |
children | ReactNode | - | Conteúdo extra renderizado abaixo dos logs (console HTML cru, controles de debug, etc.). |
className | string | - | Classes extras na raiz do Collapsible. |
Um Collapsible que abre ou fecha via o estado compartilhado consoleOpen. Logs vazios exibem um placeholder "No console output". O trigger + content são renderizados internamente - NÃO componha com WebPreviewConsoleTrigger / WebPreviewConsoleContent separados, esses subcomponentes não existem.
Composição
<WebPreview>é o wrapper que forneceWebPreviewContext. Segure o estado de URL aqui.<WebPreviewNavigation>é a linha da barra de endereço. ColoqueWebPreviewNavigationButtons para voltar / avançar / recarregar, entãoWebPreviewUrlcomo o input flex-1.<WebPreviewBody>preenche a altura restante com o iframe.<WebPreviewConsole>acopla na base e expande para cima quando aberto. O estado "console aberto" é compartilhado, então um trigger customizado em outro lugar também pode expandi-lo.
Variações
Preview read-only
Quando a URL é fixa (uma demo MDX, um asset gerado), pule a linha de navegação inteiramente.
<WebPreview defaultUrl="/preview/landing">
<WebPreviewBody src="/preview/landing" className="h-[480px]" />
</WebPreview>Chrome de browser com voltar / avançar
Adicione WebPreviewNavigationButtons antes do input de URL para uma sensação mais parecida com browser.
<WebPreview defaultUrl="/preview/landing">
<WebPreviewNavigation>
<WebPreviewNavigationButton tooltip="Back" onClick={back}>
<ArrowLeftIcon className="size-4" />
</WebPreviewNavigationButton>
<WebPreviewNavigationButton tooltip="Forward" onClick={forward}>
<ArrowRightIcon className="size-4" />
</WebPreviewNavigationButton>
<WebPreviewNavigationButton tooltip="Reload" onClick={reload}>
<RotateCwIcon className="size-4" />
</WebPreviewNavigationButton>
<WebPreviewUrl />
</WebPreviewNavigation>
<WebPreviewBody src="/preview/landing" />
</WebPreview>Console ao vivo para debugar código gerado
Faça streaming dos logs do iframe (ex. via postMessage) e passe-os através de logs. Erros renderizam em cor destructive, warnings em amarelo, logs normais em foreground.
<WebPreview defaultUrl="about:blank">
<WebPreviewBody srcDoc={generatedHtml} className="h-[280px]" />
<WebPreviewConsole logs={consoleLogs} />
</WebPreview>Acessibilidade
- Título do iframe: O
<iframe>sempre carregatitle="Preview"para que leitores de tela o anunciem. Sobrescreva via as spread props se você quer um título mais específico por superfície. - Sandbox: O sandbox estrito impede o iframe de escapar do app pai. Se você precisa de um sandbox relaxado (ex. permitindo navegação de topo), passe
sandboxexplicitamente para sobrescrever. - Teclado: O foco entra no input de URL via Tab. Enter submete a nova URL. O trigger do console é um
Buttonreal, então ativa no Enter / Space. - Cor do console: Erros não são transmitidos apenas por cor. Cada entrada retém seu texto cru mais o timestamp, então o nível pode ser inferido da mensagem mesmo em displays monocromáticos. Se você quer a11y total para o nível, prepende o nível ao texto da mensagem.
- Leitores de tela: O estado de console vazio anuncia "No console output", então os usuários não recebem uma superfície colapsada silenciosa.
Relacionados
- Artifact - chrome de card que frequentemente hospeda um
WebPreview - Code Block - o código-fonte que este preview renderiza
- Open in Chat - entregue uma página gerada de volta ao chat para iteração