Saltar para o conteúdo
Blume
Esc
↑↓navegar↵abrir⌘Jpré-visualizar
Nesta página

Componentes

Cards, steps, tabs, accordions, badges, grupos de código, frames, árvores, tabelas de tipos, prévias ao vivo e diffs — os componentes integrados, utilizáveis em qualquer página MDX.

O Blume vem com um conjunto de componentes acessível e personalizável, disponível em qualquer página .mdx sem imports. Cada um é mostrado abaixo com uma prévia ao vivo e seu código-fonte. Os componentes são vanilla e não usam React; o React só entra em ação quando o seu projeto o utiliza — qualquer arquivo .tsx ou .jsx no projeto, uma ilha React, um exemplo de <Component> ou uma sobrescrita de componente — ou quando o assistente está ativado.

Um componente ignora as props que não aceita. A maioria exibe seus filhos, então a sintaxe de outras ferramentas de documentação pode renderizar vazia: o <Badge type="tip" text="beta" /> do VitePress é um Badge sem filhos, que não exibe nada. O Blume emite o aviso BLUME_UNKNOWN_PROP para um componente sem filhos que recebe props que ele não aceita, informando as props que ele aceita. Em vez disso, escreva o conteúdo entre as tags: <Badge>beta</Badge>.

Card e CardGroup

Os cards apontam para um destino com um ícone, um título e um breve resumo. Agrupe-os com CardGroup para obter uma grade responsiva. Use-os em páginas iniciais, índices de seção e “próximos passos” — em qualquer lugar em que você esteja guiando o leitor adiante.

<CardGroup cols={2}>
  <Card title="Quickstart" href="/docs/quickstart" icon="rocket">
    Install Blume and ship your first page.
  </Card>
  <Card title="Components" href="/docs/content/components" icon="folder">
    Browse the component library.
  </Card>
</CardGroup>

Card recebe title, um href opcional (omita-o para um card não clicável) e um icon do conjunto de ícones integrado do Blume. CardGroup recebe cols (padrão 2).

Um card também recebe img, uma imagem no topo (ou ao lado do texto a partir do breakpoint sm, com horizontal), informada como o caminho de uma imagem em Markdown: um arquivo ao lado da página (./cover.png), um caminho dentro de public/ ou uma URL; cta, uma linha de chamada para ação na cor de destaque abaixo do texto; arrow, uma seta após o título e o CTA (exibida por padrão apenas para links externos); type, que tinge o card e escolhe um ícone correspondente, como faz um callout (note, info, tip, check, warning ou danger); e color, qualquer cor CSS para o ícone.

Steps

Uma sequência vertical numerada para instruções ordenadas — instalações, fluxos de configuração e tutoriais em que a ordem importa. Cada Step recebe um title e um icon opcional, exibido no seu marcador no lugar do número. titleSize em Steps dimensiona os títulos das etapas como texto corrido (p, o padrão) ou como um cabeçalho h4, h3 ou h2.

Instale o Blume

Adicione o pacote ao seu projeto.

Escreva uma página

Coloque um arquivo .mdx na sua pasta de conteúdo.

Publique

Execute blume build e faça o deploy de dist/.

<Steps>
  <Step title="Install Blume">Add the package to your project.</Step>
  <Step title="Write a page">
    Drop an `.mdx` file into your content folder.
  </Step>
  <Step title="Ship it">Run `blume build` and deploy `dist/`.</Step>
</Steps>

Tabs

Alterne entre conteúdos equivalentes no mesmo lugar — variantes de linguagem, comandos específicos de sistema operacional ou abordagens alternativas — sem empilhar tudo na página. Cada Tab recebe um title.

Use o Homebrew para instalar o toolchain.
Use o winget para instalar o toolchain.
<Tabs>
  <Tab title="macOS">Use Homebrew to install the toolchain.</Tab>
  <Tab title="Windows">Use winget to install the toolchain.</Tab>
</Tabs>

Adicione inline para renderizar sem bordas — uma faixa de abas sobre uma linha de largura total, com o conteúdo fluindo abaixo como texto corrido — em vez da caixa com borda. Adicione param para sincronizar a aba ativa com um parâmetro de consulta na URL em vez do hash, o que torna a seleção compartilhável: um link terminando em ?install=windows abre na aba Windows. Cada grupo sincroniza com seu próprio param, então você pode usar vários grupos independentes e endereçáveis por link em uma mesma página.

Grupos com abas de mesmo título alternam juntos — escolha “macOS” em um e todos os grupos com uma aba macOS acompanham. Adicione syncKey para delimitar essa sincronização: apenas os grupos que compartilham a mesma chave alternam juntos, então grupos não relacionados que por acaso tenham um título de aba em comum permanecem independentes, ou sync={false} para deixar um grupo totalmente de fora dela.

A aba ativa é gravada no hash da URL, então um link abre nela; passe hash={false} para não alterar a URL. defaultTabIndex escolhe a aba que abre primeiro (contando a partir de zero, padrão 0) quando nenhum link ou seleção sincronizada define uma. dropdown troca a faixa de abas por um menu de seleção (somente no layout com caixa), borderBottom={false} remove a linha sob a faixa, e cada Tab recebe um icon exibido antes do seu título.

Use o Homebrew para instalar o toolchain.
Use o winget para instalar o toolchain.
<Tabs inline param="install">
  <Tab title="macOS">Use Homebrew to install the toolchain.</Tab>
  <Tab title="Windows">Use winget to install the toolchain.</Tab>
</Tabs>

View

Escreva uma única página para vários públicos, como leitores de diferentes linguagens de programação ou frameworks, com blocos <View>. Cada title distinto vira uma opção em um seletor acima do conteúdo da página, e apenas os blocos da visualização escolhida são exibidos. O sumário acompanha essa escolha: os cabeçalhos dentro de visualizações ocultas saem dele. O texto fora de qualquer <View> aparece em todas as visualizações, e os blocos que compartilham um título aparecem e somem juntos, então uma página pode alternar seções compartilhadas e seções específicas de cada visualização. icon aparece ao lado do nome da visualização no seletor.

Everyone reads this paragraph.

<View title="JavaScript" icon="braces">

## Install the client

```bash
npm install @acme/commerce
```

</View>

<View title="Python" icon="terminal">

## Install the client

```bash
pip install acme-commerce
```

</View>

A primeira visualização é exibida até o leitor escolher outra. O Blume lembra essa escolha entre as páginas escritas com visualizações e a grava na URL como ?view=Python, então um link abre na mesma visualização. Um link para um cabeçalho dentro de uma visualização abre essa visualização. Use <View> quando a maior parte da página muda conforme a escolha, e Tabs quando só uma parte dela muda. O Markdown voltado a agentes inclui todas as visualizações, cada uma sob o seu nome.

Callout

<Callout> é o componente por trás das diretivas de callout: :::warning[Heads up] renderiza <Callout type="warning" title="Heads up">. Escreva o próprio componente quando um callout precisar de um ícone ou de uma cor próprios, que uma diretiva não consegue definir.

<Callout type="tip" title="Ship it" icon="rocket">
  Run `blume build` before you deploy.
</Callout>

type define a tonalidade e o ícone padrão: note, info (o padrão), tip, success (ou check), warning ou danger. Os aliases caution, error, important e warn funcionam apenas na forma :::. title adiciona uma primeira linha em negrito. icon substitui o ícone do tipo e recebe as mesmas entradas que <Icon>: um nome do Lucide, um caminho ou URL de imagem, ou um SVG em linha. color, qualquer cor CSS, substitui a tonalidade do tipo: a borda, o ícone e o texto do corpo assumem essa cor sobre o fundo da página.

Badge

Um pequeno rótulo em linha para status ou metadados — tags de versão, marcadores de “novo” ou “beta”, níveis de estabilidade. O variant ajusta a cor ao significado.

Padrão

Metadados neutros, sem ênfase específica.

Estável
<Badge>Stable</Badge>

Destaque

Chama a atenção usando a cor de destaque do seu tema — bom para marcadores de “novo” ou de destaque.

Novo
<Badge variant="accent">New</Badge>

Sucesso

Um estado positivo ou aprovado.

Aprovado
<Badge variant="success">Passing</Badge>

Aviso

Algo a ser usado com cautela, como um recurso experimental.

Beta
<Badge variant="warning">Beta</Badge>

Perigo

Um estado negativo ou incompatível, como uma descontinuação.

Descontinuado
<Badge variant="danger">Deprecated</Badge>

Cor, formato e tamanho

Além de variant, um badge recebe color — um matiz nomeado (blue, green, orange, purple, red, teal, violet, yellow), um neutro (gray, surface, white, surface-destructive ou white-destructive) ou um valor hexadecimal — e também shape (rounded, o padrão, ou pill), size (xs, sm, md por padrão, ou lg), stroke para um contorno em vez de preenchimento, icon para um ícone antes do rótulo, tooltip para um texto exibido ao passar o mouse e disabled para esmaecê-lo.

Um badge roxo em formato de pílula, com contorno e ícone: Prévia

<Badge color="purple" icon="sparkles" shape="pill" stroke>Preview</Badge>

Icon

Renderiza um ícone pelo nome — a mesma prop icon alimenta cards, steps, tabs e entradas da barra lateral. Os nomes vêm do Lucide, em minúsculas e em kebab-case (rocket, gauge, book-open).

<Icon icon="rocket" size={20} />

O Blume usa somente o Lucide — um nome simples é resolvido no Lucide, e você pode prefixar um nome com lucide: (lucide:rocket) por simetria com outras entradas de ícone. size define o tamanho em pixels (padrão 16) e color o colore (qualquer cor CSS; o padrão é currentColor). Passe uma string <svg> bruta, uma URL de imagem ou um caminho de imagem local no lugar de um nome para renderizar sua própria arte, e adicione um label para expô-lo a tecnologias assistivas — sem ele, o ícone é decorativo.

Os ícones são resolvidos no momento do build e embutidos como SVG sem JS — nada é buscado em tempo de execução.

Árvore de arquivos

Ilustre a estrutura de um projeto ou de uma pasta. Envolva uma lista normal em Markdown e o Blume a estiliza como uma árvore — útil para explicar a estrutura em guias de configuração e instalação.

  • docs/
    • index.mdx
    • guides/
      • configuration.mdx
  • blume.config.ts
<FileTree>

- docs/
  - index.mdx
  - guides/
    - configuration.mdx
- blume.config.ts

</FileTree>

Accordion

Empilhe elementos recolhíveis relacionados em um único contêiner com borda e divisórias entre eles — perguntas frequentes, etapas opcionais ou exemplos longos. Cada filho é um AccordionItem (title, icon opcional, description, defaultOpen). O title renderiza Markdown em linha, então trechos de código, ênfase e links nele aparecem como apareceriam em uma frase; HTML bruto nele aparece como texto. Para uma única divulgação independente, use Expandable.

Ele tem suporte a MDX?

Sim — toda página pode ser .md ou .mdx.

O tema é personalizável?

Sim, por meio dos tokens do Tailwind v4 e do seu próprio theme.css.

<Accordion>
  <AccordionItem title="Does it support MDX?">
    Yes — every page can be `.md` or `.mdx`.
  </AccordionItem>
  <AccordionItem title="Is the theme customizable?">
    Yes, via Tailwind v4 tokens and your own `theme.css`.
  </AccordionItem>
</Accordion>

Expandable

Uma divulgação em linha e leve para detalhes aninhados — expandindo as subpropriedades de um campo ou uma nota opcional. title rotula o botão de alternância (o padrão é “Mostrar mais”) e renderiza Markdown em linha, como o de um item de accordion; defina defaultOpen para começar expandido.

Mostrar opções avançadas

Essas configurações são opcionais e raramente precisam ser alteradas.

<Expandable title="Show advanced options">
  These settings are optional and rarely need changing.
</Expandable>

Columns

Disponha cards ou blocos em uma grade responsiva de colunas iguais que se reorganiza no celular. Columns recebe cols; envolva cada célula em um Column.

Rápido

Construído sobre Astro e Vite.

Personalizável

Tokens de design do Tailwind v4.

<Columns cols={2}>
  <Column>
    <Card title="Fast" icon="rocket">
      Built on Astro and Vite.
    </Card>
  </Column>
  <Column>
    <Card title="Themeable" icon="sun">
      Tailwind v4 design tokens.
    </Card>
  </Column>
</Columns>

CodeGroup

Agrupe vários blocos de código em um único alternador com abas — uma aba por linguagem ou arquivo. O rótulo da aba é o título de cada bloco (o texto após a linguagem), ou o nome da sua linguagem (TypeScript, Python) para um bloco sem título, e o botão de cópia do grupo fica na barra de abas e copia o bloco que está sendo exibido. Adicione dropdown para alternar com um menu em vez de uma barra de abas.

export const greet = (name: string) => `Hello, ${name}`;
def greet(name: str) -> str:
    return f"Hello, {name}"
fn greet(name: &str) -> String {
    format!("Hello, {name}")
}
<CodeGroup>

```ts TypeScript
export const greet = (name: string) => `Hello, ${name}`;
```

```python Python
def greet(name: str) -> str:
    return f"Hello, {name}"
```

```rust Rust
fn greet(name: &str) -> String {
    format!("Hello, {name}")
}
```

</CodeGroup>

Frame

Envolva uma imagem ou qualquer elemento visual em um quadro centralizado e com borda, com uma caption opcional (renderizada como Markdown) e um hint.

Os frames centralizam e legendam elementos visuais.

Uma ilustração emoldurada.
<Frame
  caption="A **framed** illustration."
  hint="Frames center and caption visuals."
>
  <img src="/screenshot.png" alt="Product screenshot" />
</Frame>

YouTube

Incorpore um vídeo do YouTube em um quadro 16:9 responsivo e respeitoso com a privacidade (youtube-nocookie.com) que não envia nenhum JavaScript ao cliente. Passe um id de vídeo ou uma url completa, além de um title opcional (para acessibilidade) e um tempo de start em segundos. Uma url de playlist (youtube.com/playlist?list=… ou youtube.com/embed/videoseries?list=…) incorpora a playlist inteira.

<YouTube id="aqz-KE-bpKQ" title="Big Buck Bunny" />
<YouTube url="https://youtu.be/aqz-KE-bpKQ" start={30} />

Color

Exiba amostras de cor com valores hexadecimais copiáveis — útil para documentar uma paleta ou as cores da marca. Use variant="compact" para uma lista de amostras, ou variant="table" com Color.Row para agrupá-las. Cada Color.Item recebe um name e um value (uma string hexadecimal, ou { light, dark } para cores sensíveis ao tema); uma amostra sensível ao tema copia o valor do tema que o leitor está visualizando.

<Color variant="compact">
  <Color.Item name="blue-500" value="#3B82F6" />
  <Color.Item name="green-500" value="#16A34A" />
  <Color.Item name="background" value={{ light: "#FFFFFF", dark: "#0A0A0A" }} />
</Color>

Tree

Renderize uma estrutura hierárquica de arquivos/pastas com pastas expansíveis. (Para uma versão rápida, baseada em listas, veja Árvore de arquivos; Tree oferece controle por pasta.) Use Tree.Folder (name, defaultOpen opcional, openable) e Tree.File (name).

src
index.ts
components
Button.tsx
blume.config.ts
<Tree>
  <Tree.Folder name="src" defaultOpen>
    <Tree.File name="index.ts" />
    <Tree.Folder name="components">
      <Tree.File name="Button.tsx" />
    </Tree.Folder>
  </Tree.Folder>
  <Tree.File name="blume.config.ts" />
</Tree>

Panel

Um contêiner com título para conteúdo complementar, colocado à parte. title é opcional.

<Panel title="Good to know">
  Panels hold supporting detail without interrupting the main flow.
</Panel>

Tooltip

Revele uma definição ou dica ao passar o mouse sobre um termo em linha. tip é o texto exibido ao passar o mouse; adicione um headline opcional e um cta + href para um link de continuação.

Passe o mouse sobre o termo APIAPIUm conjunto de protocolos que os softwares usam para se comunicar.Leia o guia para saber mais.

Hover the <Tooltip tip="A set of protocols software uses to communicate." headline="API" cta="Read the guide" href="/docs/quickstart">API</Tooltip> term.

Tile

Uma prévia clicável que começa com um elemento visual — um ícone ou imagem — acima de um título e uma descrição. Boa para galerias e vitrines. Recebe title, description e href; o filho é o elemento visual.

Início rápido

Publique sua primeira página em minutos.

<Tile
  title="Quickstart"
  description="Ship your first page in minutes."
  href="/docs/quickstart"
>
  <Icon icon="rocket" size={28} />
</Tile>

Prompt

Uma única linha com um rótulo e um botão de cópia. A description (Markdown) é o rótulo visível; o corpo é o próprio prompt — oculto, e copiado para a área de transferência como Markdown, com seus links, listas e código intactos, quando o botão Copiar prompt é pressionado. Sua pontuação é copiada exatamente como você a digitou: aspas retas, -- e ... permanecem como foram escritos, embora o texto corrido em outras partes da página os exiba como aspas curvas, travessões e reticências. actions controla os botões (por exemplo, ["copy", "cursor"]).

Peça ao modelo para documentar um endpoint.

<Prompt
  description="Ask the model to **document** an endpoint."
  actions={["copy"]}
>
  Write reference docs for the POST /v1/pets endpoint.
</Prompt>

Visibility

Mostre ou oculte conteúdo de acordo com o público. for="web" renderiza somente no site; for="agents" tem como alvo o Markdown voltado a agentes que os agentes de IA leem (llms-full.txt e o espelho .md de cada página).

Esta nota aparece no site, mas é omitida do Markdown voltado a agentes.

<Visibility for="web">Shown on the site only.</Visibility>
<Visibility for="agents">Shown only in the generated Markdown.</Visibility>

Tabelas de tipos

Tabelas para documentar as propriedades de um objeto — suas props, tipos e valores padrão. Escreva as linhas manualmente com TypeTable, ou gere-as diretamente a partir de uma interface ou alias de tipo do TypeScript com AutoTypeTable.

Tabela de tipos

Uma grade Prop / Tipo em que cada linha se expande para revelar sua descrição e detalhes. Passe um mapa type indexado pelo nome da propriedade; cada entrada recebe um type, além de description, default, o sinalizador required, typeDescription e typeDescriptionLink opcionais. Props opcionais (required não definido) exibem um ? após o nome.

PropriedadeTipo
labelstring

O rótulo visível do botão.

Tipostring
variant?"primary" | "ghost"

Estilo visual.

Tipo"primary" | "ghost"
Predefinição"primary"
disabled?boolean
Tipoboolean
<TypeTable
  type={{
    label: {
      type: "string",
      required: true,
      description: "The button's visible label.",
    },
    variant: {
      type: '"primary" | "ghost"',
      default: '"primary"',
      description: "Visual style.",
    },
    disabled: { type: "boolean" },
  }}
/>

Tabela de tipos automática

Gere uma tabela de tipos a partir de um tipo do TypeScript, para que a documentação permaneça em sincronia com o código-fonte. Aponte o AutoTypeTable para um arquivo com path (resolvido a partir da raiz do seu projeto, a pasta em que você executa o blume) e um name de tipo. As descrições vêm de comentários JSDoc, os valores padrão de tags @default, e as propriedades opcionais (?) são marcadas conforme o caso.

<AutoTypeTable path="./src/button.ts" name="ButtonProps" />

Você também pode passar o tipo em linha com type em vez de um path — prático para exemplos pequenos:

PropriedadeTipo
labelstring

The button's visible label.

Tipostring
variant?"primary" | "ghost"

Visual style.

Tipo"primary" | "ghost"
Predefinição"primary"
disabled?boolean

Disable interaction.

Tipoboolean
<AutoTypeTable
  name="ButtonProps"
  type={`
export interface ButtonProps {
  /** The button's visible label. */
  label: string;
  /**
   * Visual style.
   * @default "primary"
   */
  variant?: "primary" | "ghost";
  /** Disable interaction. */
  disabled?: boolean;
}
`}
/>

Campos de API

Linhas para documentar um endpoint manualmente, um campo por vez, estilizadas como a referência OpenAPI gerada. ParamField é um parâmetro da requisição, nomeado pelo atributo que indica para onde ele vai: path, query, header ou body. ResponseField é um campo da resposta, nomeado por name. Ambos recebem type, required, deprecated e default, com a descrição como conteúdo; ResponseField também recebe os rótulos pre e post ao redor do nome.

userIdpathstringobrigatório

O ID do usuário.

limitqueryinteger
Predefinição: 20

Quantos resultados retornar, até 100.

planbetastring

O plano do usuário.

<ParamField path="userId" type="string" required>
  The user's ID.
</ParamField>

<ParamField query="limit" type="integer" default={20}>
  How many results to return, up to 100.
</ParamField>

<ResponseField name="plan" type="string" post={["beta"]}>
  The user's plan.
</ResponseField>

Aninhe os campos de um objeto dentro da descrição dele com um Expandable:

<ResponseField name="address" type="object">
  Where the order ships.

  <Expandable title="properties">
    <ResponseField name="city" type="string" required>
      City name.
    </ResponseField>
  </Expandable>
</ResponseField>

Em uma página com o frontmatter api, os ParamFields também montam o painel Try it e os exemplos de requisição da página: veja Páginas de API escritas à mão. Os campos usam os mesmos nomes e props dos campos do Mintlify, então as páginas escritas para ele são renderizadas como estão. A cópia em Markdown da página lista cada campo com seu tipo e seus sinalizadores.

Exemplos de requisição e resposta

RequestExample e ResponseExample contêm blocos de código, uma aba por bloco de crase com título (dropdown troca para um menu de linguagens, como em CodeGroup). Em uma tela larga, eles ficam fixos em uma coluna ao lado da página, a requisição acima da resposta, e permanecem visíveis enquanto o leitor rola pelos campos, como fazem os exemplos de uma operação OpenAPI; a página abre mão do seu sumário para dar espaço. Em uma tela estreita, eles vêm depois do conteúdo da página.

<RequestExample>

```bash cURL
curl --request POST https://api.acme.dev/v1/users \
  --header "Authorization: Bearer $ACME_TOKEN" \
  --data '{ "email": "ada@example.com" }'
```

```ts title="Acme SDK"
await acme.users.create({ email: "ada@example.com" });
```

</RequestExample>

<ResponseExample>

```json 201
{ "id": "usr_8f2k", "status": "invited" }
```

</ResponseExample>

Escreva-os em qualquer lugar no nível superior da página; cada um é movido para a coluna. Um que esteja aninhado dentro de outro componente, como um Tab, fica onde foi escrito.

Informações do GitHub

Um card com link para um repositório do GitHub com suas contagens de estrelas e forks. As contagens são buscadas no momento do build — sem JavaScript no cliente —, então mostram os números do seu último build, e não os atuais; o card continua sendo renderizado sem elas se a API estiver inacessível. Passe owner e repo, ou omita-os para usar o repositório do seu blume.config. Defina uma variável de ambiente GITHUB_TOKEN para elevar o limite de requisições da API; uma prop token a sobrescreve para um único card, mas a variável de ambiente mantém o token fora do seu conteúdo.

O card lê a instância a partir de github.host, então, em um site hospedado no Enterprise, owner/repo explícitos também apontam para essa instância. Passe host para direcionar um card para outro lugar — um projeto público a partir de um site Enterprise, por exemplo; a base REST é derivada dele da mesma forma que a partir de github.host.

haydenbleasel/blumeThe open-source docs framework for humans and agents.Estrelas: 1.8KForks: 118
<!-- Uses the repo from blume.config -->
<GithubInfo />

<!-- Or point it at any repository -->
<GithubInfo owner="haydenbleasel" repo="blume" />

<!-- Or at a repository on another instance -->
<GithubInfo host="https://github.com" owner="haydenbleasel" repo="blume" />

Component

O Component renderiza um arquivo de exemplo do diretório examples/ do seu projeto como uma prévia ao vivo ao lado do seu código-fonte destacado, em abas. Aponte-o para um arquivo com path — sua localização dentro de examples/, sem a extensão (portanto examples/counter.tsx fica path="counter"). Exemplos em React, Vue, Svelte e Astro são todos suportados; exemplos de frameworks hidratam, os de Astro renderizam estaticamente. Ele mantém a prévia e o código em sincronia a partir de um único arquivo. Um path que não corresponde a nenhum exemplo renderiza, em vez disso, uma caixa “Nenhum exemplo encontrado”, e blume dev, blume build e blume doctor emitem um aviso sobre isso (BLUME_EXAMPLE_NOT_FOUND) na linha correspondente.

A prévia é renderizada em um frame isolado que os estilos da documentação nunca alcançam — nenhuma margem de texto, tipografia ou elemento visual do tema vaza para o seu componente. O frame recebe o Tailwind (preflight + utilitários varridos do seu projeto e do seu diretório de exemplos), os tokens de design do Blume, para que classes como bg-background sigam a paleta do site por padrão, e ele acompanha ao vivo a alternância claro/escuro do site. O painel se dimensiona conforme o exemplo renderizado — e continua acompanhando caso o exemplo cresça ou encolha após o carregamento — com as abas Prévia e Código compartilhando uma mesma altura, de modo que alterná-las nunca desloca a página.

Para estilizar as prévias com seu próprio design system — digamos, com variáveis do shadcn — aponte examples.css para uma folha de estilos. Ela é injetada em cada frame de prévia após os padrões do Blume, então seus tokens prevalecem. Não use @import "tailwindcss" nela; o frame já fornece o Tailwind. Tanto .dark quanto [data-theme="dark"] funcionam para sobrescritas de modo escuro:

// blume.config.ts
export default defineConfig({
  examples: { css: "examples/theme.css" },
});
/* examples/theme.css */
:root {
  --primary: oklch(0.6 0.2 260);
}

.dark {
  --primary: oklch(0.75 0.15 260);
}

@theme inline {
  --color-primary: var(--primary);
}

O diretório também é configurável — defina source (ou use a forma abreviada em string, examples: "...") quando seus exemplos estiverem em outro lugar (por exemplo, um layout de registro). O path é sempre relativo a ele:

// blume.config.ts
export default defineConfig({
  examples: "registry/files-sdk",
});
<!-- registry/files-sdk/file-list/basic.tsx -->
<Component path="file-list/basic" />

examples também pode ser um glob (qualquer coisa com *, ?, [], {} ou !). Somente os arquivos correspondentes são descobertos, e o path é relativo ao prefixo estático do glob (a parte anterior ao primeiro curinga). Isso serve para um registro que coloca o código-fonte de cada componente junto ao seu exemplo — aponte apenas para os exemplos, para que os códigos-fonte, que não têm export padrão para prévia, não sejam incluídos:

// blume.config.ts
export default defineConfig({
  // registry/files-sdk/file-list/file-list.tsx — source, left out
  // registry/files-sdk/file-list/examples/basic.tsx — discovered
  examples: "registry/files-sdk/**/examples/*",
});
<!-- keyed relative to registry/files-sdk -->
<Component path="file-list/examples/basic" />

Em um monorepo, os componentes que seus exemplos importam geralmente ficam em um pacote irmão do workspace. O @source do Tailwind varre arquivos, não imports: o Blume varre o seu projeto e o diretório examples (para onde quer que source aponte, mesmo fora do projeto), então uma classe usada apenas dentro daquele pacote irmão não é gerada até você adicionar o pacote à varredura. Faça isso com uma diretiva @source no examples.css (para os frames de prévia) ou no theme.css (para o site), escrita de forma relativa ao arquivo em que ela está — a regra padrão do Tailwind — e o Blume a leva para a folha de estilos gerada:

/* examples/theme.css */
@source "../../../packages/ui/src";
import { useState } from "react";

const Counter = () => {
  const [count, setCount] = useState(0);

  return (
    <button
      className="rounded-blume border-border bg-background text-foreground hover:bg-muted border px-4 py-2 text-sm font-medium transition-colors"
      onClick={() => setCount((value) => value + 1)}
      type="button"
    >
      Clicked {count} {count === 1 ? "time" : "times"}
    </button>
  );
};

export default Counter;
<!-- examples/counter.tsx -->
<Component path="counter" />

Um exemplo em Astro renderiza ao vivo sem nenhum JavaScript no cliente:

---
interface Props {
  title?: string;
}

const { title = "Hello from Astro" } = Astro.props;
---

<div class="rounded-blume border border-border bg-muted/30 px-5 py-4">
  <p class="m-0 font-semibold text-foreground text-sm">{title}</p>
  <p class="m-0 mt-1 text-muted-foreground text-sm">
    A static, server-rendered example — no client JavaScript ships.
  </p>
</div>

CodeBlock

O CodeBlock destaca uma string de código com o mesmo tema do Shiki e os mesmos transformadores do seu código em blocos de crase — incluindo a troca claro/escuro — para lugares aonde um bloco de crase não chega, como uma página inicial ou um componente personalizado. Passe code e uma lang:

export const greet = (name: string): string =>
`Hello, ${name}!`;
---
import CodeBlock from "blume/components/content/CodeBlock.astro";
---

<CodeBlock lang="ts" code={source} />

title define o rótulo do cabeçalho — um nome de arquivo, por exemplo —, que, sem ele, mostra a linguagem, e icons={false} oculta o ícone da marca da linguagem, como markdown.code.icons faz para os blocos de crase.

Sem code, o CodeBlock renderiza seus filhos como foram escritos, então um bloco de crase envolvido em <CodeBlock>…</CodeBlock> (do jeito que o Fern e o Mintlify escrevem código) aparece como esse bloco de crase. Nesse caso, title e as outras props não se aplicam a ele: em vez disso, dê ao bloco de crase o seu título após a linguagem.

Para destacar você mesmo o código em uma string HTML (por exemplo, dentro do seu próprio componente), importe o helper subjacente de blume/markdown:

import { highlightCode } from "blume/markdown";

const html = await highlightCode(source, "ts");

Diff

O Diff renderiza um diff no estilo do git, destacado com o mesmo tema do Shiki dos seus blocos de código e produzido inteiramente no momento do build — sem JavaScript no cliente. Passe a ele duas strings em linha (old / new), dois caminhos de arquivo (before / after) ou um patch unificado (uma string patch em linha ou um arquivo src).

<Diff
  lang="ts"
  old={`export function greet(name) {
  return "Hi, " + name;
}`}
  new={`export function greet(name: string): string {
  return "Hi, " + name + "!";
}`}
/>

Compare dois arquivos do seu projeto, relativos à sua raiz:

<Diff before="diffs/button-before.ts" after="diffs/button-after.ts" />

Ou renderize um patch unificado — seja de um arquivo com src, seja em linha com patch:

<Diff src="diffs/greet.patch" />
<Diff
  patch={`--- a/greet.ts
+++ b/greet.ts
@@ -1,3 +1,4 @@
-export function greet(name) {
-  return "Hi, " + name;
+export function greet(name: string): string {
+  const greeting = "Hi, " + name + "!";
+  return greeting;
 }`}
/>

Última atualização a

Esta página foi útil?