📖Browse Tutorials▼

Header Controls

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);
    }
  });
});

Whether you are building complex multi-screen trading terminals, enterprise data workspaces, or migrating from legacy layout engines, our team and community are here to help.

Open an Issue on GitHub →