Theme Integration
Learn how to integrate and customize the Entityqueue Form Widget in your Drupal theme.
Template Files
Main Widget Template
Default Location: modules/contrib/entityqueue_form_widget/templates/entityqueue-form-widget.html.twig
Override In Theme: your-theme/templates/form/entityqueue-form-widget.html.twig
Default Template Structure
<fieldset{{ attributes }}>
{% if legend_title %}
<legend>{{ legend_title }}</legend>
{% endif %}
<div class="form-section form-section--entityqueues">
{% for key, child in children %}
{% if key|first != '#' %}
<div class="form-item form-item--entityqueue">
{{ child }}
</div>
{% endif %}
{% endfor %}
</div>
</fieldset>
Template Variables
Available Variables in Widget Template
attributes {# HTML attributes for fieldset #}
legend_title {# "Entityqueues" or custom title #}
children {# Checkbox elements #}
Variables in Each Queue Item
id {# Checkbox ID #}
name {# Form element name #}
label {# Queue label/name #}
description {# Queue description #}
checked {# Boolean: is queue checked #}
disabled {# Boolean: is queue disabled #}
required {# Boolean: is queue required #}
attributes {# HTML attributes #}
Template Customization Examples
Example 1: Custom Widget Container
File: your-theme/templates/form/entityqueue-form-widget.html.twig
<div class="entityqueue-widget-container">
<div class="entityqueue-widget-header">
<h3 class="entityqueue-widget-title">
{% if legend_title %}
{{ legend_title }}
{% else %}
{{ 'Queues'|t }}
{% endif %}
</h3>
<p class="entityqueue-widget-description">
{{ 'Select queues to include this content in different sections.'|t }}
</p>
</div>
<div class="entityqueue-widget-items">
{% for key, child in children %}
{% if key|first != '#' %}
<div class="entityqueue-widget-item">
{{ child }}
</div>
{% endif %}
{% endfor %}
</div>
</div>
Example 2: Grid Layout
<fieldset class="entityqueue-form-widget entityqueue-form-widget--grid"{{ attributes }}>
{% if legend_title %}
<legend class="entityqueue-form-widget__legend">
{{ legend_title }}
</legend>
{% endif %}
<div class="entityqueue-form-widget__items entityqueue-form-widget__items--grid">
{% for key, child in children %}
{% if key|first != '#' %}
<div class="entityqueue-form-widget__item">
{{ child }}
</div>
{% endif %}
{% endfor %}
</div>
</fieldset>
Example 3: With Help Text
<fieldset class="entityqueue-widget"{{ attributes }}>
{% if legend_title %}
<legend class="entityqueue-widget__legend">
<strong>{{ legend_title }}</strong>
<span class="entityqueue-widget__required" title="{{ 'Required' }}">*</span>
</legend>
{% endif %}
<div class="entityqueue-widget__description">
<p>
{{ 'Choose which featured sections this content should appear in:'|t }}
</p>
</div>
<div class="entityqueue-widget__items">
{% for key, child in children %}
{% if key|first != '#' %}
{% set queue_name = key|replace('_', ' ')|capitalize %}
<div class="entityqueue-widget__item">
<label class="entityqueue-widget__label">
{{ child }}
<span class="entityqueue-widget__queue-name">{{ queue_name }}</span>
</label>
<small class="entityqueue-widget__hint">
{% if 'featured' in key|lower %}
{{ 'This queue has a limit of 5 items'|t }}
{% endif %}
</small>
</div>
{% endif %}
{% endfor %}
</div>
</fieldset>
CSS Styling
Default CSS Classes
/* Widget container */
.entityqueue-form-widget
.form-section--entityqueues
/* Individual items */
.form-item--entityqueue
.entityqueue-widget-item
/* Checkbox label */
.entityqueue-widget__label
/* Legend/title */
.fieldset__legend
CSS Examples
Basic Styling
/* Widget container */
.entityqueue-form-widget {
border: 1px solid #ddd;
border-radius: 4px;
padding: 15px;
margin-bottom: 20px;
background-color: #f9f9f9;
}
/* Widget title */
.entityqueue-form-widget .fieldset__legend {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
}
/* Individual queue item */
.entityqueue-widget-item {
margin-bottom: 10px;
padding: 8px;
}
/* Queue checkbox */
.entityqueue-widget-item input[type="checkbox"] {
margin-right: 8px;
}
/* Queue label */
.entityqueue-widget-item label {
display: flex;
align-items: center;
cursor: pointer;
}
Grid Layout
.entityqueue-form-widget--grid .entityqueue-widget-items {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 15px;
}
.entityqueue-form-widget--grid .entityqueue-widget-item {
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
background: white;
transition: background-color 0.2s;
}
.entityqueue-form-widget--grid .entityqueue-widget-item:hover {
background-color: #f5f5f5;
}
.entityqueue-form-widget--grid .entityqueue-widget-item input:checked ~ label {
font-weight: bold;
color: #0066cc;
}
Responsive Design
/* Large screens */
@media (min-width: 1024px) {
.entityqueue-widget-items {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
}
/* Tablets */
@media (min-width: 768px) and (max-width: 1023px) {
.entityqueue-widget-items {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
}
/* Mobile */
@media (max-width: 767px) {
.entityqueue-widget-items {
display: block;
}
.entityqueue-widget-item {
margin-bottom: 10px;
}
}
JavaScript Integration
Attach Behaviors to Widget
Location: your-theme/js/entityqueue-widget.js
(function (Drupal) {
'use strict';
Drupal.behaviors.entityqueueWidgetCustom = {
attach: function (context, settings) {
// Find all entityqueue checkboxes
const checkboxes = context.querySelectorAll(
'.entityqueue-widget input[type="checkbox"]'
);
checkboxes.forEach(checkbox => {
// Add custom behavior on change
checkbox.addEventListener('change', function() {
const queueId = this.name;
const isChecked = this.checked;
// Custom behavior
if (isChecked) {
this.closest('.entityqueue-widget-item')
.classList.add('is-selected');
Drupal.announce('Added to queue: ' + queueId);
} else {
this.closest('.entityqueue-widget-item')
.classList.remove('is-selected');
Drupal.announce('Removed from queue: ' + queueId);
}
});
});
}
};
})(Drupal);
Add to Theme Libraries
File: your-theme/your-theme.libraries.yml
entityqueue-widget:
version: 1.0
js:
js/entityqueue-widget.js: {}
css:
theme:
css/entityqueue-widget.css: {}
Attach Library in Template
{# In entityqueue-form-widget.html.twig #}
{{ attach_library('your_theme/entityqueue-widget') }}
<fieldset{{ attributes }}>
{# ... template content ... #}
</fieldset>
Accessibility
ARIA Labels
<fieldset class="entityqueue-widget" aria-label="{{ legend_title }}">
<legend>{{ legend_title }}</legend>
<div class="entityqueue-widget-items" role="group">
{% for key, child in children %}
{% if key|first != '#' %}
<div class="entityqueue-widget-item">
<input
type="checkbox"
id="{{ id }}-{{ key }}"
name="{{ name }}[{{ key }}]"
aria-label="Add to {{ queue_label }}"
aria-describedby="{{ id }}-{{ key }}-description"
/>
<label for="{{ id }}-{{ key }}">{{ queue_label }}</label>
<small id="{{ id }}-{{ key }}-description">
{{ queue_description }}
</small>
</div>
{% endif %}
{% endfor %}
</div>
</fieldset>
Keyboard Navigation
Ensure: - Tab key navigates through checkboxes - Space/Enter toggles checkboxes - Focus indicators visible - No keyboard traps
Screen Reader Support
Attributes:
<fieldset role="group" aria-label="Content queues">
<legend>Queues</legend>
<input
type="checkbox"
aria-label="Add to Featured Articles queue"
aria-describedby="featured-help"
/>
<span id="featured-help">Select to feature on homepage</span>
</fieldset>
Theme Integration Checklist
Before deploying theme changes:
- [ ] Templates override correctly
- [ ] CSS classes properly styled
- [ ] Grid/responsive layout works
- [ ] Checkboxes remain functional
- [ ] Keyboard navigation works
- [ ] Mobile/tablet view responsive
- [ ] Colors accessible (contrast)
- [ ] Labels descriptive for screen readers
- [ ] JavaScript behaviors attach correctly
- [ ] No console errors
Common Customization Scenarios
Scenario 1: Change Queue Display to Buttons
<div class="entityqueue-buttons">
{% for key, child in children %}
{% if key|first != '#' %}
<button
type="button"
class="entityqueue-button"
aria-pressed="{{ child['#checked'] ? 'true' : 'false' }}"
data-queue="{{ key }}"
>
{{ child['#title'] }}
</button>
{% endif %}
{% endfor %}
</div>
With JavaScript:
document.querySelectorAll('.entityqueue-button').forEach(btn => {
btn.addEventListener('click', function() {
const checkbox = document.querySelector(`input[name*="${this.dataset.queue}"]`);
checkbox.checked = !checkbox.checked;
checkbox.dispatchEvent(new Event('change'));
});
});
Scenario 2: Conditional Display by Role
// In your theme's theme file
function your_theme_theme_suggestions_entityqueue_form_widget_alter(&$suggestions, $variables) {
$user = \Drupal::currentUser();
if ($user->hasRole('editor')) {
$suggestions[] = 'entityqueue_form_widget__editor';
}
return $suggestions;
}
Then create: templates/form/entityqueue-form-widget--editor.html.twig
Scenario 3: Add Icons to Queues
<div class="entityqueue-widgets-with-icons">
{% for key, child in children %}
{% if key|first != '#' %}
<div class="entityqueue-item-with-icon">
<span class="entityqueue-icon" aria-hidden="true">
{% if 'featured' in key|lower %}
⭐
{% elseif 'trending' in key|lower %}
📈
{% else %}
📌
{% endif %}
</span>
<label>
{{ child }}
<span>{{ child['#title'] }}</span>
</label>
</div>
{% endif %}
{% endfor %}
</div>