Pular para o conteúdo principal

Bloco de ícone

O bloco icon-block combina um asset de imagem com título e descrição em um cartão pequeno, com suporte a alinhamento horizontal ou empilhado. É comum em seções de destaques, features ou listas de serviços.


Como foi construído

Identificação

ItemValor
ClasseSGMBlocks\Site\BlockLayout\IconBlock
block_layouticon-block
FormSGMBlocks\Form\IconBlockForm
FactorySGMBlocks\Service\BlockLayout\IconBlockFactory
Partialcommon/block-layout/icon-block

Formulário

O IconBlockForm define quatro campos:

$this->add(['name' => 'o:block[__blockIndex__][o:data][icon]',
'type' => OmekaElement\Asset::class,
'options' => ['label' => 'Ícone'],
'attributes' => ['required' => true]]);

$this->add(['name' => 'o:block[__blockIndex__][o:data][title]',
'type' => Element\Text::class,
'options' => ['label' => 'Título'],
'attributes' => ['required' => true]]);

$this->add(['name' => 'o:block[__blockIndex__][o:data][description]',
'type' => Element\Textarea::class,
'options' => ['label' => 'Descrição'],
'attributes' => ['rows' => 4]]);

$this->add(['name' => 'o:block[__blockIndex__][o:data][alignment]',
'type' => Element\Select::class,
'options' => ['label' => 'Alinhamento',
'value_options' => [
'left' => 'Esquerda',
'center' => 'Centralizado',
]],
'attributes' => ['value' => 'left']]);

icon e title são marcados como obrigatórios no atributo HTML. A validação server-side não está registrada em form.add_input_filters, então o campo só reforça a obrigatoriedade pelo browser.

Classe do bloco

IconBlock::prepareForm anexa admin.css para o preview do asset no editor:

public function prepareForm(PhpRenderer $view)
{
$view->headLink()->appendStylesheet($view->assetUrl('css/admin.css', 'SGMBlocks'));
}

IconBlock::form popula os quatro campos com populateValues, aplicando fallback left para alignment.

IconBlock::render lê o asset com try catch e delega ao partial:

$iconId = $block->dataValue('icon');
$icon = null;
if ($iconId) {
try {
$icon = $view->api()->read('assets', $iconId)->getContent();
} catch (\Exception $e) {
// asset apagado
}
}

return $view->partial('common/block-layout/icon-block', [
'icon' => $icon,
'title' => $block->dataValue('title'),
'description' => $block->dataValue('description'),
'alignment' => $block->dataValue('alignment') ?: 'left',
]);

Partial

<?php
$this->headLink()->appendStylesheet($this->assetUrl('css/style.css', 'SGMBlocks'));

if (!$icon && empty($title)) return;

$alignClass = ($alignment === 'center')
? 'sgm-icon-block--center'
: 'sgm-icon-block--left';
?>

<div class="sgm-icon-block <?= $this->escapeHtmlAttr($alignClass) ?>">
<?php if ($icon): ?>
<div class="sgm-icon-block__icon">
<img src="<?= $this->escapeHtmlAttr($icon->assetUrl()) ?>"
alt="<?= $this->escapeHtmlAttr($icon->altText() ?: $title) ?>">
</div>
<?php endif; ?>

<div class="sgm-icon-block__content">
<?php if (!empty($title)): ?>
<h3 class="sgm-icon-block__title"><?= $this->escapeHtml($title) ?></h3>
<?php endif; ?>
<?php if (!empty($description)): ?>
<p class="sgm-icon-block__description"><?= $this->escapeHtml($description) ?></p>
<?php endif; ?>
</div>
</div>

Pontos do partial:

  • Aborta o render quando não há ícone nem título.
  • Deriva a classe CSS por comparação estrita com center.
  • Define o alt do <img> como altText do asset, ou o próprio título como fallback.

Persistência

Chave em o:dataTipoDefaultObservação
iconinteiro id de assetvazioValidado apenas no required do HTML.
titlestringvazioObrigatório via atributo HTML. Escapado no partial.
descriptionstringvazioOpcional. Escapado no partial.
alignmentstringleftValores válidos: left, center.

Assets carregados

  • Frontend: asset/css/style.css. Define .sgm-icon-block, .sgm-icon-block--left, .sgm-icon-block--center, .sgm-icon-block__icon, .sgm-icon-block__title, .sgm-icon-block__description.
  • Admin: asset/css/admin.css. Ajusta o preview do asset.

Regras de CSS importantes

O style.css aplica:

  • .sgm-icon-block com display: flex e gap: 1.25rem.
  • .sgm-icon-block--left com flex-direction: row.
  • .sgm-icon-block--center com flex-direction: column e text-align: center.
  • .sgm-icon-block__icon img com width: 64px; height: 64px; object-fit: contain. Isso limita o tamanho do ícone independente do tamanho do asset carregado.

Para ícones maiores, o tema precisa sobrescrever a regra ou o partial.


Como usar como desenvolvedor

Sobrescrever o partial no tema

Copie view/common/block-layout/icon-block.phtml para themes/<tema>/view/common/block-layout/icon-block.phtml. O tema pode trocar a tag <h3> por <h4>, usar SVG inline em vez de <img>, ou alinhar o conteúdo de forma diferente.

Usar SVG como ícone

O Asset do Omeka aceita SVG. O partial renderiza com <img> apontando para assetUrl. Para inlining do SVG, crie um helper de view próprio do tema que carregue o arquivo do asset e emita o XML no HTML. O partial do módulo mantém o <img> genérico.

Trocar o tamanho do ícone

Três caminhos:

  1. Edite asset/css/style.css e ajuste a regra .sgm-icon-block__icon img.
  2. Sobrescreva o partial no tema com style="width: 80px; height: 80px".
  3. Adicione um campo de tamanho no IconBlockForm, persista em o:data[size], e aplique uma classe variável.

Adicionar um novo alinhamento

Estenda as value_options do select com uma terceira entrada e trate-a no partial:

$alignClass = match ($alignment) {
'center' => 'sgm-icon-block--center',
'right' => 'sgm-icon-block--right',
default => 'sgm-icon-block--left',
};

Acrescente .sgm-icon-block--right em asset/css/style.css com flex-direction: row-reverse.

Validar o asset no submit

O atributo required só age no browser. Para validar no servidor, anexe um listener a form.add_input_filters do IconBlockForm:

$inputFilter->add([
'name' => 'o:block[__blockIndex__][o:data][icon]',
'required' => true,
'validators' => [
['name' => 'Laminas\Validator\NotEmpty'],
],
]);

Ler o bloco em outros templates

foreach ($page->blocks() as $block) {
if ($block->layout() === 'icon-block') {
$iconId = $block->dataValue('icon');
$title = $block->dataValue('title');
}
}

Depurar

  • Se o bloco some sem motivo aparente, confirme que o asset ainda existe. A leitura da API cai em catch e o render segue com $icon = null; o partial ainda emite se houver title, mas o <img> fica ausente.
  • Se o ícone aparece grande no site, inspecione .sgm-icon-block__icon img no navegador. O tema pode estar sobrescrevendo width ou height.
  • Se alignment não bate com as classes, confirme que o valor persistido é left ou center. O fallback do render normaliza valores vazios para left.

Observações

  • Não é ícone no sentido estrito. O campo aceita qualquer asset de imagem. Nada impede carregar uma foto inteira e ela será reduzida para 64 por 64.
  • alt baseado no título. Se o asset não tem altText, o partial usa title no <img>. Isso evita alt vazio, mas pode ser redundante quando título e alt repetem a mesma informação. Considere omitir o alt via alt="" para ícones puramente decorativos em um partial customizado do tema.
  • Obrigatoriedade frouxa. required no atributo HTML impede submit no browser, mas não sobrevive a submissões programáticas. Use input filters para garantias server-side.