🌱 Seed

Templates

Alguns componentes têm uma estrutura interna fixa — um card sempre tem título, corpo e rodapé, numa ordem específica. Templates permitem definir essa estrutura uma vez e reutilizá-la em qualquer lugar.

O problema que templates resolvem

Imagine um componente @card que você quer usar assim:

```seed
@card
  @title
    Bem-vindo ao Seed
  @body
    Uma ferramenta simples para criar páginas HTML.
  @footer
    @button variant=primary
      Começar agora
```

Sem template, o Seed não saberia onde colocar o título, onde colocar o corpo, qual tag usar para cada parte, ou qual ordem seguir no HTML final.

O template resolve isso: é um arquivo (ou um trecho no YAML) que descreve a estrutura interna do componente — quais partes existem, em que ordem aparecem, e com quais classes.

Como funciona na prática

O template do @card acima seria algo assim:

```seed
@div class=p-6 border-b
  {title}
@div class=p-6 flex-1
  {?body}
@div class=p-6 border-t
  {?footer}
```

As marcações entre chaves — {title}, {?body}, {?footer} — são os espaços reservados. Cada um tem um nome, e o Seed substitui cada espaço pelo conteúdo correspondente que você passou no .seed.

Resultado: o conteúdo de @title vai para dentro do <div class="p-6 border-b"> do template. Sem você precisar lembrar da estrutura — ela está garantida pelo template.

Espaços obrigatórios e opcionais

Note que {title} não tem ? e {?body}, {?footer} têm. Essa é a diferença entre espaço obrigatório e opcional:

SintaxeSignificaSe não for preenchido
{title}ObrigatórioAparece um aviso amarelo no HTML para você perceber o erro
{?body}Opcional (note o ?)Simplesmente não aparece — nenhum HTML extra gerado
{?children}Opcional — pega tudo que sobrarSe não houver conteúdo extra, não aparece nada

O {?children} é especial: ele captura qualquer conteúdo que você passou mas que não tem um espaço reservado com aquele nome. Útil quando o componente aceita conteúdo livre além das partes nomeadas.

Detalhe importante: se um espaço opcional está dentro de um elemento HTML e ninguém preencheu, o elemento inteiro desaparece — não fica uma <div> vazia no HTML.

Como o conteúdo chega ao template

No seu arquivo .seed, cada filho direto do componente com um nome que bate com um espaço reservado é encaminhado para aquele espaço:

```seed
@card
  @title          ← vai para {title} no template
    Título do card
  @body           ← vai para {?body} no template
    Descrição aqui.
                  ← @footer foi omitido: {?footer} não aparece no HTML
```

A ordem que você escreve no .seed não importa — o HTML final sempre segue a ordem definida no template. Você pode colocar @footer antes de @title no .seed que o HTML ainda vai sair com título primeiro, rodapé por último.

Definindo o template

Você pode definir o template de duas formas — o resultado é idêntico, é só uma questão de organização:

Opção 1 — inline no YAML

Tudo em um único arquivo. Prático para componentes simples:

```yaml
card:
  tag: div
  class: bg-white rounded-xl border border-gray-200
  variant:
    elevated: shadow-lg border-0
  template: |
    @div class=p-6 border-b
      {title}
    @div class=p-6 flex-1
      {?body}
    @div class=p-6 border-t
      {?footer}
```

Opção 2 — arquivo separado

Um arquivo card.template ao lado do card.yaml. Melhor para templates longos ou quando você quer editar com syntax highlighting:

```
src/components/
  card/
    card.yaml       ← define tag, classes, variantes
    card.template   ← define a estrutura interna
```

O Seed associa automaticamente o card.template ao componente card porque estão na mesma pasta. Você não precisa configurar nada.

Templates alternativos

Um componente pode ter mais de um template — útil quando você quer o mesmo componente em layouts diferentes (vertical, horizontal, compacto, etc.):

```yaml
card:
  tag: div
  class: bg-white rounded-xl border border-gray-200
  template:
    default: |
      @div class=p-6
        {title}
        {?body}
    horizontal: |
      @div class=flex gap-6
        @div class=w-1/3
          {?image}
        @div class=flex-1 p-6
          {title}
          {?body}
```

Para usar o template alternativo, passe template= como prop:

```seed
@card template=horizontal
  @image
    @img src=foto.jpg
  @title
    Título
  @body
    Descrição do card.
```

Com arquivo separado, coloque horizontal.template na mesma pasta que card.yaml. O nome do arquivo antes de .template vira o nome da variante.

Criando um componente com template do zero

Exemplo completo: um componente feature com ícone, título e descrição.

1. Defina o componente no YAML (src/components/feature/feature.yaml):

```yaml
feature:
  tag: div
  class: flex gap-6 items-start
  variant:
    centered: flex-col items-center text-center
  template: |
    @div class=w-12 h-12 rounded-xl bg-blue-100 flex items-center justify-center shrink-0
      {?icon}
    @div
      @h3 class=font-semibold text-lg mb-1
        {title}
      @p class=text-gray-600 text-sm
        {?description}
```

2. Use no .seed:

```seed
@features-item variant=centered
  @icon
    ✨
  @title
    Recurso incrível
  @description
    Uma descrição breve e clara do benefício.
```

3. HTML gerado:

```html
<div class="flex flex-col items-center text-center">
  <div class="w-12 h-12 rounded-xl bg-blue-100 ...">✨</div>
  <div>
    <h3 class="font-semibold text-lg mb-1">Recurso incrível</h3>
    <p class="text-gray-600 text-sm">Uma descrição breve e clara do benefício.</p>
  </div>
</div>
```
⚠️

Se você passar conteúdo sem um espaço reservado correspondente no template, um bloco vermelho aparece no HTML avisando o problema. Se um espaço obrigatório não for preenchido, aparece um bloco amarelo. Esses avisos são visíveis só no HTML gerado — intencionais para facilitar a identificação de erros.

Repetindo um slot com list=True

Às vezes você quer passar vários itens para um slot, e cada item deve receber o mesmo wrapper definido no template. Sem list=True, você teria que repetir o componente inteiro várias vezes. Com list=True, você passa uma lista separada por --- e o template cuida de duplicar o wrapper para cada item.

Exemplo: lista de badges

Digamos que o template de @tag renderiza cada modificador dentro de um @badge:

```seed
@div class=mt-3 flex flex-wrap gap-2
  @badge variant=secondary
    {modifiers}
```

No .seed, passe os itens separados por --- com list=True:

```seed
@tag
  @modifiers list=True
    variant: muted, gradient
    ---
    size: sm, lg
```

Resultado: o @badge do template é duplicado — um para cada item separado por ---. Neste caso, dois badges.

Como funciona

A prop list=True no slot diz ao Seed para dividir o conteúdo em grupos usando --- como separador. Para cada grupo, o nó do template que contém o espaço reservado {modifiers} é clonado e renderizado com o conteúdo daquele grupo.

Sem list=True, o comportamento é o normal — todo o conteúdo vai para o slot de uma vez só. A funcionalidade é 100% retrocompatível.

Feito com ❤️ e Seed