Pular para o conteúdo principal

VisualContent

Componente

Visualizar na API

O componente VisualContent renderiza conteúdo de um campo de Editor Visual do Starlight em HTML.

Para fins ilustrativos, esse é um exemplo de um conteúdo básico renderizado nessa página:

Exemplo


import { VisualContent } from '@starlightcms/react-sdk'

const SimpleExample = () => {
const content = {
time: 1663784614074,
version: '1.42',
blocks: [
{
id: '1',
type: 'header',
data: {
level: 2,
text: 'Olá, mundo! 😃'
}
},
{
id: '2',
type: 'paragraph',
data: {
text: 'Esse é apenas um exemplo de conteúdo, incluindo <b>conteúdo</b> em <i>HTML!</i>'
}
}
]
}

return (
<VisualContent content={content}/>
)
}

Resultado

Olá, mundo! 😃

Esse é apenas um exemplo de conteúdo, incluindo conteúdo em HTML!

Nós escrevemos nosso próprio objeto content nesse exemplo, mas em aplicações de verdade você não precisa fazer isso. Esse objeto com informações de conteúdo é retornado pelo Starlight sempre que um modelo utiliza um campo do tipo Visual Editor.

Dito isso, esse é um exemplo de uso mais próximo da realidade:

import Starlight, { VisualContent } from '@starlightcms/react-sdk'

// Assuma que criamos um modelo de postagens de blog que usa o slug "posts",
// e que criamos um campo de Editor Visual com a chave "post_content".
const EntryComponent = ({ slug }) => {
const [entry, setEntry] = useState(null)

// Esse é apenas um exemplo, você pode requisitar
// uma entrada da maneira que preferir.
useEffect(async () => {
const response = await Starlight.posts.entries.get(slug)

setEntry(response.data)
}, [ slug ])

// Depois da requisição, o conteúdo vai estar na propriedade `entry.data.post_content`.
return (
entry ? (
<article>
<h1>{entry.title}</h1>
<VisualContent content={entry.data.post_content} />
</article>
) : (
<div>Carregando...</div>
)
)
}

Resumindo o conteúdo

O componente VisualContent suporta a propriedade excerpt que, se passada, limita o conteúdo renderizado a 40 palavras. Essa função é útil para gerar resumos do conteúdo em listagens, como, por exemplo, em uma página de posts de um blog, onde cada post só precisa de um rápido resumo do seu conteúdo.

Você também pode alterar a tamanho do resumo utilizando a propriedade excerptLength, que recebe o número máximo de palavras que serão renderizadas. Por padrão, o número máximo de palavras é 40. Ao atingir esse limite, o texto é cortado e termina em reticências (...).

Para exemplificar, vamos reutilizar o exemplo no início dessa página:

Exemplo


import { VisualContent } from '@starlightcms/react-sdk'

const ExcerptExample = () => {
const content = {
time: 1663784614074,
version: '1.42',
blocks: [
{
id: '1',
type: 'header',
data: {
level: 2,
text: 'Olá, mundo! 😃'
}
},
{
id: '2',
type: 'paragraph',
data: {
text: 'Esse é apenas um exemplo de conteúdo, incluindo <b>conteúdo</b> em <i>HTML!</i> Dessa vez, ' +
'vamos adicionar mais conteúdo nesse parágrafo apenas para exemplificar como a propriedade "excerpt" ' +
'funciona, cortando o texto quando a quantidade de palavras passa do limite definido pela propriedade ' +
'"excerptLength", que, por padrão, define um limite de 40 palavras.'
}
}
]
}

return (
// Note que passamos a propriedade "excerpt" abaixo.
// Você também pode passar "excerptLength" se quiser alterar o limite de palavras.
<VisualContent content={content} excerpt />
)
}

Resultado

Esse é apenas um exemplo de conteúdo, incluindo conteúdo em HTML! Dessa vez, vamos adicionar mais conteúdo nesse parágrafo apenas para exemplificar como a propriedade "excerpt" funciona, cortando o texto quando a quantidade de palavras passa do limite definido pela...

Note que, no exemplo acima, o cabeçalho "Olá, mundo! 😃" não foi renderizado. Isso acontece porque, ao passar a propriedade excerpt, o componente renderiza apenas blocos de parágrafo, ignorando todo o resto, como cabeçalhos, imagens, listas, embeds, etc. Isso garante que o conteúdo renderizado não vai "quebrar" o layout da sua aplicação.

Personalizando componentes

O componente VisualContent também permite que você personalize como blocos são renderizados. Para isso, basta passar um objeto de componentes personalizados pela propriedade components. Cada componente recebe um objeto com o conteúdo a ser renderizado, e pode renderizar esse conteúdo da maneira que preferir.

Por exemplo, por padrão, blocos de lista são renderizados utilizando elementos <ul> ou <ol>, dependendo se essas listas são ordenadas ou sem ordem. Se quisermos mudar esse comportamento, podemos criar um componente personalizado para isso.

No exemplo abaixo, vamos renderizar listas ordenadas como texto simples separado por vírgulas, mas vamos renderizar listas sem ordem sem alterações, utilizando o componente original:

Exemplo


import { VisualContent, ListComponent } from '@starlightcms/react-sdk'

const CustomListComponent = ({ id, type, data }) => {
if (data.style === 'ordered') {
// Retornamos uma lista em texto para listas ordenadas.
return (
<p>{data.items.map(item => item.content).join(', ')}.</p>
)
}

// Usamos o componente de lista padrão para listas sem ordem.
return <ListComponent id={id} type={type} data={data} />
}

const CustomExample = () => {
const content = {
time: 1663784614074,
version: '1.42',
blocks: [
{
id: '1',
type: 'list',
data: {
style: 'ordered',
items: [{ content: 'Maçãs' }, { content: 'Bananas' }, { content: 'Laranjas' }]
}
},
{
id: '2',
type: 'list',
data: {
style: 'unordered',
items: [{ content: 'Azul' }, { content: 'Vermelho' }, { content: 'Verde' }]
}
}
]
}

return (
<VisualContent
content={content}
components={{
list: CustomListComponent
}}
/>
)
}

Resultado

Maçãs, Bananas, Laranjas.

  • Azul
  • Vermelho
  • Verde

Todos os componentes que renderizam blocos podem ser personalizados, e os tipos de bloco suportados estão listados na tabela abaixo. Para substituir um componente, passe um objeto para a propriedade components onde cada chave é um tipo da tabela abaixo, assim como foi feito com o componente list no exemplo acima.

Todo componente recebe um objeto do tipo VisualDataBlock que contém 3 propriedades: id, type e data.

  • id pode ser usado para identificar o bloco atual dentro do conteúdo.
  • type é uma string com o tipo do bloco atual.
  • data é um objeto com o conteúdo do bloco.

A propriedade data é genérica e seu conteúdo depende do type do bloco. Você pode clicar no link da terceira coluna da tabela abaixo para saber quais dados a propriedade data terá para seu respectivo tipo de bloco.

Na quarta coluna, você pode ver qual componente do SDK renderiza esse tipo de bloco por padrão, o que pode ser útil para servir de referência na hora de implementar um componente customizado.

Blocos suportados

O VisualContent suporta os seguintes tipos de bloco:

Nome do blocoTipoDados recebidos pelo componenteComponente padrão
CabeçalhoheaderHeaderBlockHeaderComponent
CitaçãoquoteQuoteBlockQuoteComponent
HTMLrawHTMLBlockHTMLComponent
ImagemimageImageBlockImageComponent
ListalistListBlockListComponent
ParágrafoparagraphParagraphBlockParagraphComponent
VídeovideoVideoBlockVideoComponent

Para criar componentes personalizados, sugerimos que você copie o código-fonte do bloco padrão que deseja personalizar e faça as alterações que desejar a partir disso. Você pode visualizar o código-fonte dos blocos padrões no GitHub.

Classes CSS

Todos os elementos renderizados pelos componentes de bloco padrões do VisualContent contém classes CSS que podem ser utilizadas para estilizar seus conteúdos sem a necessidade de criar um componente personalizado.

Por exemplo, se você quer fazer uma alteração simples de design, como adicionar bordas arrendondadas nos blocos de imagem, é possível fazê-la utilizando apenas CSS:

.sl-image img {
border-radius: 10px;
}

Assim, você não precisa criar um componente personalizado para blocos de imagem para chegar no design desejado.

As classes CSS usadas pelos componentes padrões do VisualContent são as seguintes:

Classe CSSUtilizada porDescrição
sl-visual-contentVisualContentElemento raíz que envolve todo o conteúdo.
sl-content-blockTodos os blocosElemento que envolve o conteúdo de um bloco.
sl-headerHeaderComponentElemento que envolve um bloco de cabeçalho.
sl-quoteQuoteComponentElemento que envolve um bloco de citação.
sl-htmlHTMLComponentElemento que envolve um bloco de HTML.
sl-imageImageComponentElemento que envolve um bloco de imagem.
sl-listListComponentElemento que envolve um bloco de lista.
sl-list__rootListComponentElemento que envolve a primeira lista (a lista raíz) do bloco de lista.
sl-paragraphParagraphComponentElemento que envolve um bloco de parágrafo.
emptyParagraphComponentElemento que envolve um bloco de parágrafo vazio (sem conteúdo).
sl-videoVideoComponentElemento que envolve um bloco de vídeo.
sl-width-fixedTodos os blocosDenota que a largura do bloco é fixa (definida pelo usuário).
sl-width-autoTodos os blocosDenota que a largura do bloco é definida automaticamente pelo navegador.
sl-width-justifyTodos os blocosDenota que a largura do bloco é justificada ao texto.
sl-width-maxTodos os blocosDenota que a largura do bloco é a maior possível.

Largura dos blocos

Por padrão, blocos de conteúdo utilizam todo o espaço horizontal disponível para o componente VisualContent, mas a largura dos blocos pode ser facilmente alterada pela interface do editor de conteúdo no Starlight. Nela, o usuário pode escolher dentre 4 tipos de largura: fixa, automática, justificada e máxima.

Na largura fixa, o usuário define manualmente a largura do bloco em pixels ou porcentagem da largura total do conteúdo.

Na automática, a largura do bloco é definida como a largura original do seu conteúdo, mas nunca maior do que a largura total do conteúdo. Por exemplo, se a largura de um bloco de imagem for definida como automática, e a imagem selecionada tiver 600 pixels de largura, a largura do bloco será de 600 pixels. Porém, se a largura total do conteúdo ao redor do bloco de imagem for menor do que 600 pixels, a imagem terá a mesma largura que o conteúdo.

Na justificada, a largura é definida como a mesma largura do resto do conteúdo, independente do conteúdo do bloco. Essa é a configuração padrão.

Na máxima, a largura do bloco é sempre a maior possível. Sem nenhuma configuração adicional, a largura máxima se comporta da mesma maneira que a largura justificada. Porém, é possível configurar o CSS do componente VisualContent para permitir que blocos com largura máxima excedam a largura dos outros blocos de conteúdo.

Largura máxima

A largura de um bloco renderizado pelo VisualContent depende do seu conteúdo, como a quantidade de texto escrita num bloco de parágrafo ou a resolução da imagem selecionada pelo usuário num bloco de imagem.

Dito isso, é possível limitar a largura de um bloco utilizando a classe .sl-content-block. Por exemplo, para limitar a largura dos blocos de conteúdo em 500 pixels, você pode utilizar esse CSS:

.sl-content-block {
max-width: 500px;
}

Porém, blocos de conteúdo configurados com a largura máxima podem exceder esse limite, e suas larguras são limitadas apenas pela largura do componente VisualContent em si.

Por exemplo, se você utilizar o CSS do exemplo acima e renderizar o componente VisualContent dentro de um elemento com 1000 pixels de largura disponível, blocos com largura máxima terão 1000 pixels de largura, e todos os outros blocos terão no máximo 500 pixels de largura.

Como outro exemplo, digamos que você tenha um blog onde o conteúdo das postagens é centralizado na página, e você quer que a largura de certos blocos, como algumas imagens, exceda a largura do conteúdo para um efeito dramático:

Depois da atualização, os blocos de conteúdo continuam com a mesma largura por padrão, mas blocos que tem largura máxima (.sl-width-max) ocupam todo o espaço disponível na tela.

Nesse exemplo, digamos que o elemento de classe .parent-component originalmente tenha uma largura de 1000 pixels, que é representado pelo antes na imagem acima e no código abaixo.

Para atualizar a largura do conteúdo, você deve definir a largura do elemento de classe .parent-component como 100% da largura da tela e a largura máxima dos elementos de classe .sl-content-block como 1000 pixels:

Antes
.parent-component {
width: 1000px;
}
Depois
.parent-component {
width: 100%;
}

.sl-content-block {
/* Note como usamos a regra
max-width, e não width! */
max-width: 1000px;
}

Com esse código, blocos com largura máxima irão preencher 100% da largura da tela, e todos os outros blocos terão no máximo 1000 pixels de largura.

Por último, note como nós não precisamos alterar nada no elemento .sl-visual-content, já que esse sempre utiliza toda a largura disponibilizada pelo seu elemento pai.

Imagens responsivas

O componente ImageComponent, que renderiza blocos do tipo image por padrão, provê uma propriedade adicional para dar suporte a imagens responsivas: a propriedade sizes. Essa propriedade define o atributo de mesmo nome na tag <img> que é renderizada.

Essa propriedade serve para permitir que o navegador use a imagem de melhor tamanho dentre as variações geradas pelo Starlight de acordo com o tamanho da tela do usuário. Você pode aprender mais sobre essa propriedade na página do MDN sobre imagens responsivas. Você só precisa definir a propriedade sizes: o atributo srcset é automaticamente gerado pelo ImageComponent.

Por padrão, a propriedade sizes tem o valor de '(max-width: 480px) 90vw, 70vw', que funciona bem para a maioria dos sites. Para alterar essa propriedade, você só precisa criar um componente de imagem personalizado:

import { VisualContent, ImageComponent } from '@starlightcms/react-sdk'

const CustomImageComponent = (props) => {
return (
// Você só precisa definir a propriedade "sizes" e repassar todos os props.
<ImageComponent
sizes="(max-width: 320px) 90vw, (max-width: 900px) 300px, 500px"
{...props}
/>
)
}

const ResponsiveImageExample = () => {
const content = {
time: 1663784614074,
version: '1.42',
blocks: [/* exemplo */]
}

return (
<VisualContent
content={content}
components={{
image: CustomImageComponent
}}
/>
)
}