Pular para o conteúdo

Typography

templates/components/Typography

Typography é a camada de leitura de texto longo: uma hierarquia de elementos semânticos (H1–H4, P, Blockquote, List, InlineCode) para documentos, artigos e documentação — não um widget interativo. Por isso seus enriquecedores tratam de navegar, anotar e medir o texto, nunca de reestilizá-lo.

Base congelada

Taxing Laughter: The Joke Tax Chronicles

Once upon a time, in a far-off land, there was a very lazy king who spent all day lounging on his throne. One day, his advisors came to him with a problem: the kingdom was running out of money.

The King's Plan

The king thought long and hard, and finally came up with a brilliant plan: he would tax the jokes in the kingdom.

"After all," he said, "everyone enjoys a good joke, so it's only fair that they should pay for the privilege."

The Joke Tax

The king's subjects were not amused. They grumbled and complained, but the king was firm:

  • 1st level of puns: 5 gold coins
  • 2nd level of jokes: 10 gold coins
  • 3rd level of one-liners : 20 gold coins

As a result, people stopped telling jokes, and the kingdom fell into a gloom. But there was one person who refused to let the king's foolishness get him down: a court jester named Jokester.

Jokester's Revolt

Jokester began sneaking into the castle in the middle of the night and leaving jokes all over the place: under the king's pillow, in his soup, even in the royal toilet. The king was furious, but he couldn't seem to stop Jokester.

And then, one day, the people of the kingdom discovered that the jokes left by Jokester were so funny that they couldn't help but laugh. And once they started laughing, they couldn't stop.

The People's Rebellion

The people of the kingdom, feeling uplifted by the laughter, started to tell jokes and puns again, and soon the entire kingdom was in on the joke.

King's Treasury People's happiness
Empty Overflowing
Modest Satisfied
Full Ecstatic

The king, seeing how much happier his subjects were, realized the error of his ways and repealed the joke tax. Jokester was declared a hero, and the kingdom lived happily ever after.

The moral of the story is: never underestimate the power of a good laugh and always be careful of bad ideas.

Conteúdo

Numeração de cabeçalhos

Prefixa automaticamente os cabeçalhos com numeração…

Prefixa automaticamente os cabeçalhos com numeração sequencial/multinível — ideal para cláusulas de NRs e documentos normativos de SST.

Tempo de leitura & contagem

Calcula e exibe métricas derivadas do…

Calcula e exibe métricas derivadas do texto (tempo estimado de leitura, nº de palavras/caracteres) sem alterar o conteúdo. posicionável

Notas de rodapé

Insere marcadores de referência sobrescritos no…

Insere marcadores de referência sobrescritos no texto ligados a definições numeradas ao final do bloco, com retorno ao ponto de origem.

Auto-link (linkificar)

Detecta e converte URLs, e-mails e…

Detecta e converte URLs, e-mails e menções em links seguindo a convenção de link já congelada, sem criar novo estilo.

Comportamento

Âncora de cabeçalho (permalink)

Gera id-slug automático em cada H1–H4…

Gera id-slug automático em cada H1–H4 e revela um ícone de link no hover para copiar a URL profunda; aproveita o scroll-m-20 já embutido na base. posicionável

Índice automático (sumário)

Monta um sumário navegável a partir…

Monta um sumário navegável a partir da hierarquia de cabeçalhos existentes, com rolagem suave até a seção. Escolhe quais níveis entram. posicionável

Ler mais (recolher/expandir)

Limita um parágrafo a N linhas…

Limita um parágrafo a N linhas e adiciona alternador 'ler mais / recolher' para textos longos em prévias e cards, sem tocar no estilo do corpo.

Destacar termo (marcação)

Envolve as ocorrências de um termo…

Envolve as ocorrências de um termo em <mark> para realce de busca dentro do texto, sem reestilizar o corpo do parágrafo.

Glossário / abreviações (abbr)

Marca siglas técnicas (EPI, NR, CA)…

Marca siglas técnicas (EPI, NR, CA) com <abbr> e tooltip da definição, expandindo o significado no hover/foco — anotação semântica aditiva.
Código gerado

Cole no Claude Code — ele acerta de primeira.

Typography (UI) — Design System (Symfony UX Toolkit / shadcn)

BASE CONGELADA (não mude por instância): Ficam CONGELADOS: os elementos semânticos e toda a sua identidade visual — família de fonte, tamanhos (text-4xl/3xl/2xl/xl/base), pesos (extrabold/semibold/normal), tracking-tight, altura de linha (leading-7), o ritmo vertical (mt-6, pb-2, ml-6), a borda inferior do H2, a borda esquerda + itálico do Blockquote, os marcadores list-disc da List, o mono + bg-muted + rounded do InlineCode, a cor muted-foreground, o offset scroll-m-20 dos cabeçalhos, e a a11y (h1–h4/p/blockquote/ul/code corretos, data-slot). Ligar/desligar qualquer capacidade jamais muda esse visual.

USO: <twig:Typography />

CAPACIDADES OPT-IN (ligue sem alterar o visual):
- Âncora de cabeçalho (permalink): Gera id-slug automático em cada H1–H4 e revela um ícone de link no hover para copiar a URL profunda; aproveita o scroll-m-20 já embutido na base. [toggle]- Índice automático (sumário): Monta um sumário navegável a partir da hierarquia de cabeçalhos existentes, com rolagem suave até a seção. Escolhe quais níveis entram. [multi → Incluir H1 / Incluir H2 / Incluir H3 / Incluir H4]- Numeração de cabeçalhos: Prefixa automaticamente os cabeçalhos com numeração sequencial/multinível — ideal para cláusulas de NRs e documentos normativos de SST. [select → 1, 2, 3 (simples) / 1., 1.1, 1.1.1 (decimal multinível) / I, II, III (romano) / a, b, c (alfabético)]- Tempo de leitura & contagem: Calcula e exibe métricas derivadas do texto (tempo estimado de leitura, nº de palavras/caracteres) sem alterar o conteúdo. [multi → Tempo de leitura / Número de palavras / Número de caracteres]- Ler mais (recolher/expandir): Limita um parágrafo a N linhas e adiciona alternador 'ler mais / recolher' para textos longos em prévias e cards, sem tocar no estilo do corpo. [number]- Destacar termo (marcação): Envolve as ocorrências de um termo em <mark> para realce de busca dentro do texto, sem reestilizar o corpo do parágrafo. [text]- Notas de rodapé: Insere marcadores de referência sobrescritos no texto ligados a definições numeradas ao final do bloco, com retorno ao ponto de origem. [toggle]- Auto-link (linkificar): Detecta e converte URLs, e-mails e menções em links seguindo a convenção de link já congelada, sem criar novo estilo. [multi → URLs / E-mails / @menções]- Glossário / abreviações (abbr): Marca siglas técnicas (EPI, NR, CA) com <abbr> e tooltip da definição, expandindo o significado no hover/foco — anotação semântica aditiva. [toggle]FAÇA:
- Use <twig:Nome> — a base é congelada, você é dono do template em templates/components/.
- Ligue apenas capacidades opt-in listadas (e_funcao=true); a aparência não muda ao ligá-las.
- Passe atributos extras (id, aria-*, name, data-*) via {{ attributes }}.
NÃO FAÇA:
- Não mude cor/fonte/cantos/espaçamento por instância — é decisão de BASE, na fonte única assets/styles/app.css.
- Não crie variante/fork para a mesma coisa — existe UMA base por componente.
- Não reimplemente o componente nem adicione toolchain Node.
TESTE ANTES DE MUDAR: "é função ou é base?" — função = capacidade opt-in; base = mude o token na fonte única (assets/styles/app.css), para todos.

A11Y (herdada da base): Ficam CONGELADOS: os elementos semânticos e toda a sua identidade visual — família de fonte, tamanhos (text-4xl/3xl/2xl/xl/base), pesos (extrabold/semibold/normal), tracking-tight, altura de linha (leading-7), o ritmo vertical (mt-6, pb-2, ml-6), a borda inferior do H2, a borda esquerda + itálico do Blockquote, os marcadores list-disc da List, o mono + bg-muted + rounded do InlineCode, a cor muted-foreground, o offset scroll-m-20 dos cabeçalhos, e a a11y (h1–h4/p/blockquote/ul/code corretos, data-slot)

Via MCP: tool get_component com {"id": "typography"} · list_capabilities("typography").

Spec crua: config/ds-specs/typography.json · Conectar o MCP.

Spec machine-readable (JSON)

{
    "$schema_version": "1.0",
    "id": "typography",
    "component": "Typography",
    "eixo": "ui",
    "particularidade": "Typography é a camada de leitura de texto longo: uma hierarquia de elementos semânticos (H1–H4, P, Blockquote, List, InlineCode) para documentos, artigos e documentação — não um widget interativo. Por isso seus enriquecedores tratam de navegar, anotar e medir o texto, nunca de reestilizá-lo.",
    "base_congelada": "Ficam CONGELADOS: os elementos semânticos e toda a sua identidade visual — família de fonte, tamanhos (text-4xl/3xl/2xl/xl/base), pesos (extrabold/semibold/normal), tracking-tight, altura de linha (leading-7), o ritmo vertical (mt-6, pb-2, ml-6), a borda inferior do H2, a borda esquerda + itálico do Blockquote, os marcadores list-disc da List, o mono + bg-muted + rounded do InlineCode, a cor muted-foreground, o offset scroll-m-20 dos cabeçalhos, e a a11y (h1–h4/p/blockquote/ul/code corretos, data-slot). Ligar/desligar qualquer capacidade jamais muda esse visual.",
    "props": [],
    "capacidades": [
        {
            "id": "ncora-de-cabe-alho-permalink",
            "nome": "Âncora de cabeçalho (permalink)",
            "descricao": "Gera id-slug automático em cada H1–H4 e revela um ícone de link no hover para copiar a URL profunda; aproveita o scroll-m-20 já embutido na base.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/typography; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "ndice-autom-tico-sum-rio",
            "nome": "Índice automático (sumário)",
            "descricao": "Monta um sumário navegável a partir da hierarquia de cabeçalhos existentes, com rolagem suave até a seção. Escolhe quais níveis entram.",
            "controle": "multi",
            "opcoes": [
                "Incluir H1",
                "Incluir H2",
                "Incluir H3",
                "Incluir H4"
            ],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (multi). Ligue no configurador em /vitrine/ui/typography; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "numera-o-de-cabe-alhos",
            "nome": "Numeração de cabeçalhos",
            "descricao": "Prefixa automaticamente os cabeçalhos com numeração sequencial/multinível — ideal para cláusulas de NRs e documentos normativos de SST.",
            "controle": "select",
            "opcoes": [
                "1, 2, 3 (simples)",
                "1., 1.1, 1.1.1 (decimal multinível)",
                "I, II, III (romano)",
                "a, b, c (alfabético)"
            ],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ui/typography; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "tempo-de-leitura-contagem",
            "nome": "Tempo de leitura & contagem",
            "descricao": "Calcula e exibe métricas derivadas do texto (tempo estimado de leitura, nº de palavras/caracteres) sem alterar o conteúdo.",
            "controle": "multi",
            "opcoes": [
                "Tempo de leitura",
                "Número de palavras",
                "Número de caracteres"
            ],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (multi). Ligue no configurador em /vitrine/ui/typography; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "ler-mais-recolher-expandir",
            "nome": "Ler mais (recolher/expandir)",
            "descricao": "Limita um parágrafo a N linhas e adiciona alternador 'ler mais / recolher' para textos longos em prévias e cards, sem tocar no estilo do corpo.",
            "controle": "number",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (number). Ligue no configurador em /vitrine/ui/typography; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "destacar-termo-marca-o",
            "nome": "Destacar termo (marcação)",
            "descricao": "Envolve as ocorrências de um termo em <mark> para realce de busca dentro do texto, sem reestilizar o corpo do parágrafo.",
            "controle": "text",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (text). Ligue no configurador em /vitrine/ui/typography; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "notas-de-rodap",
            "nome": "Notas de rodapé",
            "descricao": "Insere marcadores de referência sobrescritos no texto ligados a definições numeradas ao final do bloco, com retorno ao ponto de origem.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/typography; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "auto-link-linkificar",
            "nome": "Auto-link (linkificar)",
            "descricao": "Detecta e converte URLs, e-mails e menções em links seguindo a convenção de link já congelada, sem criar novo estilo.",
            "controle": "multi",
            "opcoes": [
                "URLs",
                "E-mails",
                "@menções"
            ],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (multi). Ligue no configurador em /vitrine/ui/typography; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "gloss-rio-abrevia-es-abbr",
            "nome": "Glossário / abreviações (abbr)",
            "descricao": "Marca siglas técnicas (EPI, NR, CA) com <abbr> e tooltip da definição, expandindo o significado no hover/foco — anotação semântica aditiva.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/typography; comportamento via controller Stimulus. Não altera a base."
        }
    ],
    "snippet_uso": "<twig:Typography />",
    "exemplo_demo": "<div class=\"self-start w-full\">\n<twig:Typography:H1>Taxing Laughter: The Joke Tax Chronicles</twig:Typography:H1>\n<twig:Typography:P class=\"text-xl text-muted-foreground\">\n    Once upon a time, in a far-off land, there was a very lazy king who spent all day lounging on his throne. One day, his advisors came to him with a problem: the kingdom was running out of money.\n</twig:Typography:P>\n<twig:Typography:H2 class=\"mt-10\">The King's Plan</twig:Typography:H2>\n<twig:Typography:P>\n    The king thought long and hard, and finally came up with <a href=\"#\" class=\"font-medium text-primary underline underline-offset-4\">a brilliant plan</a>: he would tax the jokes in the kingdom.\n</twig:Typography:P>\n<twig:Typography:Blockquote>\n    \"After all,\" he said, \"everyone enjoys a good joke, so it's only fair that they should pay for the privilege.\"\n</twig:Typography:Blockquote>\n<twig:Typography:H3 class=\"mt-8\">The Joke Tax</twig:Typography:H3>\n<twig:Typography:P>\n    The king's subjects were not amused. They grumbled and complained, but the king was firm:\n</twig:Typography:P>\n<twig:Typography:List>\n    <li>1st level of puns: 5 gold coins</li>\n    <li>2nd level of jokes: 10 gold coins</li>\n    <li>3rd level of one-liners : 20 gold coins</li>\n</twig:Typography:List>\n<twig:Typography:P>\n    As a result, people stopped telling jokes, and the kingdom fell into a gloom. But there was one person who refused to let the king's foolishness get him down: a court jester named Jokester.\n</twig:Typography:P>\n<twig:Typography:H3 class=\"mt-8\">Jokester's Revolt</twig:Typography:H3>\n<twig:Typography:P>\n    Jokester began sneaking into the castle in the middle of the night and leaving jokes all over the place: under the king's pillow, in his soup, even in the royal toilet. The king was furious, but he couldn't seem to stop Jokester.\n</twig:Typography:P>\n<twig:Typography:P>\n    And then, one day, the people of the kingdom discovered that the jokes left by Jokester were so funny that they couldn't help but laugh. And once they started laughing, they couldn't stop.\n</twig:Typography:P>\n<twig:Typography:H3 class=\"mt-8\">The People's Rebellion</twig:Typography:H3>\n<twig:Typography:P>\n    The people of the kingdom, feeling uplifted by the laughter, started to tell jokes and puns again, and soon the entire kingdom was in on the joke.\n</twig:Typography:P>\n<div class=\"my-6 w-full overflow-y-auto\">\n    <table class=\"w-full\">\n        <thead>\n            <tr class=\"m-0 border-t p-0 even:bg-muted\">\n                <th class=\"border px-4 py-2 text-left font-bold\">King's Treasury</th>\n                <th class=\"border px-4 py-2 text-left font-bold\">People's happiness</th>\n            </tr>\n        </thead>\n        <tbody>\n            <tr class=\"m-0 border-t p-0 even:bg-muted\">\n                <td class=\"border px-4 py-2 text-left\">Empty</td>\n                <td class=\"border px-4 py-2 text-left\">Overflowing</td>\n            </tr>\n            <tr class=\"m-0 border-t p-0 even:bg-muted\">\n                <td class=\"border px-4 py-2 text-left\">Modest</td>\n                <td class=\"border px-4 py-2 text-left\">Satisfied</td>\n            </tr>\n            <tr class=\"m-0 border-t p-0 even:bg-muted\">\n                <td class=\"border px-4 py-2 text-left\">Full</td>\n                <td class=\"border px-4 py-2 text-left\">Ecstatic</td>\n            </tr>\n        </tbody>\n    </table>\n</div>\n<twig:Typography:P>\n    The king, seeing how much happier his subjects were, realized the error of his ways and repealed the joke tax. Jokester was declared a hero, and the kingdom lived happily ever after.\n</twig:Typography:P>\n<twig:Typography:P>\n    The moral of the story is: never underestimate the power of a good laugh and always be careful of bad ideas.\n</twig:Typography:P>\n</div>",
    "regras": {
        "faca": [
            "Use <twig:Nome> — a base é congelada, você é dono do template em templates/components/.",
            "Ligue apenas capacidades opt-in listadas (e_funcao=true); a aparência não muda ao ligá-las.",
            "Passe atributos extras (id, aria-*, name, data-*) via {{ attributes }}."
        ],
        "nao_faca": [
            "Não mude cor/fonte/cantos/espaçamento por instância — é decisão de BASE, na fonte única assets/styles/app.css.",
            "Não crie variante/fork para a mesma coisa — existe UMA base por componente.",
            "Não reimplemente o componente nem adicione toolchain Node."
        ]
    },
    "a11y": "Ficam CONGELADOS: os elementos semânticos e toda a sua identidade visual — família de fonte, tamanhos (text-4xl/3xl/2xl/xl/base), pesos (extrabold/semibold/normal), tracking-tight, altura de linha (leading-7), o ritmo vertical (mt-6, pb-2, ml-6), a borda inferior do H2, a borda esquerda + itálico do Blockquote, os marcadores list-disc da List, o mono + bg-muted + rounded do InlineCode, a cor muted-foreground, o offset scroll-m-20 dos cabeçalhos, e a a11y (h1–h4/p/blockquote/ul/code corretos, data-slot)",
    "mcp": {
        "tool": "get_component",
        "args": {
            "id": "typography"
        }
    },
    "props_nota": "Sem props próprias declaradas: a base repassa atributos nativos via {{ attributes }} (id, name, type, value, aria-*, data-*). Props específicas, quando existem, ficam nos subcomponentes."
}
  1. v0.1.0 Camada de IA: scaffold de página + specs íntegras
    • Novo tool MCP get_page_scaffold: devolve a MOLDURA de uma página nova (layout + blocks reais, contrato do renderPage, receita de rota + buildNav, tokens de layout lidos de app.css e snippet .html.twig válido) — dá pra montar página sem ler o controller/layout.
    • Fonte única do scaffold em config/ds-specs/_page-scaffold.json (padrão v1.0); tokens semânticos derivados de assets/styles/app.css em runtime.
    • Fix: exemplo_demo estava truncado em 1600 bytes em 5 specs (card, field, table, tabs, typography) — reconstituídos íntegros a partir dos demos, fechando todas as tags.
    • Nova seção Updates (este changelog versionado) como 9º eixo do shell.
    • Docs: CLAUDE.md e AI-LAYER.md citam o novo tool; contadores de tools atualizados (6 → 7).

Changelog completo em Updates.