Strelit Layout provides a number of hooks that make it easy to extend its native functionality, e.g. by adding additional controls to all headers.
The Goal
For this tutorial we’ll add a dropdown to every header that allows the user to change the background color.
It needs to:
- Change the component’s background color when a color is selected
- Set the initial color based on the component’s configuration
- Notify the LayoutManager about state changes when a new color is selected
The Result
Interactive Example: Add Control to Header
Inspect, fork, and test this complete layout implementation live on CodePen:
The Approach
Whenever a new Row, Column, Stack or Component is created, Strelit Layout emits an event, providing the new item as an argument.
myLayout.on('stackCreated', function (stack) {
// ...manipulate the stack
});
myLayout.on('componentCreated', function (component) {
// ...manipulate the component
});
Stacks, Rows, Columns and Components expose the Item API.
Please note: All components are children of Stacks (the item with the header and the tabs)! Even if a component is not configured as a child of a stack one will implicitly be added.
The Stack item provides access to its header (stack.header) and child components. For example:
myLayout.on('stackCreated', (stack) => {
/*
* Accessing the native DOM element that contains header control buttons:
* (popout, maximise, minimise, close)
*/
const customButton = document.createElement('button');
customButton.className = 'my-header-btn';
customButton.textContent = '⚙️';
stack.header.controlsContainerElement.prepend(customButton);
/*
* Listening for activeContentItemChanged:
* Fires initially and whenever the active tab switches
*/
stack.on('activeContentItemChanged', (componentItem) => {
console.log('Active tab switched to:', componentItem.title);
});
/*
* Accessing the active component container and element:
*/
const activeItem = stack.getActiveComponentItem();
if (activeItem) {
activeItem.container.element.style.borderColor = '#eab308';
}
});
Complete Code Example
myLayout.on('stackCreated', (stack) => {
// Create native dropdown container
const dropdown = document.createElement('select');
dropdown.className = 'header-color-select';
dropdown.innerHTML = `
<option value="#1e293b">Slate</option>
<option value="#14532d">Emerald</option>
<option value="#701a75">Fuchsia</option>
<option value="#1e3a5f">Navy</option>
`;
const setColor = (color) => {
const activeItem = stack.getActiveComponentItem();
if (!activeItem) return;
// Apply color directly to container's DOM element
activeItem.container.element.style.backgroundColor = color;
// Provide updated state for layout persistence
activeItem.container.stateRequestEvent = () => ({ color });
};
dropdown.addEventListener('change', (e) => {
setColor(e.target.value);
});
// Prepend dropdown into stack header controls
stack.header.controlsContainerElement.prepend(dropdown);
// Sync dropdown when active tab switches
stack.on('activeContentItemChanged', (item) => {
const state = item.container.initialState || {};
if (state.color) {
dropdown.value = state.color;
setColor(state.color);
}
});
});