Pular para o conteúdo principal

Botão

O bloco button-block emite um <a> estilizado com texto, URL e um estilo entre filled e outline. É um bloco autônomo que pode aparecer em qualquer layout e foi adicionado na versão 1.3 junto com os blocos de ícone, acordeão e barra de pesquisa.


Como foi construído

Identificação

ItemValor
ClasseSGMBlocks\Site\BlockLayout\ButtonBlock
block_layoutbutton-block
FormSGMBlocks\Form\ButtonBlockForm
FactorySGMBlocks\Service\BlockLayout\ButtonBlockFactory
Partialcommon/block-layout/button-block

Formulário

ButtonBlockForm tem três campos, todos não obrigatórios no required do atributo HTML, mas a renderização é condicional aos dois primeiros estarem preenchidos:

$this->add(['name' => 'o:block[__blockIndex__][o:data][button_text]',
'type' => Element\Text::class,
'options' => ['label' => 'Texto do Botão'],
'attributes' => ['required' => false]]);

$this->add(['name' => 'o:block[__blockIndex__][o:data][button_url]',
'type' => Element\Text::class,
'options' => ['label' => 'URL do Botão'],
'attributes' => ['required' => false]]);

$this->add(['name' => 'o:block[__blockIndex__][o:data][button_style]',
'type' => Element\Select::class,
'options' => ['label' => 'Estilo do Botão',
'value_options' => [
'filled' => 'Preenchido',
'outline' => 'Sem fundo (contorno)',
]],
'attributes' => ['value' => 'filled']]);

Classe do bloco

ButtonBlock não implementa prepareForm. Não injeta CSS nem JS no admin.

ButtonBlock::form popula os três campos a partir de $block->dataValue(...). button_style tem fallback para filled quando o valor é falsy.

ButtonBlock::render aplica um contrato de curto-circuito:

$buttonText = $block->dataValue('button_text');
$buttonUrl = $block->dataValue('button_url');
$buttonStyle = $block->dataValue('button_style') ?: 'filled';

if (empty($buttonText) || empty($buttonUrl)) {
return '';
}

return $view->partial('common/block-layout/button-block', [
'button_text' => $buttonText,
'button_url' => $buttonUrl,
'button_style' => $buttonStyle,
]);

Sem texto ou sem URL, o bloco retorna string vazia antes mesmo de delegar ao partial. Isso previne botões mudos ou links quebrados no frontend.

Partial

<?php
$escape = $this->plugin('escapeHtml');

$buttonText = isset($this->button_text) ? $this->button_text : null;
$buttonUrl = isset($this->button_url) ? $this->button_url : null;
$buttonStyle = isset($this->button_style) ? $this->button_style : 'filled';

if (empty($buttonText) || empty($buttonUrl)) {
return;
}

$buttonClasses = ($buttonStyle === 'outline')
? 'sgm-button sgm-button-outline'
: 'sgm-button sgm-button-filled';
?>

<div class="sgm-button-block">
<a href="<?php echo $escape($buttonUrl); ?>" class="<?php echo $buttonClasses; ?>">
<?php echo $escape($buttonText); ?>
</a>
</div>

O partial duplica a verificação de empty por precaução. Também aplica escapeHtml no href, o que é uma escolha conservadora: o canônico para atributos HTML é escapeHtmlAttr. Veja observações abaixo.

Persistência

Chave em o:dataTipoValores possíveisDefault efetivo
button_textstringqualquer stringvazio
button_urlstringURL absoluta ou âncoravazio
button_stylestringfilled ou outlinefilled

Assets carregados

  • Frontend: o partial não chama headLink. O CSS das classes sgm-button, sgm-button-filled, sgm-button-outline entra por outro bloco que já carregou style.css na página, ou pelo tema. Se o botão for o único bloco SGM da página, o CSS pode não ser carregado automaticamente.
  • Admin: nenhum asset específico.

Como usar como desenvolvedor

Garantir que o CSS seja carregado

Se a página usa apenas button-block sem nenhum outro bloco SGM que anexe style.css, o <a> sai sem estilo. Duas estratégias resolvem:

  1. Adicionar $this->headLink()->appendStylesheet($this->assetUrl('css/style.css', 'SGMBlocks')) ao partial do bloco.
  2. Anexar o CSS no layout do tema uma vez por site, independente dos blocos.

A primeira opção é mais coerente com os demais partials do módulo.

Adicionar um novo estilo de botão

Edite ButtonBlockForm para acrescentar a opção:

'value_options' => [
'filled' => 'Preenchido',
'outline' => 'Sem fundo (contorno)',
'ghost' => 'Fantasma',
],

Atualize o partial para mapear a nova string:

switch ($buttonStyle) {
case 'outline': $buttonClasses = 'sgm-button sgm-button-outline'; break;
case 'ghost': $buttonClasses = 'sgm-button sgm-button-ghost'; break;
default: $buttonClasses = 'sgm-button sgm-button-filled';
}

Acrescente a classe .sgm-button-ghost em asset/css/style.css.

Sobrescrever o partial no tema

Copie view/common/block-layout/button-block.phtml para themes/<tema>/view/common/block-layout/button-block.phtml. O tema passa a ditar a estrutura do botão inteira.

Ler o bloco em outros templates

foreach ($page->blocks() as $block) {
if ($block->layout() === 'button-block') {
$text = $block->dataValue('button_text');
$url = $block->dataValue('button_url');
}
}

Validar URL

Anexe um listener a form.add_input_filters do ButtonBlockForm com o validator Uri do Laminas:

$inputFilter->add([
'name' => 'o:block[__blockIndex__][o:data][button_url]',
'required' => false,
'validators' => [
['name' => 'Uri', 'options' => ['allowRelative' => true, 'allowAbsolute' => true]],
],
]);

Observações

  • escapeHtml em href. O correto para atributos HTML é escapeHtmlAttr. O escape atual funciona para URLs comuns porque <, > e & são os alvos, mas quebras de entidade com aspas ainda passam. Ao editar o partial, prefira escapeHtmlAttr no atributo.
  • Bloqueio silencioso de render. Quando button_text ou button_url estão vazios, o bloco some. O admin não avisa. Para orientar editores, torne os dois campos obrigatórios no form ou avise via mensagem customizada no editor.
  • Assets fora do partial. O bloco não carrega style.css. Se o botão aparece sem borda ou fundo, é esse o motivo.
  • Rótulo do select. O valor traduzível do ButtonBlockForm para a opção outline é a string literal 'Sem fundo (contorno)'. Está no value_options do Select e aparece assim no admin. Em revisões futuras pode-se decidir se o texto exibido deve ser simplificado, mas a coluna button_style persistida continua sendo outline.