Skip to main content
Gremorie

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 array

Instalaçã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>

PropTypeDefaultDescrição
defaultUrlstring""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).
classNamestring-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>

PropTypeDefaultDescrição
tooltipstring-Label do tooltip. Obrigatório para botões apenas de ícone.
onClick() => void-Handler de clique.
disabledboolean-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.

PropTypeDefaultDescrição
valuestringurl do contextoSobrescreve o valor do contexto para tornar o input totalmente controlado.
onChangeChangeEventHandler<HTMLInputElement>-Sobrescrita opcional do handler de change.
onKeyDownKeyboardEventHandler<HTMLInputElement>-Chamado junto com o handler interno de Enter.

Estende todas as props de Input de @gremorie/rx-forms.

<WebPreviewBody>

O iframe em sandbox.

PropTypeDefaultDescrição
srcstringurl do contextoSobrescreve a source do iframe. Recai para a URL do contexto.
loadingReactNode-Skeleton ou spinner opcional renderizado junto ao iframe.
classNamestring-Classes extras no iframe.

Sandbox hardcoded: allow-scripts allow-same-origin allow-forms allow-popups allow-presentation. Título: "Preview".

<WebPreviewConsole>

PropTypeDefaultDescrição
logsArray<{ level, message, timestamp }>[]Entradas de log. level é "log" | "warn" | "error", timestamp é um Date.
childrenReactNode-Conteúdo extra renderizado abaixo dos logs (console HTML cru, controles de debug, etc.).
classNamestring-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

  1. <WebPreview> é o wrapper que fornece WebPreviewContext. Segure o estado de URL aqui.
  2. <WebPreviewNavigation> é a linha da barra de endereço. Coloque WebPreviewNavigationButtons para voltar / avançar / recarregar, então WebPreviewUrl como o input flex-1.
  3. <WebPreviewBody> preenche a altura restante com o iframe.
  4. <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 carrega title="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 sandbox explicitamente para sobrescrever.
  • Teclado: O foco entra no input de URL via Tab. Enter submete a nova URL. O trigger do console é um Button real, 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

On this page