VisualContent
Componente
Visualizar na APIO 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 bloco | Tipo | Dados recebidos pelo componente | Componente padrão |
---|---|---|---|
Cabeçalho | header | HeaderBlock | HeaderComponent |
Citação | quote | QuoteBlock | QuoteComponent |
HTML | raw | HTMLBlock | HTMLComponent |
Imagem | image | ImageBlock | ImageComponent |
Lista | list | ListBlock | ListComponent |
Parágrafo | paragraph | ParagraphBlock | ParagraphComponent |
Vídeo | video | VideoBlock | VideoComponent |
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 CSS | Utilizada por | Descrição |
---|---|---|
sl-visual-content | VisualContent | Elemento raíz que envolve todo o conteúdo. |
sl-content-block | Todos os blocos | Elemento que envolve o conteúdo de um bloco. |
sl-header | HeaderComponent | Elemento que envolve um bloco de cabeçalho. |
sl-quote | QuoteComponent | Elemento que envolve um bloco de citação. |
sl-html | HTMLComponent | Elemento que envolve um bloco de HTML. |
sl-image | ImageComponent | Elemento que envolve um bloco de imagem. |
sl-list | ListComponent | Elemento que envolve um bloco de lista. |
sl-list__root | ListComponent | Elemento que envolve a primeira lista (a lista raíz) do bloco de lista. |
sl-paragraph | ParagraphComponent | Elemento que envolve um bloco de parágrafo. |
empty | ParagraphComponent | Elemento que envolve um bloco de parágrafo vazio (sem conteúdo). |
sl-video | VideoComponent | Elemento que envolve um bloco de vídeo. |
sl-width-fixed | Todos os blocos | Denota que a largura do bloco é fixa (definida pelo usuário). |
sl-width-auto | Todos os blocos | Denota que a largura do bloco é definida automaticamente pelo navegador. |
sl-width-justify | Todos os blocos | Denota que a largura do bloco é justificada ao texto. |
sl-width-max | Todos os blocos | Denota 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:
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:
.parent-component {
width: 1000px;
}
.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
}}
/>
)
}