Introducción
Este tutorial explica con todo lujo de detalles cómo diseñar e implementar un bloque de Gutenberg para WordPress que muestre una Tabla de especificaciones destinada a plugins o temas. El objetivo es crear un bloque robusto, accesible, responsive y listo tanto para guardado en cliente (save) como para renderizado en servidor (render_callback) para máxima compatibilidad con temas y editores.
Resumen de características del bloque
- Edición visual en el editor de bloques con controles para filas, etiquetas y valores.
- Soporte para estilos: variantes compacta/extendida, columnas, iconos por fila.
- Renderizado seguro y semántico: lttablegt con lttheadgt y lttbodygt (se puede usar también ltdlgt, pero aquí usamos table para datos tabulares).
- Compatibilidad con server-side rendering para mantener SEO y macros dinámicas.
- Soporte para atributos serializados (JSON) y migraciones futuras.
Requisitos previos
- Entorno de desarrollo con Node.js y npm/yarn.
- Conocimiento básico de ESNext, React y la API de bloques de WordPress (@wordpress/blocks, @wordpress/components, @wordpress/block-editor).
- Opcional: herramienta @wordpress/create-block o @wordpress/scripts para compilación.
1) Estructura del proyecto y block.json
Comencemos con el archivo block.json, que define metadatos del bloque (nombre, icono, atributos, estilos). Este archivo facilita el registro automático del bloque.
{
apiVersion: 2,
name: mi-plugin/tabla-especificaciones,
title: Tabla de especificaciones,
category: widgets,
icon: editor-table,
description: Tabla para mostrar especificaciones técnicas de un plugin o tema.,
supports: {
html: false,
anchor: true
},
attributes: {
rows: {
type: array,
default: [
{ label: Versión, value: 1.0.0 },
{ label: Licencia, value: GPLv2 }
]
},
styleVariant: {
type: string,
default: standard
},
showHeader: {
type: boolean,
default: false
},
headerLabel: {
type: string,
default: Especificaciones
}
},
textdomain: mi-plugin,
editorScript: file:./build/index.js,
style: file:./build/style.css,
editorStyle: file:./build/editor.css
}
2) Archivo principal del editor (JavaScript)
En el editor se controla la UI: añadir/eliminar filas, editar etiquetas/valores, reordenar (si se desea añadirSortable). Aquí un ejemplo simplificado con componentes básicos de Gutenberg.
import { registerBlockType } from @wordpress/blocks
import {
useBlockProps,
RichText,
InspectorControls
} from @wordpress/block-editor
import {
PanelBody,
Button,
TextControl,
ToggleControl
} from @wordpress/components
import { Fragment } from @wordpress/element
registerBlockType(mi-plugin/tabla-especificaciones, {
edit: ({ attributes, setAttributes }) => {
const { rows, styleVariant, showHeader, headerLabel } = attributes
const blockProps = useBlockProps()
const updateRow = (index, key, value) => {
const newRows = rows.map((r, i) => i === index ? { ...r, [key]: value } : r)
setAttributes({ rows: newRows })
}
const addRow = () => {
setAttributes({ rows: [...rows, { label: Nueva fila, value: }] })
}
const removeRow = (index) => {
const newRows = rows.filter((_, i) => i !== index)
setAttributes({ rows: newRows })
}
return (
setAttributes({ headerLabel: v })}
/>
setAttributes({ showHeader: v })}
/>
Estilo:
{ showHeader { headerLabel }
}
{rows.map((row, index) => (
updateRow(index, label, v)}
placeholder=Etiqueta
/>
updateRow(index, value, v)}
placeholder=Valor
/>
))}
)
},
save: ({ attributes }) => {
const { rows, styleVariant, showHeader, headerLabel } = attributes
const blockProps = useBlockProps.save()
return (
{ showHeader { headerLabel }
}
{ rows.map((row, i) => (
{ row.label }
{ row.value }
)) }
)
}
})
Notas sobre el código JavaScript
- Se usan RichText para permitir edición inline de etiqueta y valor.
- Las filas se guardan como un array en los atributos esto facilita la serialización en el contenido del post.
- Las clases CSS aplican variantes visuales (standard / compact) que definiremos en el CSS.
3) Estilos (CSS)
Mantén un CSS simple, accesible y responsive. Define variantes y estilos para impresión/responsive.
.specs-table {
width: 100%
border-collapse: collapse
margin: 0 0 1em 0
}
.specs-table td {
border: 1px solid #e1e1e1
padding: 8px 10px
vertical-align: top
}
.specs-compact td {
padding: 6px 8px
font-size: 0.9em
}
@media (max-width: 600px) {
.specs-table, .specs-table tbody, .specs-table tr, .specs-table td {
display: block
width: 100%
}
.specs-table tr {
margin-bottom: 10px
}
.specs-table td {
border: none
padding: 6px 0
}
.specs-table td:first-child {
font-weight: bold
}
}
4) Renderizado en servidor (opcional pero recomendado)
Registrar un render callback en PHP permite controlar totalmente el marcado final, escapar salida y añadir microdatos (schema.org) o filtros. Ideal si quieres calcular valores dinámicos o incluir datos que no deben almacenarse en el post content.
mi_plugin_render_tabla_especificaciones
) )
}
add_action( init, mi_plugin_registrar_bloque_tabla_especificaciones )
function mi_plugin_render_tabla_especificaciones( attributes ) {
rows = isset( attributes[rows] ) ? attributes[rows] : array()
style = isset( attributes[styleVariant] ) ? esc_attr( attributes[styleVariant] ) : standard
show_header = ! empty( attributes[showHeader] )
header_label = isset( attributes[headerLabel] ) ? esc_html( attributes[headerLabel] ) :
// Comenzamos a construir el HTML de salida
html =
if ( show_header ) {
html .= . header_label .
}
html .= | . label . | html .=. value . | html .=
Buenas prácticas en el renderizado PHP
- Escapa la salida con wp_kses_post o funciones de escape según el contexto.
- Si quieres incluir atributos ARIA o schema.org, añádelos aquí para controlar su validez.
- Aplicar filtros de WordPress para permitir personalización: apply_filters(mi_plugin_spec_table_html, html, attributes).
5) Accesibilidad y semanticidad
Al ser una tabla de datos, usar lttablegt es la opción semánticamente correcta. Sin embargo, en móviles puedes cambiar visualmente a una estructura en bloques mediante CSS. Asegúrate de:
- Proveer contraste suficiente entre texto y fondo.
- Usar encabezados (si corresponde) y roles ARIA solo si es necesario.
- Permitir navegación por teclado en el editor y en la interfaz pública.
6) Variantes y estilos globales
Registra estilos para el bloque en block.json o mediante register_block_style en PHP para que el usuario pueda seleccionar variantes desde la barra lateral del bloque.
compacto,
label => Compacto
)
)
register_block_style(
mi-plugin/tabla-especificaciones,
array(
name => destacado,
label => Destacado
)
)
}
add_action( init, mi_plugin_registrar_estilos_bloque )
?>
7) Migraciones y cambios de atributos
Si en el futuro cambias la estructura de atributos (por ejemplo, añadir unit, icon, type), implementa funciones de migración en el archivo de edición para detectar viejos formatos y transformarlos. También puedes usar deprecated en registerBlockType para mantener retrocompatibilidad.
8) Shortcode de fallback (opcional)
Para compatibilidad con editores antiguos o para permitir inserción fuera del editor, puedes registrar un shortcode que acepte JSON o parámetros simples y renderice la tabla con la misma lógica PHP.
), atts, tabla_especificaciones )
rows = json_decode( stripslashes( atts[data] ), true )
if ( ! is_array( rows ) ) {
return
}
// Reusar la función de renderizado si se quiere
return mi_plugin_render_tabla_especificaciones( array( rows => rows ) )
}
add_shortcode( tabla_especificaciones, mi_plugin_shortcode_tabla_especificaciones )
?>
9) Pruebas, calidad y performance
- Prueba en varios themes para asegurar estilos no colisionen. Usa prefijos de clase (ej. .specs-table).
- Minimiza scripts y estilos: en producción usa builds con @wordpress/scripts o tu bundler.
- Si renderizas en servidor, evita consultas costosas en cada carga. Cachable si procede.
- Incluye pruebas unitarias o snapshot para la parte JS si tu flujo lo permite.
10) Ejemplo de salida final HTML (lo que verá el usuario)
Especificaciones
Versión 1.2.0 Licencia GPLv2 Soporte Foro en wordpress.org
Conclusión
Con este diseño tendrás un bloque de Tabla de especificaciones flexible y profesional, listo para integrarse en plugins o temas. Incluye la edición completa en Gutenberg, estilos personalizables y un renderizado en servidor para mantener seguridad y SEO. Adapta y amplía las funciones según necesidades: iconos por fila, reordenado con drag-and-drop, compatibilidad con WPML/Polylang, o generación automática desde los metadatos del plugin/tema.
Leave a Reply