This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 15d8b3cd13 Rewrite toolbars to properly work in hop web, fixes #6495 
(#6501)
15d8b3cd13 is described below

commit 15d8b3cd13b84e94be837ac04e8b7ca668506696
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Fri Feb 6 13:16:35 2026 +0100

    Rewrite toolbars to properly work in hop web, fixes #6495 (#6501)
---
 .../main/java/org/apache/hop/git/GitGuiPlugin.java |  31 +-
 .../apache/hop/projects/gui/ProjectsGuiPlugin.java | 131 +++---
 .../apache/hop/testing/gui/TestingGuiPlugin.java   |   9 +-
 .../apache/hop/ui/hopgui/ToolbarFacadeImpl.java    |  43 ++
 .../apache/hop/ui/hopgui/WebToolbarContainer.java  |  44 ++
 .../org/apache/hop/ui/core/widget/svg/svg-label.js |  79 +++-
 .../hop/ui/hopgui/ToolBarToolbarContainer.java     |  44 ++
 .../apache/hop/ui/hopgui/ToolbarFacadeImpl.java    |  31 ++
 .../database/dialog/DatabaseExplorerDialog.java    |  12 +-
 .../apache/hop/ui/core/dialog/ContextDialog.java   |  10 +-
 .../apache/hop/ui/core/gui/GuiToolbarWidgets.java  | 467 ++++++++++++++++-----
 .../apache/hop/ui/core/gui/IToolbarContainer.java  |  38 ++
 .../hop/ui/core/gui/IToolbarWidgetRegistrar.java   |  35 ++
 .../apache/hop/ui/core/vfs/HopVfsFileDialog.java   |  27 +-
 .../hop/ui/core/widget/MetaSelectionLine.java      |  16 +-
 .../org/apache/hop/ui/core/widget/TableView.java   |  11 +-
 .../main/java/org/apache/hop/ui/hopgui/HopGui.java |  17 +-
 .../org/apache/hop/ui/hopgui/ToolbarFacade.java    |  70 +++
 .../hopgui/file/pipeline/HopGuiPipelineGraph.java  |  30 +-
 .../delegates/HopGuiPipelineCheckDelegate.java     |  10 +-
 .../delegates/HopGuiPipelineGridDelegate.java      |  50 ++-
 .../delegates/HopGuiPipelineLogDelegate.java       |  13 +-
 .../hopgui/file/workflow/HopGuiWorkflowGraph.java  |  25 +-
 .../delegates/HopGuiWorkflowCheckDelegate.java     |  10 +-
 .../delegates/HopGuiWorkflowLogDelegate.java       |  13 +-
 .../execution/ExecutionPerspective.java            |  10 +-
 .../execution/PipelineExecutionViewer.java         |   9 +-
 .../execution/WorkflowExecutionViewer.java         |   9 +-
 .../perspective/explorer/ExplorerPerspective.java  |  10 +-
 .../perspective/metadata/MetadataPerspective.java  |   8 +-
 .../hop/ui/hopgui/shared/BaseExecutionViewer.java  |   8 +-
 31 files changed, 1004 insertions(+), 316 deletions(-)

diff --git 
a/plugins/misc/git/src/main/java/org/apache/hop/git/GitGuiPlugin.java 
b/plugins/misc/git/src/main/java/org/apache/hop/git/GitGuiPlugin.java
index bc8124f053..72c437050a 100644
--- a/plugins/misc/git/src/main/java/org/apache/hop/git/GitGuiPlugin.java
+++ b/plugins/misc/git/src/main/java/org/apache/hop/git/GitGuiPlugin.java
@@ -68,10 +68,10 @@ import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.MenuItem;
 import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.ToolItem;
 import org.eclipse.swt.widgets.Tree;
 import org.eclipse.swt.widgets.TreeItem;
 
@@ -335,10 +335,11 @@ public class GitGuiPlugin
       toolTip = "i18n::GitGuiPlugin.Toolbar.Branch.Tooltip",
       separator = true)
   public void showGitContextMenu() {
-    ToolItem item = getGitToolItem();
-    if (item != null) {
-      Rectangle rect = item.getBounds();
-      Point pt = item.getParent().toDisplay(new Point(rect.x, rect.y + 
rect.height));
+    GuiToolbarWidgets statusWidgets = 
HopGui.getInstance().getStatusToolbarWidgets();
+    Control control = statusWidgets.getWidgetsMap().get(ID_TOOLBAR_ITEM_GIT);
+    if (control != null && !control.isDisposed()) {
+      Rectangle rect = control.getBounds();
+      Point pt = control.getParent().toDisplay(new Point(rect.x, rect.y + 
rect.height));
       Menu menu = createGitContextMenu();
       menu.setLocation(pt);
       menu.setVisible(true);
@@ -600,7 +601,8 @@ public class GitGuiPlugin
       label = "i18n::GitGuiPlugin.Menu.Branch.Rename.Text",
       image = "ui/images/rename.svg")
   public void gitRenameBranch() {
-    String oldName = getGitToolItem().getText();
+    String oldName =
+        
HopGui.getInstance().getStatusToolbarWidgets().getToolbarItemText(ID_TOOLBAR_ITEM_GIT);
     EnterStringDialog enterStringDialog =
         new EnterStringDialog(
             HopGui.getInstance().getShell(),
@@ -848,7 +850,7 @@ public class GitGuiPlugin
     menuWidgets.enableMenuItem(CONTEXT_MENU_GIT_COMMIT, isSelected);
     menuWidgets.enableMenuItem(CONTEXT_MENU_GIT_REVERT, isSelected);
 
-    getGitToolItem().setEnabled(isGit);
+    
HopGui.getInstance().getStatusToolbarWidgets().enableToolbarItem(ID_TOOLBAR_ITEM_GIT,
 isGit);
   }
 
   /**
@@ -931,17 +933,10 @@ public class GitGuiPlugin
     return git;
   }
 
-  private static ToolItem getGitToolItem() {
-    return 
HopGui.getInstance().getStatusToolbarWidgets().findToolItem(ID_TOOLBAR_ITEM_GIT);
-  }
-
   private void setBranchLabel(String branch) {
-    // Set the branch name using the new method that handles both SWT and RWT
-    ToolItem item = getGitToolItem();
-    if (item != null && !item.isDisposed()) {
-      HopGui.getInstance()
-          .getStatusToolbarWidgets()
-          .setToolbarItemText(ID_TOOLBAR_ITEM_GIT, Const.NVL(branch, ""));
-    }
+    // Set the branch name using the new method that handles both SWT and RWT 
(and flow toolbar)
+    HopGui.getInstance()
+        .getStatusToolbarWidgets()
+        .setToolbarItemText(ID_TOOLBAR_ITEM_GIT, Const.NVL(branch, ""));
   }
 }
diff --git 
a/plugins/misc/projects/src/main/java/org/apache/hop/projects/gui/ProjectsGuiPlugin.java
 
b/plugins/misc/projects/src/main/java/org/apache/hop/projects/gui/ProjectsGuiPlugin.java
index 1d4ff72835..36bbd62321 100644
--- 
a/plugins/misc/projects/src/main/java/org/apache/hop/projects/gui/ProjectsGuiPlugin.java
+++ 
b/plugins/misc/projects/src/main/java/org/apache/hop/projects/gui/ProjectsGuiPlugin.java
@@ -81,6 +81,7 @@ import org.apache.hop.ui.core.dialog.MessageBox;
 import org.apache.hop.ui.core.dialog.ProgressMonitorDialog;
 import org.apache.hop.ui.core.gui.GuiMenuWidgets;
 import org.apache.hop.ui.core.gui.GuiResource;
+import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
 import org.apache.hop.ui.core.gui.HopNamespace;
 import org.apache.hop.ui.core.vfs.HopVfsFileDialog;
 import org.apache.hop.ui.core.widget.FileTree;
@@ -94,11 +95,11 @@ import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.layout.FormLayout;
 import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.MenuItem;
 import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.ToolItem;
 
 @GuiPlugin
 public class ProjectsGuiPlugin {
@@ -273,66 +274,48 @@ public class ProjectsGuiPlugin {
     }
   }
 
-  private static ToolItem getProjectToolItem() {
-    return 
HopGui.getInstance().getStatusToolbarWidgets().findToolItem(ID_TOOLBAR_ITEM_PROJECT);
-  }
-
-  private static ToolItem getEnvironmentToolItem() {
-    return 
HopGui.getInstance().getStatusToolbarWidgets().findToolItem(ID_TOOLBAR_ITEM_ENVIRONMENT);
-  }
-
   private static void updateProjectToolItem(String projectName) {
-    ToolItem item = getProjectToolItem();
-    if (item != null && !item.isDisposed()) {
-      ProjectsConfig config = ProjectsConfigSingleton.getConfig();
-      ProjectConfig projectConfig = config.findProjectConfig(projectName);
-      if (projectConfig != null) {
-        String projectHome = projectConfig.getProjectHome();
-        if (StringUtils.isNotEmpty(projectHome)) {
-          // Use the new method that handles both SWT and RWT
-          HopGui.getInstance()
-              .getStatusToolbarWidgets()
-              .setToolbarItemText(ID_TOOLBAR_ITEM_PROJECT, projectName);
-          item.setToolTipText(
-              BaseMessages.getString(
-                  PKG,
-                  "HopGui.Toolbar.Project.Tooltip",
-                  projectName,
-                  projectHome,
-                  projectConfig.getConfigFilename()));
-        }
+    GuiToolbarWidgets statusWidgets = 
HopGui.getInstance().getStatusToolbarWidgets();
+    ProjectsConfig config = ProjectsConfigSingleton.getConfig();
+    ProjectConfig projectConfig = config.findProjectConfig(projectName);
+    if (projectConfig != null) {
+      String projectHome = projectConfig.getProjectHome();
+      if (StringUtils.isNotEmpty(projectHome)) {
+        statusWidgets.setToolbarItemText(ID_TOOLBAR_ITEM_PROJECT, projectName);
+        statusWidgets.setToolbarItemToolTip(
+            ID_TOOLBAR_ITEM_PROJECT,
+            BaseMessages.getString(
+                PKG,
+                "HopGui.Toolbar.Project.Tooltip",
+                projectName,
+                projectHome,
+                projectConfig.getConfigFilename()));
       }
     }
   }
 
   private static void updateEnvironmentToolItem(String environmentName) {
-    ToolItem item = getEnvironmentToolItem();
-    if (item != null && !item.isDisposed()) {
-      if (Utils.isEmpty(environmentName)) {
-        // Use the new method that handles both SWT and RWT
-        HopGui.getInstance()
-            .getStatusToolbarWidgets()
-            .setToolbarItemText(ID_TOOLBAR_ITEM_ENVIRONMENT, "");
-        item.setToolTipText(
-            BaseMessages.getString(PKG, 
"HopGui.Toolbar.Environment.Select.Tooltip"));
-        return;
-      }
+    GuiToolbarWidgets statusWidgets = 
HopGui.getInstance().getStatusToolbarWidgets();
+    if (Utils.isEmpty(environmentName)) {
+      statusWidgets.setToolbarItemText(ID_TOOLBAR_ITEM_ENVIRONMENT, "");
+      statusWidgets.setToolbarItemToolTip(
+          ID_TOOLBAR_ITEM_ENVIRONMENT,
+          BaseMessages.getString(PKG, 
"HopGui.Toolbar.Environment.Select.Tooltip"));
+      return;
+    }
 
-      ProjectsConfig config = ProjectsConfigSingleton.getConfig();
-      LifecycleEnvironment environment = 
config.findEnvironment(environmentName);
-      if (environment != null) {
-        // Use the new method that handles both SWT and RWT
-        HopGui.getInstance()
-            .getStatusToolbarWidgets()
-            .setToolbarItemText(ID_TOOLBAR_ITEM_ENVIRONMENT, environmentName);
-        item.setToolTipText(
-            BaseMessages.getString(
-                PKG,
-                "HopGui.Toolbar.Environment.Tooltip",
-                environmentName,
-                environment.getProjectName(),
-                environment.getPurpose()));
-      }
+    ProjectsConfig config = ProjectsConfigSingleton.getConfig();
+    LifecycleEnvironment environment = config.findEnvironment(environmentName);
+    if (environment != null) {
+      statusWidgets.setToolbarItemText(ID_TOOLBAR_ITEM_ENVIRONMENT, 
environmentName);
+      statusWidgets.setToolbarItemToolTip(
+          ID_TOOLBAR_ITEM_ENVIRONMENT,
+          BaseMessages.getString(
+              PKG,
+              "HopGui.Toolbar.Environment.Tooltip",
+              environmentName,
+              environment.getProjectName(),
+              environment.getPurpose()));
     }
   }
 
@@ -459,11 +442,14 @@ public class ProjectsGuiPlugin {
           if (askAboutProjectRefresh(hopGui)) {
             // Try to stick to the same environment if we have one selected...
             //
-            LifecycleEnvironment environment = null;
-            ToolItem environmentItem = getEnvironmentToolItem();
-            if (environmentItem != null) {
-              environment = config.findEnvironment(environmentItem.getText());
-            }
+            String environmentName =
+                HopGui.getInstance()
+                    .getStatusToolbarWidgets()
+                    .getToolbarItemText(ID_TOOLBAR_ITEM_ENVIRONMENT);
+            LifecycleEnvironment environment =
+                StringUtils.isNotEmpty(environmentName)
+                    ? config.findEnvironment(environmentName)
+                    : null;
             enableHopGuiProject(projectConfig.getProjectName(), project, 
environment);
           }
 
@@ -497,10 +483,11 @@ public class ProjectsGuiPlugin {
       image = "project.svg",
       toolTip = "i18n::HopGui.Toolbar.Project.Tooltip")
   public void showProjectContextMenu() {
-    ToolItem item = getProjectToolItem();
-    if (item != null) {
-      Rectangle rect = item.getBounds();
-      Point location = item.getParent().toDisplay(new Point(rect.x, rect.y + 
rect.height));
+    Control control =
+        
HopGui.getInstance().getStatusToolbarWidgets().getControlForMenu(ID_TOOLBAR_ITEM_PROJECT);
+    if (control != null && !control.isDisposed()) {
+      Rectangle rect = control.getBounds();
+      Point location = control.getParent().toDisplay(new Point(rect.x, rect.y 
+ rect.height));
       Menu menu = createProjectContextMenu();
       menu.setLocation(location);
       menu.setVisible(true);
@@ -622,10 +609,13 @@ public class ProjectsGuiPlugin {
       image = "environment.svg",
       toolTip = "i18n::HopGui.Toolbar.Environment.Tooltip")
   public void showEnvironmentContextMenu() {
-    ToolItem item = getEnvironmentToolItem();
-    if (item != null) {
-      Rectangle rect = item.getBounds();
-      Point location = item.getParent().toDisplay(new Point(rect.x, rect.y + 
rect.height));
+    Control control =
+        HopGui.getInstance()
+            .getStatusToolbarWidgets()
+            .getControlForMenu(ID_TOOLBAR_ITEM_ENVIRONMENT);
+    if (control != null && !control.isDisposed()) {
+      Rectangle rect = control.getBounds();
+      Point location = control.getParent().toDisplay(new Point(rect.x, rect.y 
+ rect.height));
       Menu menu = createEnvironmentContextMenu();
       menu.setLocation(location);
       menu.setVisible(true);
@@ -1287,11 +1277,8 @@ public class ProjectsGuiPlugin {
     if (zipFilename == null) {
       return;
     }
-    ToolItem projectItem = getProjectToolItem();
-    if (projectItem == null) {
-      return;
-    }
-    String projectName = projectItem.getText();
+    String projectName =
+        
HopGui.getInstance().getStatusToolbarWidgets().getToolbarItemText(ID_TOOLBAR_ITEM_PROJECT);
     if (StringUtils.isEmpty(projectName)) {
       return;
     }
diff --git 
a/plugins/misc/testing/src/main/java/org/apache/hop/testing/gui/TestingGuiPlugin.java
 
b/plugins/misc/testing/src/main/java/org/apache/hop/testing/gui/TestingGuiPlugin.java
index 4ba0658774..e696fe79a0 100644
--- 
a/plugins/misc/testing/src/main/java/org/apache/hop/testing/gui/TestingGuiPlugin.java
+++ 
b/plugins/misc/testing/src/main/java/org/apache/hop/testing/gui/TestingGuiPlugin.java
@@ -889,8 +889,7 @@ public class TestingGuiPlugin {
       root = HopGuiPipelineGraph.GUI_PLUGIN_TOOLBAR_PARENT_ID,
       id = ID_TOOLBAR_ITEM_UNIT_TEST_EDIT,
       toolTip = "i18n::TestingGuiPlugin.ToolbarElement.UnitTest.Edit.Tooltip",
-      image = "Test_tube_icon_edit.svg",
-      separator = true)
+      image = "Test_tube_icon_edit.svg")
   public void editUnitTest() {
     HopGui hopGui = HopGui.getInstance();
     PipelineMeta pipelineMeta = getActivePipelineMeta();
@@ -954,8 +953,7 @@ public class TestingGuiPlugin {
       root = HopGuiPipelineGraph.GUI_PLUGIN_TOOLBAR_PARENT_ID,
       id = ID_TOOLBAR_ITEM_UNIT_TESTS_CREATE,
       toolTip = 
"i18n::TestingGuiPlugin.ToolbarElement.UnitTest.Create.Tooltip",
-      image = "Test_tube_icon_create.svg",
-      separator = true)
+      image = "Test_tube_icon_create.svg")
   public void createUnitTest() {
     HopGui hopGui = HopGui.getInstance();
     PipelineMeta pipelineMeta = getActivePipelineMeta();
@@ -990,8 +988,7 @@ public class TestingGuiPlugin {
       root = HopGuiPipelineGraph.GUI_PLUGIN_TOOLBAR_PARENT_ID,
       id = ID_TOOLBAR_ITEM_UNIT_TESTS_DELETE,
       toolTip = 
"i18n::TestingGuiPlugin.ToolbarElement.UnitTest.Delete.Tooltip",
-      image = "Test_tube_icon_delete.svg",
-      separator = true)
+      image = "Test_tube_icon_delete.svg")
   public void deleteUnitTest() {
     HopGui hopGui = HopGui.getInstance();
     PipelineMeta pipelineMeta = getActivePipelineMeta();
diff --git a/rap/src/main/java/org/apache/hop/ui/hopgui/ToolbarFacadeImpl.java 
b/rap/src/main/java/org/apache/hop/ui/hopgui/ToolbarFacadeImpl.java
new file mode 100644
index 0000000000..baafdee4d9
--- /dev/null
+++ b/rap/src/main/java/org/apache/hop/ui/hopgui/ToolbarFacadeImpl.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+import org.apache.hop.core.Props;
+import org.apache.hop.ui.core.PropsUi;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+
+/** Hop Web (RAP) implementation: returns a container wrapping a Composite 
with RowLayout (wrap). */
+public class ToolbarFacadeImpl extends ToolbarFacade {
+
+  @Override
+  protected IToolbarContainer createToolbarContainerInternal(Composite parent, 
int style) {
+    Composite composite = new Composite(parent, SWT.NONE);
+    RowLayout rowLayout = new RowLayout(SWT.HORIZONTAL);
+    rowLayout.wrap = true;
+    rowLayout.spacing = 4;
+    rowLayout.marginWidth = 0;
+    rowLayout.marginHeight = 0;
+    rowLayout.center = true;
+    composite.setLayout(rowLayout);
+    PropsUi.setLook(composite, Props.WIDGET_STYLE_TOOLBAR);
+    return new WebToolbarContainer(composite);
+  }
+}
diff --git 
a/rap/src/main/java/org/apache/hop/ui/hopgui/WebToolbarContainer.java 
b/rap/src/main/java/org/apache/hop/ui/hopgui/WebToolbarContainer.java
new file mode 100644
index 0000000000..28474a8e01
--- /dev/null
+++ b/rap/src/main/java/org/apache/hop/ui/hopgui/WebToolbarContainer.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarItem;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
+import org.apache.hop.ui.core.gui.IToolbarWidgetRegistrar;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/** Hop Web (RAP) toolbar container: wraps a Composite with RowLayout (wrap). 
*/
+public class WebToolbarContainer implements IToolbarContainer {
+
+  private final Composite composite;
+
+  public WebToolbarContainer(Composite composite) {
+    this.composite = composite;
+  }
+
+  @Override
+  public Control getControl() {
+    return composite;
+  }
+
+  @Override
+  public void addItem(GuiToolbarItem item, IToolbarWidgetRegistrar registrar) {
+    registrar.addItem(item, composite);
+  }
+}
diff --git 
a/rap/src/main/resources/org/apache/hop/ui/core/widget/svg/svg-label.js 
b/rap/src/main/resources/org/apache/hop/ui/core/widget/svg/svg-label.js
index 41d1a707d0..2ede6bd060 100644
--- a/rap/src/main/resources/org/apache/hop/ui/core/widget/svg/svg-label.js
+++ b/rap/src/main/resources/org/apache/hop/ui/core/widget/svg/svg-label.js
@@ -16,33 +16,88 @@
  *
  */
 
+function findImg(widget, id) {
+    var img = document.getElementById(id);
+    if (img === null && widget.$el && widget.$el[0]) {
+        img = widget.$el[0].querySelector('img');
+    }
+    return img;
+}
+
+/** Apply transparent background (and optionally opacity) so toolbar has no 
white box. */
+function applyShowStylesToImg(img, opacity) {
+    if (!img) return;
+    img.style.background = 'transparent';
+    if (opacity != null) {
+        img.style.opacity = opacity;
+    }
+    if (img.parentElement) {
+        img.parentElement.style.background = 'transparent';
+    }
+    if (img.parentElement && img.parentElement.parentElement) {
+        img.parentElement.parentElement.style.background = 'transparent';
+    }
+}
+
+/** Only set transparent background; do not touch opacity (preserves 
enabled/disabled state). */
+function applyTransparentBackgroundOnly(img) {
+    if (!img) return;
+    img.style.background = 'transparent';
+    if (img.parentElement) {
+        img.parentElement.style.background = 'transparent';
+    }
+    if (img.parentElement && img.parentElement.parentElement) {
+        img.parentElement.parentElement.style.background = 'transparent';
+    }
+}
+
+/**
+ * Find the toolbar container and set transparent background on every img so 
the last item
+ * is never missed. We do not set opacity here so we don't overwrite 
setEnabled (opacity 0.3).
+ */
+function styleAllToolbarImgsFrom(img) {
+    if (!img) return;
+    var node = img.parentElement;
+    var toolbar = null;
+    while (node) {
+        if (node.children && node.children.length > 2) {
+            toolbar = node;
+            break;
+        }
+        node = node.parentElement;
+    }
+    if (!toolbar) return;
+    for (var i = 0; i < toolbar.children.length; i++) {
+        var child = toolbar.children[i];
+        var im = child.querySelector ? child.querySelector('img') : null;
+        if (im) {
+            applyTransparentBackgroundOnly(im);
+        }
+    }
+}
+
 const handleEvent = function (event) {
     const widget = event.widget;
 
     const props = widget.getData('props');
+    if (!props || props.id == null) {
+        return;
+    }
     const id = props.id;
 
-    let img = document.getElementById(id);
-
-    if (img===null) {
+    const img = findImg(widget, id);
+    if (img === null) {
         return;
     }
 
     switch (event.type) {
         case SWT.MouseDown:
-            // Handled by regular SWT listener
             break;
         case SWT.Hide:
-            // The widget is hidden so changing anything doesn't matter.
             break;
         case SWT.Show:
-            // We always get one call here, so we can set the background 
transparent and adjust the style in general.
-            // Respect the initial enabled state from props
-            //
-            img.style.background = 'transparent';
-            img.style.opacity = props.enabled ? '1.0' : '0.3';
-            img.parentElement.style.background = 'transparent';
-            img.parentElement.parentElement.style.background = 'transparent';
+            applyShowStylesToImg(img, props.enabled ? '1.0' : '0.3');
+            styleAllToolbarImgsFrom(img);
             break;
         case SWT.MouseEnter:
             // Try to make the background a bit gray
diff --git 
a/rcp/src/main/java/org/apache/hop/ui/hopgui/ToolBarToolbarContainer.java 
b/rcp/src/main/java/org/apache/hop/ui/hopgui/ToolBarToolbarContainer.java
new file mode 100644
index 0000000000..4d536af919
--- /dev/null
+++ b/rcp/src/main/java/org/apache/hop/ui/hopgui/ToolBarToolbarContainer.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarItem;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
+import org.apache.hop.ui.core.gui.IToolbarWidgetRegistrar;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.ToolBar;
+
+/** Desktop (RCP) toolbar container: wraps an SWT ToolBar. */
+public class ToolBarToolbarContainer implements IToolbarContainer {
+
+  private final ToolBar toolBar;
+
+  public ToolBarToolbarContainer(ToolBar toolBar) {
+    this.toolBar = toolBar;
+  }
+
+  @Override
+  public Control getControl() {
+    return toolBar;
+  }
+
+  @Override
+  public void addItem(GuiToolbarItem item, IToolbarWidgetRegistrar registrar) {
+    registrar.addItem(item, toolBar);
+  }
+}
diff --git a/rcp/src/main/java/org/apache/hop/ui/hopgui/ToolbarFacadeImpl.java 
b/rcp/src/main/java/org/apache/hop/ui/hopgui/ToolbarFacadeImpl.java
new file mode 100644
index 0000000000..968810e219
--- /dev/null
+++ b/rcp/src/main/java/org/apache/hop/ui/hopgui/ToolbarFacadeImpl.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+import org.apache.hop.ui.core.gui.IToolbarContainer;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.ToolBar;
+
+/** Desktop (RCP) implementation: returns a container wrapping an SWT ToolBar. 
*/
+public class ToolbarFacadeImpl extends ToolbarFacade {
+
+  @Override
+  protected IToolbarContainer createToolbarContainerInternal(Composite parent, 
int style) {
+    return new ToolBarToolbarContainer(new ToolBar(parent, style));
+  }
+}
diff --git 
a/ui/src/main/java/org/apache/hop/ui/core/database/dialog/DatabaseExplorerDialog.java
 
b/ui/src/main/java/org/apache/hop/ui/core/database/dialog/DatabaseExplorerDialog.java
index c7c4193a0f..7e80dba221 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/core/database/dialog/DatabaseExplorerDialog.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/core/database/dialog/DatabaseExplorerDialog.java
@@ -49,8 +49,10 @@ import org.apache.hop.ui.core.dialog.PreviewRowsDialog;
 import org.apache.hop.ui.core.dialog.TransformFieldsDialog;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.gui.WindowProperty;
 import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionAdapter;
@@ -60,13 +62,13 @@ import org.eclipse.swt.layout.FormData;
 import org.eclipse.swt.layout.FormLayout;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Dialog;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.MenuItem;
 import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.ToolBar;
 import org.eclipse.swt.widgets.Tree;
 import org.eclipse.swt.widgets.TreeItem;
 
@@ -140,7 +142,7 @@ public class DatabaseExplorerDialog extends Dialog {
   private String activeSchemaTable;
   private Button bTruncate;
 
-  private ToolBar toolBar;
+  private Control toolBar;
 
   public DatabaseExplorerDialog(
       Shell parent,
@@ -226,10 +228,12 @@ public class DatabaseExplorerDialog extends Dialog {
 
     // Add a toolbar
     //
-    toolBar = new ToolBar(shell, SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(shell, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    toolBar = toolBarContainer.getControl();
     GuiToolbarWidgets toolBarWidgets = new GuiToolbarWidgets();
     toolBarWidgets.registerGuiPluginObject(this);
-    toolBarWidgets.createToolbarWidgets(toolBar, GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
     FormData layoutData = new FormData();
     layoutData.top = new FormAttachment(0, 0);
     layoutData.left = new FormAttachment(0, 0);
diff --git a/ui/src/main/java/org/apache/hop/ui/core/dialog/ContextDialog.java 
b/ui/src/main/java/org/apache/hop/ui/core/dialog/ContextDialog.java
index aec107273a..8911f75ac5 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/dialog/ContextDialog.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/dialog/ContextDialog.java
@@ -43,8 +43,10 @@ import org.apache.hop.ui.core.PropsUi;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
 import org.apache.hop.ui.core.gui.HopNamespace;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.gui.WindowProperty;
 import org.apache.hop.ui.core.widget.OsHelper;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
 import org.apache.hop.ui.util.EnvironmentUtils;
 import org.eclipse.swt.SWT;
@@ -61,6 +63,7 @@ import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Canvas;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Dialog;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Event;
@@ -69,7 +72,6 @@ import org.eclipse.swt.widgets.Monitor;
 import org.eclipse.swt.widgets.ScrollBar;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.Text;
-import org.eclipse.swt.widgets.ToolBar;
 import org.eclipse.swt.widgets.ToolItem;
 
 @GuiPlugin(description = "This dialog presents you all the actions you can 
take in a given context")
@@ -401,10 +403,12 @@ public class ContextDialog extends Dialog {
 
     // Create a toolbar at the right of the search bar...
     //
-    ToolBar toolBar = new ToolBar(searchComposite, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(searchComposite, SWT.WRAP | 
SWT.LEFT | SWT.HORIZONTAL);
+    Control toolBar = toolBarContainer.getControl();
     toolBarWidgets = new GuiToolbarWidgets();
     toolBarWidgets.registerGuiPluginObject(this);
-    toolBarWidgets.createToolbarWidgets(toolBar, GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
     toolBar.pack();
     PropsUi.setLook(toolBar, Props.WIDGET_STYLE_TOOLBAR);
 
diff --git a/ui/src/main/java/org/apache/hop/ui/core/gui/GuiToolbarWidgets.java 
b/ui/src/main/java/org/apache/hop/ui/core/gui/GuiToolbarWidgets.java
index 12336abb61..587978fce6 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/gui/GuiToolbarWidgets.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/gui/GuiToolbarWidgets.java
@@ -40,25 +40,32 @@ import org.apache.hop.ui.core.PropsUi;
 import org.apache.hop.ui.core.widget.svg.SvgLabelFacade;
 import org.apache.hop.ui.core.widget.svg.SvgLabelListener;
 import org.apache.hop.ui.hopgui.TextSizeUtilFacade;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.file.IHopFileType;
 import org.apache.hop.ui.util.EnvironmentUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
 import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowData;
 import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Canvas;
 import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.ToolBar;
 import org.eclipse.swt.widgets.ToolItem;
 
 /** This class contains the widgets for the GUI elements of a GUI Plugin */
-public class GuiToolbarWidgets extends BaseGuiWidgets {
+public class GuiToolbarWidgets extends BaseGuiWidgets implements 
IToolbarWidgetRegistrar {
 
   public static final String CONST_TOOLBAR_ITEM_WITH_ID = "toolbar item with 
id '";
 
@@ -78,15 +85,26 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
     removeToolItems = new ArrayList<>();
   }
 
-  public void createToolbarWidgets(Composite parent, String root, List<String> 
diabledToolItems) {
-    this.removeToolItems = diabledToolItems;
-    createToolbarWidgets(parent, root);
+  /**
+   * Create a toolbar parent control. Delegates to {@link ToolbarFacade}; on 
desktop returns a
+   * ToolBar, on Hop Web (RAP) returns a Composite with RowLayout (wrap) so 
items wrap. Prefer
+   * {@link ToolbarFacade#createToolbarContainer(Composite, int)} with {@link
+   * #createToolbarWidgets(IToolbarContainer, String)} for a single code path.
+   *
+   * @param parent the parent composite
+   * @param style SWT style (e.g. SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL)
+   * @return the control to use for layout (container.getControl())
+   */
+  public static Control createToolbarParent(Composite parent, int style) {
+    return ToolbarFacade.createToolbar(parent, style);
   }
 
-  public void createToolbarWidgets(Composite parent, String root) {
-
-    // Find the GUI Elements for the given toolbar root...
-    //
+  /**
+   * Single-path toolbar creation using a container (from {@link
+   * ToolbarFacade#createToolbarContainer}). No branching on environment; the 
container
+   * implementation handles ToolBar vs web Composite.
+   */
+  public void createToolbarWidgets(IToolbarContainer container, String root) {
     List<GuiToolbarItem> toolbarItems = 
GuiRegistry.getInstance().findGuiToolbarItems(root);
     if (toolbarItems.isEmpty()) {
       LogChannel.UI.logError("Create widgets: no GUI toolbar items found for 
root: " + root);
@@ -95,23 +113,43 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
 
     Collections.sort(toolbarItems);
 
-    // Loop over the toolbar items, create and remember the widgets...
-    //
     for (GuiToolbarItem toolbarItem : toolbarItems) {
       boolean add = lookupToolbarItemFilter(toolbarItem, root);
       if (add && !removeToolItems.contains(toolbarItem.getId())) {
-        addToolbarWidgets(parent, toolbarItem);
+        guiToolBarMap.put(toolbarItem.getId(), toolbarItem);
+        container.addItem(toolbarItem, this);
       }
     }
 
-    // Force re-layout
-    //
-    parent.layout(true, true);
-    parent.pack();
+    Control control = container.getControl();
+    if (control instanceof Composite composite) {
+      composite.layout(true, true);
+    }
+    control.pack();
+    addDeRegisterGuiPluginObjectListener(control);
+  }
 
-    // Clean up when the parent is disposed
-    //
-    addDeRegisterGuiPluginObjectListener(parent);
+  /**
+   * Same as {@link #createToolbarWidgets(IToolbarContainer, String)} but 
excludes the given item
+   * ids from the toolbar.
+   */
+  public void createToolbarWidgets(
+      IToolbarContainer container, String root, List<String> 
disabledToolItems) {
+    this.removeToolItems = disabledToolItems != null ? disabledToolItems : new 
ArrayList<>();
+    createToolbarWidgets(container, root);
+  }
+
+  @Override
+  public void addItem(GuiToolbarItem item, Composite parent) {
+    if (item.isIgnored()) {
+      return;
+    }
+    // Switch between Hop GUI and Hop Web toolbars
+    if (parent instanceof ToolBar toolBar) {
+      addToolbarWidgetsToToolBar(toolBar, item);
+    } else {
+      addToolbarWidgetsToWebComposite(parent, item);
+    }
   }
 
   private boolean lookupToolbarItemFilter(GuiToolbarItem toolbarItem, String 
root) {
@@ -147,35 +185,18 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
     return show;
   }
 
-  private void addToolbarWidgets(Composite parent, GuiToolbarItem toolbarItem) 
{
-    if (toolbarItem.isIgnored()) {
-      return;
-    }
-
-    // We might need it later...
-    //
-    guiToolBarMap.put(toolbarItem.getId(), toolbarItem);
-
-    if (!(parent instanceof ToolBar toolBar)) {
-      throw new RuntimeException(
-          "We can only add toolbar items to a toolbar, not class " + 
parent.getClass().getName());
-    }
-
-    // We want to add a separator if the annotation asked for it
-    // We also want to add a separator in case the toolbar element type isn't 
a button
-    //
+  /** ToolBar (desktop) path: add one item to an SWT ToolBar. */
+  private void addToolbarWidgetsToToolBar(ToolBar toolBar, GuiToolbarItem 
toolbarItem) {
     if (toolbarItem.isAddingSeparator()) {
       new ToolItem(toolBar, SWT.SEPARATOR);
     }
 
-    // Add a label in front of the item
-    //
     if (toolbarItem.getType() != GuiToolbarElementType.LABEL
         && toolbarItem.getType() != GuiToolbarElementType.CHECKBOX
         && StringUtils.isNotEmpty(toolbarItem.getLabel())) {
       ToolItem labelSeparator = new ToolItem(toolBar, SWT.SEPARATOR);
       CLabel label =
-          new CLabel(parent, SWT.CENTER | (toolbarItem.isAlignRight() ? 
SWT.RIGHT : SWT.LEFT));
+          new CLabel(toolBar, SWT.CENTER | (toolbarItem.isAlignRight() ? 
SWT.RIGHT : SWT.LEFT));
       label.setText(Const.NVL(toolbarItem.getLabel(), ""));
       label.setToolTipText(Const.NVL(toolbarItem.getToolTip(), ""));
       PropsUi.setLook(label, Props.WIDGET_STYLE_TOOLBAR);
@@ -184,13 +205,10 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
       labelSeparator.setControl(label);
     }
 
-    // Add the GUI element
-    //
     switch (toolbarItem.getType()) {
       case LABEL:
         addToolbarLabel(toolbarItem, toolBar);
         break;
-
       case BUTTON:
         if (EnvironmentUtils.getInstance().isWeb()) {
           addWebToolbarButton(toolbarItem, toolBar);
@@ -198,20 +216,207 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
           addToolbarButton(toolbarItem, toolBar);
         }
         break;
-
       case COMBO:
         addToolbarCombo(toolbarItem, toolBar);
         break;
-
       case CHECKBOX:
         addToolbarCheckbox(toolbarItem, toolBar);
         break;
+      default:
+        break;
+    }
+  }
+
+  /** Add toolbar items to a web Composite (Hop Web); no ToolItems, controls 
wrap by RowLayout. */
+  private void addToolbarWidgetsToWebComposite(Composite parent, 
GuiToolbarItem toolbarItem) {
+    if (toolbarItem.isAddingSeparator()) {
+      addWebToolbarSeparator(parent);
+    }
 
+    if (toolbarItem.getType() != GuiToolbarElementType.LABEL
+        && toolbarItem.getType() != GuiToolbarElementType.CHECKBOX
+        && StringUtils.isNotEmpty(toolbarItem.getLabel())) {
+      CLabel label =
+          new CLabel(parent, SWT.CENTER | (toolbarItem.isAlignRight() ? 
SWT.RIGHT : SWT.LEFT));
+      label.setText(Const.NVL(toolbarItem.getLabel(), ""));
+      label.setToolTipText(Const.NVL(toolbarItem.getToolTip(), ""));
+      PropsUi.setLook(label, Props.WIDGET_STYLE_TOOLBAR);
+      label.pack();
+    }
+
+    switch (toolbarItem.getType()) {
+      case LABEL:
+        addWebToolbarLabel(toolbarItem, parent);
+        break;
+      case BUTTON:
+        addWebToolbarButtonToComposite(toolbarItem, parent);
+        break;
+      case COMBO:
+        addWebToolbarCombo(toolbarItem, parent);
+        break;
+      case CHECKBOX:
+        addWebToolbarCheckbox(toolbarItem, parent);
+        break;
       default:
         break;
     }
   }
 
+  /**
+   * Vertical separator with groove look for Hop Web toolbar (matches desktop 
ToolItem SEPARATOR).
+   * Uses toolbar background so no visible strip; draws groove full height 
with no top/bottom
+   * margin.
+   */
+  private void addWebToolbarSeparator(Composite parent) {
+    int width = 6;
+    int height = (int) (ConstUi.SMALL_ICON_SIZE * 
PropsUi.getNativeZoomFactor()) + 6;
+    Canvas canvas = new Canvas(parent, SWT.NONE);
+    canvas.setLayoutData(new RowData(width, height));
+    canvas.setBackground(parent.getBackground());
+    PropsUi.setLook(canvas, Props.WIDGET_STYLE_TOOLBAR);
+    canvas.addPaintListener(
+        new PaintListener() {
+          @Override
+          public void paintControl(PaintEvent e) {
+            GC gc = e.gc;
+            Display display = e.display;
+            Color highlight = 
display.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
+            Color shadow = 
display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+            int w = e.width;
+            int h = e.height;
+            int x = w / 2 - 1;
+            gc.setForeground(highlight);
+            gc.drawLine(x, 0, x, h - 1);
+            gc.setForeground(shadow);
+            gc.drawLine(x + 1, 0, x + 1, h - 1);
+          }
+        });
+  }
+
+  private void addWebToolbarLabel(GuiToolbarItem toolbarItem, Composite 
parent) {
+    CLabel label =
+        new CLabel(parent, SWT.CENTER | (toolbarItem.isAlignRight() ? 
SWT.RIGHT : SWT.LEFT));
+    label.setText(Const.NVL(toolbarItem.getLabel(), ""));
+    label.setToolTipText(Const.NVL(toolbarItem.getToolTip(), ""));
+    PropsUi.setLook(label, Props.WIDGET_STYLE_TOOLBAR);
+    label.pack();
+    widgetsMap.put(toolbarItem.getId(), label);
+    Listener listener = getListener(toolbarItem);
+    label.addListener(SWT.MouseUp, listener);
+  }
+
+  private void addWebToolbarCombo(GuiToolbarItem toolbarItem, Composite 
parent) {
+    Combo combo =
+        new Combo(
+            parent,
+            SWT.SINGLE
+                | SWT.CENTER
+                | (toolbarItem.isAlignRight() ? SWT.RIGHT : SWT.LEFT)
+                | (toolbarItem.isReadOnly() ? SWT.READ_ONLY : SWT.NONE));
+    combo.setToolTipText(Const.NVL(toolbarItem.getToolTip(), ""));
+    combo.setItems(getComboItems(toolbarItem));
+    PropsUi.setLook(combo, Props.WIDGET_STYLE_TOOLBAR);
+    combo.pack();
+    int width = calculateComboWidth(combo) + toolbarItem.getExtraWidth();
+    combo.setLayoutData(new RowData(width, SWT.DEFAULT));
+    Listener listener = getListener(toolbarItem);
+    combo.addListener(SWT.Selection, listener);
+    combo.addListener(SWT.DefaultSelection, listener);
+    widgetsMap.put(toolbarItem.getId(), combo);
+  }
+
+  private void addWebToolbarCheckbox(GuiToolbarItem toolbarItem, Composite 
parent) {
+    Button checkbox =
+        new Button(parent, SWT.CHECK | (toolbarItem.isAlignRight() ? SWT.RIGHT 
: SWT.LEFT));
+    checkbox.setToolTipText(Const.NVL(toolbarItem.getToolTip(), ""));
+    checkbox.setText(Const.NVL(toolbarItem.getLabel(), ""));
+    PropsUi.setLook(checkbox, Props.WIDGET_STYLE_TOOLBAR);
+    checkbox.pack();
+    checkbox.setLayoutData(
+        new RowData(checkbox.getSize().x + toolbarItem.getExtraWidth(), 
SWT.DEFAULT));
+    Listener listener = getListener(toolbarItem);
+    checkbox.addListener(SWT.Selection, listener);
+    widgetsMap.put(toolbarItem.getId(), checkbox);
+  }
+
+  private void addWebToolbarButtonToComposite(GuiToolbarItem toolbarItem, 
Composite parent) {
+    Composite composite = new Composite(parent, SWT.NONE);
+    GridLayout layout = new GridLayout(2, false);
+    layout.marginWidth = 0;
+    layout.marginHeight = 0;
+    layout.horizontalSpacing = 4;
+    layout.verticalSpacing = 0;
+    composite.setLayout(layout);
+    PropsUi.setLook(composite, Props.WIDGET_STYLE_TOOLBAR);
+
+    Label imageLabel = new Label(composite, SWT.NONE);
+    if (StringUtils.isNotEmpty(toolbarItem.getToolTip())) {
+      imageLabel.setToolTipText(toolbarItem.getToolTip());
+      composite.setToolTipText(toolbarItem.getToolTip());
+    }
+    Listener listener = SvgLabelListener.getInstance();
+    Listener toolbarListener = getListener(toolbarItem);
+
+    imageLabel.addListener(SWT.MouseDown, listener);
+    imageLabel.addListener(SWT.Hide, listener);
+    imageLabel.addListener(SWT.Show, listener);
+    imageLabel.addListener(SWT.MouseEnter, listener);
+    imageLabel.addListener(SWT.MouseExit, listener);
+    imageLabel.addListener(SWT.MouseUp, toolbarListener);
+    composite.addListener(SWT.MouseUp, toolbarListener);
+
+    int size =
+        (int)
+            (ConstUi.SMALL_ICON_SIZE * PropsUi.getNativeZoomFactor() + 
toolbarItem.getExtraWidth());
+
+    String imageFilename = findImageFilename(toolbarItem);
+    String uniqueId = instanceId + "-" + toolbarItem.getId();
+    SvgLabelFacade.setData(uniqueId, imageLabel, imageFilename, size);
+    composite.setData("iconSize", size);
+    composite.setData("uniqueId", uniqueId);
+    // Copy props to composite so client script (svg-label.js) has props.id 
when event.widget is the
+    // composite
+    composite.setData("props", imageLabel.getData("props"));
+
+    GridData imageData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
+    imageData.widthHint = size;
+    imageData.heightHint = size;
+    imageLabel.setLayoutData(imageData);
+
+    Label textLabel = new Label(composite, SWT.NONE);
+    textLabel.setText("");
+    PropsUi.setLook(textLabel, Props.WIDGET_STYLE_TOOLBAR);
+    if (StringUtils.isNotEmpty(toolbarItem.getToolTip())) {
+      textLabel.setToolTipText(toolbarItem.getToolTip());
+    }
+    textLabel.addListener(SWT.MouseUp, toolbarListener);
+    GridData textData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
+    textLabel.setLayoutData(textData);
+    textLabel.setVisible(false);
+
+    composite.pack();
+    composite.setLayoutData(new RowData(composite.getSize().x, 
composite.getSize().y));
+
+    widgetsMap.put(toolbarItem.getId(), composite);
+    textLabelMap.put(toolbarItem.getId(), textLabel);
+
+    setToolItemKeyboardShortcutForComposite(composite, toolbarItem);
+  }
+
+  private void setToolItemKeyboardShortcutForComposite(
+      Composite composite, GuiToolbarItem guiToolbarItem) {
+    KeyboardShortcut shortcut =
+        GuiRegistry.getInstance()
+            .findKeyboardShortcut(
+                guiToolbarItem.getListenerClass(),
+                guiToolbarItem.getListenerMethod(),
+                Const.isOSX());
+    if (shortcut != null) {
+      String tip = Const.NVL(guiToolbarItem.getToolTip(), "");
+      composite.setToolTipText(tip + " (" + shortcut + ')');
+    }
+  }
+
   private void addToolbarLabel(GuiToolbarItem toolbarItem, ToolBar toolBar) {
     ToolItem labelSeparator = new ToolItem(toolBar, SWT.SEPARATOR);
     CLabel label =
@@ -284,6 +489,7 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
     Listener listener = getListener(toolbarItem);
     item.addListener(SWT.Selection, listener);
     toolItemMap.put(toolbarItem.getId(), item);
+    widgetsMap.put(toolbarItem.getId(), item.getParent());
     setToolItemKeyboardShortcut(item, toolbarItem);
   }
 
@@ -347,11 +553,12 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
     imageLabel.addListener(SWT.MouseEnter, listener);
     imageLabel.addListener(SWT.MouseExit, listener);
 
-    // Also add the toolbar click handler to the image label
-    imageLabel.addListener(SWT.MouseDown, toolbarListener);
+    // Also add the toolbar click handler to the image label (MouseUp to match 
ToolItem.Selection
+    // and avoid menu dismiss on RAP)
+    imageLabel.addListener(SWT.MouseUp, toolbarListener);
 
     // Make the entire composite clickable (image + text)
-    composite.addListener(SWT.MouseDown, toolbarListener);
+    composite.addListener(SWT.MouseUp, toolbarListener);
 
     // Take into account zooming and the extra room for widget decorations
     //
@@ -368,6 +575,9 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
     // selected)
     composite.setData("iconSize", size);
     composite.setData("uniqueId", uniqueId);
+    // Copy props to composite so client script (svg-label.js) has props.id 
when event.widget is the
+    // composite
+    composite.setData("props", imageLabel.getData("props"));
 
     GridData imageData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
     imageData.widthHint = size;
@@ -382,7 +592,7 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
       textLabel.setToolTipText(toolbarItem.getToolTip());
     }
     // Make text label part of the clickable button
-    textLabel.addListener(SWT.MouseDown, toolbarListener);
+    textLabel.addListener(SWT.MouseUp, toolbarListener);
     GridData textData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
     textLabel.setLayoutData(textData);
     textLabel.setVisible(false); // Hidden until text is set
@@ -441,26 +651,37 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
   }
 
   public void enableToolbarItem(String id, boolean enabled) {
+    Control control = widgetsMap.get(id);
     ToolItem toolItem = toolItemMap.get(id);
-    if (toolItem == null || toolItem.isDisposed()) {
+
+    // Web composite mode (Hop Web): no ToolItem, enable/disable the control 
only
+    if (toolItem == null) {
+      if (control != null && !control.isDisposed()) {
+        if (control instanceof Composite composite) {
+          Control[] children = composite.getChildren();
+          if (children.length > 0 && children[0] instanceof Label imageLabel) {
+            String uniqueId = instanceId + "-" + id;
+            SvgLabelFacade.enable(null, uniqueId, imageLabel, enabled);
+          }
+          composite.setEnabled(enabled);
+        } else {
+          control.setEnabled(enabled);
+        }
+      }
+      return;
+    }
+    if (toolItem.isDisposed()) {
       return;
     }
     if (EnvironmentUtils.getInstance().isWeb()) {
-      // In web/RWT, the widget is a Composite containing the image label
-      Control control = widgetsMap.get(id);
       if (control instanceof Composite composite) {
-        // Find the image label (first child)
         Control[] children = composite.getChildren();
         if (children.length > 0 && children[0] instanceof Label imageLabel) {
-          // Use the unique DOM element ID (instance ID + toolbar item ID)
           String uniqueId = instanceId + "-" + id;
           SvgLabelFacade.enable(toolItem, uniqueId, imageLabel, enabled);
         }
-        // So that disabled buttons do not receive clicks in RWT 
(ToolItem.setEnabled does not
-        // always prevent the control from receiving events)
         composite.setEnabled(enabled);
       }
-      // Also update the ToolItem state for consistency
       if (enabled != toolItem.isEnabled()) {
         toolItem.setEnabled(enabled);
       }
@@ -497,28 +718,28 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
   public ToolItem enableToolbarItem(
       IHopFileType fileType, String id, String permission, boolean active) {
     ToolItem item = findToolItem(id);
-    if (item == null || item.isDisposed()) {
+    boolean hasCapability = fileType.hasCapability(permission);
+    boolean enable = hasCapability && active;
+
+    if (item == null) {
+      // Web composite mode: no ToolItem, enable/disable the control only
+      enableToolbarItem(id, enable);
       return null;
     }
-    boolean hasCapability = fileType.hasCapability(permission);
-    boolean enabled = hasCapability && active;
-    if (enabled != item.isEnabled()) {
-      boolean enable = hasCapability && active;
+    if (item.isDisposed()) {
+      return null;
+    }
+    if (enable != item.isEnabled()) {
       if (EnvironmentUtils.getInstance().isWeb()) {
-        // In web/RWT, the widget is a Composite containing the image label
         Control control = widgetsMap.get(id);
         if (control instanceof Composite composite) {
-          // Find the image label (first child)
           Control[] children = composite.getChildren();
           if (children.length > 0 && children[0] instanceof Label imageLabel) {
-            // Use the unique DOM element ID (instance ID + toolbar item ID)
             String uniqueId = instanceId + "-" + id;
             SvgLabelFacade.enable(null, uniqueId, imageLabel, enable);
           }
-          // So that disabled buttons do not receive clicks in RWT
           composite.setEnabled(enable);
         }
-        // Update ToolItem state so future checks work correctly
         item.setEnabled(enable);
       } else {
         item.setEnabled(enable);
@@ -531,6 +752,19 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
     return toolItemMap.get(id);
   }
 
+  /**
+   * Return the Control to use for positioning a popup menu for the given 
toolbar item. A ToolItem
+   * is not a Control, and getControl() is only set for SEPARATOR items (the 
wrapped label/widget).
+   * For BUTTON items we store the composite (image+text) in widgetsMap; use 
that for menu
+   * positioning.
+   *
+   * @param id toolbar item id (e.g. {@code ID_TOOLBAR_ITEM_PROJECT})
+   * @return the Control to use for getBounds() / toDisplay(), or null if not 
found
+   */
+  public Control getControlForMenu(String id) {
+    return widgetsMap.get(id);
+  }
+
   /**
    * Set the image of a toolbar item by path. Use this when toggling between 
two icons (e.g. show
    * only selected / show all). In desktop SWT this sets the ToolItem's image; 
in web RWT this
@@ -543,27 +777,45 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
     if (StringUtils.isEmpty(imagePath)) {
       return;
     }
+    Control control = widgetsMap.get(id);
     ToolItem toolItem = toolItemMap.get(id);
+
+    if (EnvironmentUtils.getInstance().isWeb()
+        && control instanceof Composite composite
+        && !composite.isDisposed()) {
+      Control[] children = composite.getChildren();
+      if (children.length > 0 && children[0] instanceof Label imageLabel) {
+        String uniqueId = (String) composite.getData("uniqueId");
+        if (uniqueId != null) {
+          SvgLabelFacade.updateImageSource(uniqueId, imageLabel, imagePath);
+        }
+      }
+      return;
+    }
     if (toolItem == null || toolItem.isDisposed()) {
       return;
     }
-    if (EnvironmentUtils.getInstance().isWeb()) {
-      Control control = widgetsMap.get(id);
-      if (control instanceof Composite composite && !composite.isDisposed()) {
-        Control[] children = composite.getChildren();
-        if (children.length > 0 && children[0] instanceof Label imageLabel) {
-          String uniqueId = (String) composite.getData("uniqueId");
-          if (uniqueId != null) {
-            // Update img src via JavaScript so the icon updates in RWT 
(setText may not re-render)
-            SvgLabelFacade.updateImageSource(uniqueId, imageLabel, imagePath);
-          }
-        }
-      }
-    } else {
-      Image image = GuiResource.getInstance().getImage(imagePath);
-      if (image != null) {
-        toolItem.setImage(image);
-      }
+    Image image = GuiResource.getInstance().getImage(imagePath);
+    if (image != null) {
+      toolItem.setImage(image);
+    }
+  }
+
+  /**
+   * Set the tooltip on a toolbar item. Works for both ToolBar (desktop) and 
web Composite (Hop
+   * Web).
+   *
+   * @param id the toolbar item id (from @GuiToolbarElement)
+   * @param tooltip the tooltip text
+   */
+  public void setToolbarItemToolTip(String id, String tooltip) {
+    Control control = widgetsMap.get(id);
+    ToolItem toolItem = toolItemMap.get(id);
+    if (control != null && !control.isDisposed()) {
+      control.setToolTipText(Const.NVL(tooltip, ""));
+    }
+    if (toolItem != null && !toolItem.isDisposed()) {
+      toolItem.setToolTipText(Const.NVL(tooltip, ""));
     }
   }
 
@@ -575,36 +827,34 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
    * @param text The text to set
    */
   public void setToolbarItemText(String id, String text) {
+    Label textLabel = textLabelMap.get(id);
+    Composite composite = widgetsMap.get(id) instanceof Composite c ? c : null;
     ToolItem toolItem = toolItemMap.get(id);
-    if (toolItem == null || toolItem.isDisposed()) {
-      return;
-    }
 
-    if (EnvironmentUtils.getInstance().isWeb()) {
-      // In web/RWT, update the separate text label
-      Label textLabel = textLabelMap.get(id);
+    if (EnvironmentUtils.getInstance().isWeb() && (textLabel != null || 
composite != null)) {
       if (textLabel != null && !textLabel.isDisposed()) {
         String textToSet = Const.NVL(text, "");
         textLabel.setText(textToSet);
         textLabel.setVisible(!Utils.isEmpty(textToSet));
-
-        // Update the composite width to accommodate the text
-        Composite composite = (Composite) widgetsMap.get(id);
-        if (composite != null && !composite.isDisposed()) {
-          composite.pack();
-          // Add extra margin to the right for spacing between toolbar items
-          int extraMargin = !Utils.isEmpty(textToSet) ? 10 : 0;
+      }
+      if (composite != null && !composite.isDisposed()) {
+        composite.pack();
+        int extraMargin = !Utils.isEmpty(Const.NVL(text, "")) ? 10 : 0;
+        if (toolItem != null && !toolItem.isDisposed()) {
           toolItem.setWidth(composite.getSize().x + extraMargin);
-
-          // Force layout update
           ToolBar toolbar = toolItem.getParent();
           if (toolbar != null && !toolbar.isDisposed()) {
             toolbar.layout(true, true);
           }
+        } else {
+          composite.setLayoutData(
+              new RowData(composite.getSize().x + extraMargin, 
composite.getSize().y));
+          composite.getParent().layout(true, true);
         }
       }
-    } else {
-      // In SWT, set text directly on the ToolItem
+      return;
+    }
+    if (toolItem != null && !toolItem.isDisposed()) {
       toolItem.setText(Const.NVL(text, ""));
     }
   }
@@ -617,22 +867,15 @@ public class GuiToolbarWidgets extends BaseGuiWidgets {
    * @return The text on the toolbar item, or empty string if not found
    */
   public String getToolbarItemText(String id) {
-    ToolItem toolItem = toolItemMap.get(id);
-    if (toolItem == null || toolItem.isDisposed()) {
-      return "";
+    Label textLabel = textLabelMap.get(id);
+    if (textLabel != null && !textLabel.isDisposed()) {
+      return Const.NVL(textLabel.getText(), "");
     }
-
-    if (EnvironmentUtils.getInstance().isWeb()) {
-      // In web/RWT, get text from the separate text label
-      Label textLabel = textLabelMap.get(id);
-      if (textLabel != null && !textLabel.isDisposed()) {
-        return Const.NVL(textLabel.getText(), "");
-      }
-      return "";
-    } else {
-      // In SWT, get text directly from the ToolItem
+    ToolItem toolItem = toolItemMap.get(id);
+    if (toolItem != null && !toolItem.isDisposed()) {
       return Const.NVL(toolItem.getText(), "");
     }
+    return "";
   }
 
   public void refreshComboItemList(String id) {
diff --git a/ui/src/main/java/org/apache/hop/ui/core/gui/IToolbarContainer.java 
b/ui/src/main/java/org/apache/hop/ui/core/gui/IToolbarContainer.java
new file mode 100644
index 0000000000..ca74718179
--- /dev/null
+++ b/ui/src/main/java/org/apache/hop/ui/core/gui/IToolbarContainer.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.core.gui;
+
+import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarItem;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Abstraction over a toolbar container: either an SWT ToolBar (desktop) or a 
Composite with
+ * RowLayout (Hop Web). Allows adding toolbar items in a single code path; the 
implementation
+ * handles the difference.
+ */
+public interface IToolbarContainer {
+
+  /** The control to use for layout (setLayoutData, etc.). */
+  Control getControl();
+
+  /**
+   * Add one toolbar item (separator, optional label, and the element). The 
implementation creates
+   * the appropriate widgets and registers them via the registrar.
+   */
+  void addItem(GuiToolbarItem item, IToolbarWidgetRegistrar registrar);
+}
diff --git 
a/ui/src/main/java/org/apache/hop/ui/core/gui/IToolbarWidgetRegistrar.java 
b/ui/src/main/java/org/apache/hop/ui/core/gui/IToolbarWidgetRegistrar.java
new file mode 100644
index 0000000000..28521c0c19
--- /dev/null
+++ b/ui/src/main/java/org/apache/hop/ui/core/gui/IToolbarWidgetRegistrar.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.core.gui;
+
+import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarItem;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * Callback used by {@link IToolbarContainer} to add one toolbar item. The 
container passes its
+ * control (a ToolBar or a Composite); the registrar branches on type so 
widget creation stays in
+ * one place (e.g. {@link GuiToolbarWidgets}).
+ */
+public interface IToolbarWidgetRegistrar {
+
+  /**
+   * Add one toolbar item. {@code parent} is either an SWT ToolBar (desktop) 
or a Composite with
+   * RowLayout (Hop Web); ToolBar extends Composite so both use the same 
callback.
+   */
+  void addItem(GuiToolbarItem item, Composite parent);
+}
diff --git a/ui/src/main/java/org/apache/hop/ui/core/vfs/HopVfsFileDialog.java 
b/ui/src/main/java/org/apache/hop/ui/core/vfs/HopVfsFileDialog.java
index c1ddb372ef..3d941ed56e 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/vfs/HopVfsFileDialog.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/vfs/HopVfsFileDialog.java
@@ -59,10 +59,12 @@ import org.apache.hop.ui.core.dialog.MessageBox;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
 import org.apache.hop.ui.core.gui.HopNamespace;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.gui.WindowProperty;
 import org.apache.hop.ui.core.widget.TextVar;
 import org.apache.hop.ui.core.widget.TreeUtil;
 import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.file.HopFileTypePluginType;
 import org.apache.hop.ui.hopgui.file.HopFileTypeRegistry;
 import org.apache.hop.ui.hopgui.file.IHopFileType;
@@ -92,13 +94,13 @@ import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.List;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.MenuItem;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.Text;
-import org.eclipse.swt.widgets.ToolBar;
 import org.eclipse.swt.widgets.ToolItem;
 import org.eclipse.swt.widgets.Tree;
 import org.eclipse.swt.widgets.TreeColumn;
@@ -321,13 +323,16 @@ public class HopVfsFileDialog implements IFileDialog, 
IDirectoryDialog {
     navigateComposite.setLayoutData(fdNavigationForm);
 
     // A toolbar above the browser, below the filename
-    ToolBar navigateToolBar = new ToolBar(navigateComposite, SWT.LEFT | 
SWT.HORIZONTAL);
+    IToolbarContainer navigateToolBarContainer =
+        ToolbarFacade.createToolbarContainer(navigateComposite, SWT.LEFT | 
SWT.HORIZONTAL);
+    Control navigateToolBar = navigateToolBarContainer.getControl();
     navigateToolBar.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, 
true));
     PropsUi.setLook(navigateToolBar, Props.WIDGET_STYLE_TOOLBAR);
 
     navigateToolbarWidgets = new GuiToolbarWidgets();
     navigateToolbarWidgets.registerGuiPluginObject(this);
-    navigateToolbarWidgets.createToolbarWidgets(navigateToolBar, 
NAVIGATE_TOOLBAR_PARENT_ID);
+    navigateToolbarWidgets.createToolbarWidgets(
+        navigateToolBarContainer, NAVIGATE_TOOLBAR_PARENT_ID);
     navigateToolBar.pack();
 
     wFilename = new TextVar(variables, navigateComposite, SWT.SINGLE | 
SWT.LEFT | SWT.BORDER);
@@ -362,8 +367,10 @@ public class HopVfsFileDialog implements IFileDialog, 
IDirectoryDialog {
     bookmarksComposite.setLayout(new FormLayout());
 
     // Above the bookmarks a toolbar with add, delete
-    ToolBar bookmarksToolBar =
-        new ToolBar(bookmarksComposite, SWT.WRAP | SWT.SHADOW_IN | SWT.LEFT | 
SWT.HORIZONTAL);
+    IToolbarContainer bookmarksToolBarContainer =
+        ToolbarFacade.createToolbarContainer(
+            bookmarksComposite, SWT.WRAP | SWT.SHADOW_IN | SWT.LEFT | 
SWT.HORIZONTAL);
+    Control bookmarksToolBar = bookmarksToolBarContainer.getControl();
     FormData fdBookmarksToolBar = new FormData();
     fdBookmarksToolBar.left = new FormAttachment(0, 0);
     fdBookmarksToolBar.top = new FormAttachment(0, 0);
@@ -373,7 +380,8 @@ public class HopVfsFileDialog implements IFileDialog, 
IDirectoryDialog {
 
     bookmarksToolbarWidgets = new GuiToolbarWidgets();
     bookmarksToolbarWidgets.registerGuiPluginObject(this);
-    bookmarksToolbarWidgets.createToolbarWidgets(bookmarksToolBar, 
BOOKMARKS_TOOLBAR_PARENT_ID);
+    bookmarksToolbarWidgets.createToolbarWidgets(
+        bookmarksToolBarContainer, BOOKMARKS_TOOLBAR_PARENT_ID);
     bookmarksToolBar.pack();
 
     // Below that we have a list with all the bookmarks in them
@@ -473,7 +481,10 @@ public class HopVfsFileDialog implements IFileDialog, 
IDirectoryDialog {
     browserComposite.setLayoutData(fdTreeComposite);
 
     // A toolbar above the browser, below the filename
-    ToolBar browserToolBar = new ToolBar(browserComposite, SWT.WRAP | SWT.LEFT 
| SWT.HORIZONTAL);
+    IToolbarContainer browserToolBarContainer =
+        ToolbarFacade.createToolbarContainer(
+            browserComposite, SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL);
+    Control browserToolBar = browserToolBarContainer.getControl();
     FormData fdBrowserToolBar = new FormData();
     fdBrowserToolBar.left = new FormAttachment(0, 0);
     fdBrowserToolBar.top = new FormAttachment(0, 0);
@@ -483,7 +494,7 @@ public class HopVfsFileDialog implements IFileDialog, 
IDirectoryDialog {
 
     browserToolbarWidgets = new GuiToolbarWidgets();
     browserToolbarWidgets.registerGuiPluginObject(this);
-    browserToolbarWidgets.createToolbarWidgets(browserToolBar, 
BROWSER_TOOLBAR_PARENT_ID);
+    browserToolbarWidgets.createToolbarWidgets(browserToolBarContainer, 
BROWSER_TOOLBAR_PARENT_ID);
     browserToolBar.pack();
 
     SashForm browseSash = new SashForm(browserComposite, SWT.VERTICAL);
diff --git 
a/ui/src/main/java/org/apache/hop/ui/core/widget/MetaSelectionLine.java 
b/ui/src/main/java/org/apache/hop/ui/core/widget/MetaSelectionLine.java
index d800a903c5..5f81f773d0 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/widget/MetaSelectionLine.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/widget/MetaSelectionLine.java
@@ -35,8 +35,10 @@ import org.apache.hop.metadata.util.HopMetadataUtil;
 import org.apache.hop.ui.core.ConstUi;
 import org.apache.hop.ui.core.PropsUi;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.metadata.MetadataManager;
 import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.perspective.metadata.MetadataPerspective;
 import org.apache.hop.ui.util.EnvironmentUtils;
 import org.apache.hop.ui.util.SwtSvgImageUtil;
@@ -53,7 +55,6 @@ import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.ToolBar;
 
 /**
  * The goal of this composite is to add a line on a dialog which contains: - A 
label (for example:
@@ -79,7 +80,7 @@ public class MetaSelectionLine<T extends IHopMetadata> 
extends Composite {
   private PropsUi props;
   private final Label wLabel;
   private ComboVar wCombo = null;
-  private final ToolBar wToolBar;
+  private final Control wToolBar;
 
   public MetaSelectionLine(
       IVariables variables,
@@ -189,7 +190,9 @@ public class MetaSelectionLine<T extends IHopMetadata> 
extends Composite {
 
     // Toolbar for default actions
     //
-    wToolBar = new ToolBar(this, SWT.FLAT | SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(this, SWT.FLAT | SWT.HORIZONTAL);
+    wToolBar = toolBarContainer.getControl();
     PropsUi.setLook(wToolBar, Props.WIDGET_STYLE_DEFAULT);
     FormData fdToolBar = new FormData();
     fdToolBar.right = new FormAttachment(100, 0);
@@ -200,8 +203,7 @@ public class MetaSelectionLine<T extends IHopMetadata> 
extends Composite {
     //
     GuiToolbarWidgets toolbarWidgets = new GuiToolbarWidgets();
     toolbarWidgets.registerGuiPluginObject(this);
-    // Removed for Windows dark mode
-    toolbarWidgets.createToolbarWidgets(wToolBar, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolbarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
 
     int textFlags = SWT.SINGLE | SWT.LEFT | SWT.BORDER;
     if (flags != SWT.NONE) {
@@ -527,11 +529,11 @@ public class MetaSelectionLine<T extends IHopMetadata> 
extends Composite {
   }
 
   /**
-   * Gets wToolBar
+   * Gets wToolBar (the toolbar control; on desktop a ToolBar, on web a 
Composite with RowLayout).
    *
    * @return value of wToolBar
    */
-  public ToolBar getwToolBar() {
+  public Control getwToolBar() {
     return wToolBar;
   }
 }
diff --git a/ui/src/main/java/org/apache/hop/ui/core/widget/TableView.java 
b/ui/src/main/java/org/apache/hop/ui/core/widget/TableView.java
index cb30d31ae3..052e436992 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/widget/TableView.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/widget/TableView.java
@@ -56,7 +56,9 @@ import org.apache.hop.ui.core.dialog.ErrorDialog;
 import org.apache.hop.ui.core.dialog.MessageBox;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.hopgui.TextSizeUtilFacade;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.util.EnvironmentUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.SWTException;
@@ -98,7 +100,6 @@ import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.swt.widgets.TableItem;
 import org.eclipse.swt.widgets.Text;
-import org.eclipse.swt.widgets.ToolBar;
 
 /** Widget to display or modify data, displayed in a Table format. */
 @GuiPlugin
@@ -159,7 +160,7 @@ public class TableView extends Composite {
   private final TableColumn[] tableColumn;
   private final PropsUi props;
   @Getter private final boolean toolbarEnabled;
-  @Getter @Setter private ToolBar toolbar;
+  @Getter @Setter private Control toolbar;
   @Getter @Setter private GuiToolbarWidgets toolbarWidgets;
   private Control text;
   private Combo combo;
@@ -1440,7 +1441,9 @@ public class TableView extends Composite {
     toolbarWidgets.registerGuiPluginObject(this);
 
     if (toolbarEnabled && props.isShowTableViewToolbar()) {
-      toolbar = new ToolBar(this, SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL);
+      IToolbarContainer toolBarContainer =
+          ToolbarFacade.createToolbarContainer(this, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+      toolbar = toolBarContainer.getControl();
       FormData fdToolBar = new FormData();
       fdToolBar.left = new FormAttachment(0, 0);
       fdToolBar.top = new FormAttachment(0, 0);
@@ -1448,7 +1451,7 @@ public class TableView extends Composite {
       toolbar.setLayoutData(fdToolBar);
       PropsUi.setLook(toolbar, Props.WIDGET_STYLE_TOOLBAR);
 
-      toolbarWidgets.createToolbarWidgets(toolbar, ID_TOOLBAR, 
removeToolItems);
+      toolbarWidgets.createToolbarWidgets(toolBarContainer, ID_TOOLBAR, 
removeToolItems);
       toolbar.pack();
     }
   }
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java 
b/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
index 63c59776bc..1bb4dd60bb 100644
--- a/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/HopGui.java
@@ -92,6 +92,7 @@ import org.apache.hop.ui.core.gui.GuiMenuWidgets;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
 import org.apache.hop.ui.core.gui.HopNamespace;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.gui.WindowProperty;
 import org.apache.hop.ui.core.metadata.MetadataManager;
 import org.apache.hop.ui.core.widget.OsHelper;
@@ -260,10 +261,10 @@ public class HopGui
   private GuiMenuWidgets mainMenuWidgets;
   private Composite mainHopGuiComposite;
 
-  private ToolBar mainToolbar;
+  private Control mainToolbar;
   private GuiToolbarWidgets mainToolbarWidgets;
 
-  private ToolBar statusToolbar;
+  private Control statusToolbar;
   private GuiToolbarWidgets statusToolbarWidgets;
 
   private Composite perspectivesSidebar;
@@ -1243,7 +1244,9 @@ public class HopGui
   }
 
   protected void addMainToolbar() {
-    mainToolbar = new ToolBar(shell, SWT.WRAP | SWT.RIGHT | SWT.HORIZONTAL);
+    IToolbarContainer mainToolbarContainer =
+        ToolbarFacade.createToolbarContainer(shell, SWT.WRAP | SWT.RIGHT | 
SWT.HORIZONTAL);
+    mainToolbar = mainToolbarContainer.getControl();
     FormData fdToolBar = new FormData();
     fdToolBar.left = new FormAttachment(0, 0);
     fdToolBar.top = new FormAttachment(0, 0);
@@ -1253,12 +1256,14 @@ public class HopGui
 
     mainToolbarWidgets = new GuiToolbarWidgets();
     mainToolbarWidgets.registerGuiPluginObject(this);
-    mainToolbarWidgets.createToolbarWidgets(mainToolbar, ID_MAIN_TOOLBAR);
+    mainToolbarWidgets.createToolbarWidgets(mainToolbarContainer, 
ID_MAIN_TOOLBAR);
     mainToolbar.pack();
   }
 
   protected void addStatusToolbar() {
-    statusToolbar = new ToolBar(shell, SWT.WRAP | SWT.RIGHT | SWT.HORIZONTAL);
+    IToolbarContainer statusToolbarContainer =
+        ToolbarFacade.createToolbarContainer(shell, SWT.WRAP | SWT.RIGHT | 
SWT.HORIZONTAL);
+    statusToolbar = statusToolbarContainer.getControl();
     FormData fdToolBar = new FormData();
     fdToolBar.left = new FormAttachment(0, 10);
     fdToolBar.right = new FormAttachment(100, 0);
@@ -1268,7 +1273,7 @@ public class HopGui
 
     statusToolbarWidgets = new GuiToolbarWidgets();
     statusToolbarWidgets.registerGuiPluginObject(this);
-    statusToolbarWidgets.createToolbarWidgets(statusToolbar, 
ID_STATUS_TOOLBAR);
+    statusToolbarWidgets.createToolbarWidgets(statusToolbarContainer, 
ID_STATUS_TOOLBAR);
     statusToolbar.pack();
   }
 
diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/ToolbarFacade.java 
b/ui/src/main/java/org/apache/hop/ui/hopgui/ToolbarFacade.java
new file mode 100644
index 0000000000..061432c514
--- /dev/null
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/ToolbarFacade.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui;
+
+import org.apache.hop.ui.core.gui.IToolbarContainer;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Facade for toolbar creation. Abstracts the difference between desktop (SWT 
ToolBar) and Hop Web
+ * (RAP), where the RAP implementation returns a Composite with RowLayout so 
toolbars wrap to
+ * multiple lines.
+ *
+ * <p>Use {@link #createToolbarContainer(Composite, int)} with {@link
+ * 
org.apache.hop.ui.core.gui.GuiToolbarWidgets#createToolbarWidgets(IToolbarContainer,
 String)} for
+ * the single code path. {@link #createToolbar(Composite, int)} returns only 
the control for layout.
+ */
+public abstract class ToolbarFacade {
+
+  private static final ToolbarFacade IMPL;
+
+  static {
+    IMPL = (ToolbarFacade) 
ImplementationLoader.newInstance(ToolbarFacade.class);
+  }
+
+  /**
+   * Create a toolbar container. Use {@link IToolbarContainer#getControl()} 
for layout, then {@link
+   * 
org.apache.hop.ui.core.gui.GuiToolbarWidgets#createToolbarWidgets(IToolbarContainer,
 String)}
+   * to add items in a single path.
+   *
+   * @param parent the parent composite
+   * @param style SWT style (e.g. SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL)
+   * @return container whose getControl() is the toolbar (ToolBar or Composite)
+   */
+  public static IToolbarContainer createToolbarContainer(Composite parent, int 
style) {
+    return IMPL.createToolbarContainerInternal(parent, style);
+  }
+
+  /**
+   * Create a toolbar parent control. Convenience for {@link 
#createToolbarContainer(Composite,
+   * int)}.{@link IToolbarContainer#getControl() getControl()}.
+   */
+  public static Control createToolbar(Composite parent, int style) {
+    return createToolbarContainer(parent, style).getControl();
+  }
+
+  /**
+   * Implementation-specific toolbar container creation.
+   *
+   * @param parent the parent composite
+   * @param style SWT style
+   * @return container wrapping ToolBar (desktop) or Composite with RowLayout 
(web)
+   */
+  protected abstract IToolbarContainer 
createToolbarContainerInternal(Composite parent, int style);
+}
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
index 59bbd2e490..a52780b48e 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
@@ -146,11 +146,13 @@ import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
 import org.apache.hop.ui.core.gui.HopNamespace;
 import org.apache.hop.ui.core.gui.HopToolTip;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.hopgui.CanvasFacade;
 import org.apache.hop.ui.hopgui.CanvasListener;
 import org.apache.hop.ui.hopgui.HopGui;
 import org.apache.hop.ui.hopgui.HopGuiExtensionPoint;
 import org.apache.hop.ui.hopgui.ServerPushSessionFacade;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.context.GuiContextUtil;
 import org.apache.hop.ui.hopgui.context.IGuiContextHandler;
 import org.apache.hop.ui.hopgui.delegates.HopGuiServerDelegate;
@@ -204,6 +206,7 @@ import org.eclipse.swt.layout.FormLayout;
 import org.eclipse.swt.widgets.Canvas;
 import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.Menu;
@@ -291,7 +294,7 @@ public class HopGuiPipelineGraph extends HopGuiAbstractGraph
 
   @Getter private final ExplorerPerspective perspective;
 
-  @Getter @Setter private ToolBar toolBar;
+  @Getter @Setter private Control toolBar;
 
   @Getter private GuiToolbarWidgets toolBarWidgets;
 
@@ -2102,10 +2105,12 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
     try {
       // Create a new toolbar at the top of the main composite...
       //
-      toolBar = new ToolBar(this, SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL);
+      IToolbarContainer toolBarContainer =
+          ToolbarFacade.createToolbarContainer(this, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+      toolBar = toolBarContainer.getControl();
       toolBarWidgets = new GuiToolbarWidgets();
       toolBarWidgets.registerGuiPluginObject(this);
-      toolBarWidgets.createToolbarWidgets(toolBar, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
+      toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
       FormData layoutData = new FormData();
       layoutData.left = new FormAttachment(0, 0);
       layoutData.top = new FormAttachment(0, 0);
@@ -4150,7 +4155,6 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
       image = "ui/images/show-results.svg",
       separator = true)
   public void showExecutionResults() {
-    ToolItem item = 
toolBarWidgets.findToolItem(TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS);
     if (isExecutionResultsPaneVisible()) {
       disposeExtraView();
     } else {
@@ -4174,9 +4178,11 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
     sashForm.layout();
     sashForm.setWeights(100);
 
-    ToolItem item = 
toolBarWidgets.findToolItem(TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS);
-    item.setToolTipText(BaseMessages.getString(PKG, 
"HopGui.Tooltip.ShowExecutionResults"));
-    item.setImage(GuiResource.getInstance().getImageShowResults());
+    toolBarWidgets.setToolbarItemToolTip(
+        TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS,
+        BaseMessages.getString(PKG, "HopGui.Tooltip.ShowExecutionResults"));
+    toolBarWidgets.setToolbarItemImage(
+        TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS, "ui/images/show-results.svg");
   }
 
   private void minMaxExtraView() {
@@ -4550,11 +4556,11 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
       extraViewTabFolder.setSelection(0);
     }
 
-    if (!EnvironmentUtils.getInstance().isWeb()) {
-      ToolItem item = 
toolBarWidgets.findToolItem(TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS);
-      item.setImage(GuiResource.getInstance().getImageHideResults());
-      item.setToolTipText(BaseMessages.getString(PKG, 
"HopGui.Tooltip.HideExecutionResults"));
-    }
+    toolBarWidgets.setToolbarItemImage(
+        TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS, "ui/images/hide-results.svg");
+    toolBarWidgets.setToolbarItemToolTip(
+        TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS,
+        BaseMessages.getString(PKG, "HopGui.Tooltip.HideExecutionResults"));
   }
 
   public synchronized void debug(
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineCheckDelegate.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineCheckDelegate.java
index 2683c59015..64e52d4f99 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineCheckDelegate.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineCheckDelegate.java
@@ -38,7 +38,9 @@ import org.apache.hop.ui.core.dialog.ErrorDialog;
 import org.apache.hop.ui.core.dialog.ProgressMonitorDialog;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.file.IHopFileTypeHandler;
 import org.apache.hop.ui.hopgui.file.pipeline.HopGuiPipelineGraph;
 import org.eclipse.swt.SWT;
@@ -48,8 +50,8 @@ import org.eclipse.swt.layout.FormAttachment;
 import org.eclipse.swt.layout.FormData;
 import org.eclipse.swt.layout.FormLayout;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.ToolBar;
 import org.eclipse.swt.widgets.Tree;
 import org.eclipse.swt.widgets.TreeItem;
 
@@ -117,7 +119,9 @@ public class HopGuiPipelineCheckDelegate {
 
     // Add toolbar
     //
-    ToolBar toolbar = new ToolBar(checkComposite, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(checkComposite, SWT.WRAP | 
SWT.LEFT | SWT.HORIZONTAL);
+    Control toolbar = toolBarContainer.getControl();
     FormData fdToolBar = new FormData();
     fdToolBar.left = new FormAttachment(0, 0);
     fdToolBar.top = new FormAttachment(0, 0);
@@ -127,7 +131,7 @@ public class HopGuiPipelineCheckDelegate {
 
     toolBarWidgets = new GuiToolbarWidgets();
     toolBarWidgets.registerGuiPluginObject(this);
-    toolBarWidgets.createToolbarWidgets(toolbar, GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
     toolbar.pack();
 
     FormData fd = new FormData();
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineGridDelegate.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineGridDelegate.java
index 0b17300468..2f261be7c6 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineGridDelegate.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineGridDelegate.java
@@ -49,9 +49,11 @@ import org.apache.hop.pipeline.transform.TransformStatus;
 import org.apache.hop.ui.core.PropsUi;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.widget.ColumnInfo;
 import org.apache.hop.ui.core.widget.TableView;
 import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.file.IHopFileTypeHandler;
 import org.apache.hop.ui.hopgui.file.pipeline.HopGuiPipelineGraph;
 import org.apache.hop.ui.hopgui.selection.HopGuiSelectionTracker;
@@ -60,7 +62,9 @@ import org.eclipse.swt.custom.CTabItem;
 import org.eclipse.swt.layout.FormAttachment;
 import org.eclipse.swt.layout.FormData;
 import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.layout.RowData;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.swt.widgets.TableItem;
@@ -95,7 +99,7 @@ public class HopGuiPipelineGridDelegate {
 
   private TableView pipelineGridView;
 
-  private ToolBar toolbar;
+  private Control toolbar;
   private GuiToolbarWidgets toolbarWidget;
 
   private Composite pipelineGridComposite;
@@ -364,8 +368,10 @@ public class HopGuiPipelineGridDelegate {
   }
 
   private void addToolBar() {
-
-    toolbar = new ToolBar(pipelineGridComposite, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(
+            pipelineGridComposite, SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL);
+    toolbar = toolBarContainer.getControl();
     FormData fdToolBar = new FormData();
     fdToolBar.left = new FormAttachment(0, 0);
     fdToolBar.top = new FormAttachment(0, 0);
@@ -375,14 +381,40 @@ public class HopGuiPipelineGridDelegate {
 
     toolbarWidget = new GuiToolbarWidgets();
     toolbarWidget.registerGuiPluginObject(this);
-    toolbarWidget.createToolbarWidgets(toolbar, GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolbarWidget.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
+
+    addSearchBarToToolbar(toolbar);
+
+    toolbar.pack();
+  }
+
+  /**
+   * Add the transform-name search bar to the toolbar. Layout differs for 
ToolBar (desktop) vs
+   * Composite (web flow).
+   */
+  private void addSearchBarToToolbar(Control toolbarControl) {
+    final int searchWidth = 260;
+    final int textStyle = SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL | 
SWT.BORDER;
+
+    if (toolbarControl instanceof ToolBar tb) {
+      ToolItem searchSeparator = new ToolItem(tb, SWT.SEPARATOR);
+      searchText = new Text(tb, textStyle);
+      configureSearchTextListener();
+      searchSeparator.setControl(searchText);
+      searchSeparator.setWidth(searchWidth);
+    } else {
+      searchText = new Text((Composite) toolbarControl, textStyle);
+      configureSearchTextListener();
+      searchText.pack();
+      searchText.setLayoutData(new RowData(searchWidth, SWT.DEFAULT));
+    }
 
-    // Search bar: filter table by transform name (smart search, min 2 chars, 
case-insensitive)
-    ToolItem searchSeparator = new ToolItem(toolbar, SWT.SEPARATOR);
-    searchText = new Text(toolbar, SWT.SEARCH | SWT.ICON_SEARCH | 
SWT.ICON_CANCEL | SWT.BORDER);
     searchText.setMessage(
         BaseMessages.getString(PKG, 
"PipelineLog.Search.TransformName.Placeholder"));
     PropsUi.setLook(searchText, Props.WIDGET_STYLE_TOOLBAR);
+  }
+
+  private void configureSearchTextListener() {
     searchText.addListener(
         SWT.Modify,
         e -> {
@@ -393,10 +425,6 @@ public class HopGuiPipelineGridDelegate {
           transformNameSearchText = raw != null ? raw.trim() : "";
           refreshView();
         });
-    searchSeparator.setControl(searchText);
-    searchSeparator.setWidth(260);
-
-    toolbar.pack();
   }
 
   /** Opens the transform configuration for the selected metrics row (same as 
double-click). */
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineLogDelegate.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineLogDelegate.java
index 11439a2b66..da0d2c35a6 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineLogDelegate.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineLogDelegate.java
@@ -33,11 +33,13 @@ import org.apache.hop.ui.core.PropsUi;
 import org.apache.hop.ui.core.dialog.EnterSelectionDialog;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.widget.OsHelper;
 import org.apache.hop.ui.core.widget.StyledTextComp;
 import org.apache.hop.ui.core.widget.StyledTextVar;
 import org.apache.hop.ui.core.widget.TextComposite;
 import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.file.IHopFileTypeHandler;
 import org.apache.hop.ui.hopgui.file.pipeline.HopGuiLogBrowser;
 import org.apache.hop.ui.hopgui.file.pipeline.HopGuiPipelineGraph;
@@ -49,7 +51,7 @@ import org.eclipse.swt.layout.FormAttachment;
 import org.eclipse.swt.layout.FormData;
 import org.eclipse.swt.layout.FormLayout;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.ToolItem;
 
 @GuiPlugin(description = "Pipeline Graph Log Delegate")
@@ -75,7 +77,7 @@ public class HopGuiPipelineLogDelegate {
   private TextComposite pipelineLogText;
   private TextZoom textZoom;
 
-  private ToolBar toolbar;
+  private Control toolbar;
   private GuiToolbarWidgets toolBarWidgets;
 
   private Composite pipelineLogComposite;
@@ -181,7 +183,10 @@ public class HopGuiPipelineLogDelegate {
   }
 
   private void addToolBar() {
-    toolbar = new ToolBar(pipelineLogComposite, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(
+            pipelineLogComposite, SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL);
+    toolbar = toolBarContainer.getControl();
     FormData fdToolBar = new FormData();
     fdToolBar.left = new FormAttachment(0, 0);
     fdToolBar.top = new FormAttachment(0, 0);
@@ -191,7 +196,7 @@ public class HopGuiPipelineLogDelegate {
 
     toolBarWidgets = new GuiToolbarWidgets();
     toolBarWidgets.registerGuiPluginObject(this);
-    toolBarWidgets.createToolbarWidgets(toolbar, GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
     toolbar.pack();
   }
 
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
index f1737c4543..ac7923e1da 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
@@ -106,11 +106,13 @@ import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
 import org.apache.hop.ui.core.gui.HopNamespace;
 import org.apache.hop.ui.core.gui.HopToolTip;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.hopgui.CanvasFacade;
 import org.apache.hop.ui.hopgui.CanvasListener;
 import org.apache.hop.ui.hopgui.HopGui;
 import org.apache.hop.ui.hopgui.HopGuiExtensionPoint;
 import org.apache.hop.ui.hopgui.ServerPushSessionFacade;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.context.GuiContextUtil;
 import org.apache.hop.ui.hopgui.context.IGuiContextHandler;
 import org.apache.hop.ui.hopgui.dialog.NotePadDialog;
@@ -171,6 +173,7 @@ import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.widgets.Canvas;
 import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.ToolBar;
@@ -301,7 +304,7 @@ public class HopGuiWorkflowGraph extends HopGuiAbstractGraph
 
   public CTabFolder extraViewTabFolder;
 
-  private ToolBar toolBar;
+  private Control toolBar;
   @Getter private GuiToolbarWidgets toolBarWidgets;
 
   private boolean halting;
@@ -1649,10 +1652,12 @@ public class HopGuiWorkflowGraph extends 
HopGuiAbstractGraph
     try {
       // Create a new toolbar at the top of the main composite...
       //
-      toolBar = new ToolBar(this, SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL);
+      IToolbarContainer toolBarContainer =
+          ToolbarFacade.createToolbarContainer(this, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+      toolBar = toolBarContainer.getControl();
       toolBarWidgets = new GuiToolbarWidgets();
       toolBarWidgets.registerGuiPluginObject(this);
-      toolBarWidgets.createToolbarWidgets(toolBar, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
+      toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
       FormData layoutData = new FormData();
       layoutData.left = new FormAttachment(0, 0);
       layoutData.top = new FormAttachment(0, 0);
@@ -3706,11 +3711,12 @@ public class HopGuiWorkflowGraph extends 
HopGuiAbstractGraph
     sashForm.layout();
     sashForm.setWeights(100);
 
-    ToolItem item = 
toolBarWidgets.findToolItem(TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS);
-    item.setToolTipText(
+    toolBarWidgets.setToolbarItemToolTip(
+        TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS,
         TranslateUtil.translate(
             
"i18n:org.apache.hop.ui.hopgui:HopGui.Tooltip.ShowExecutionResults", PKG));
-    item.setImage(GuiResource.getInstance().getImageShowResults());
+    toolBarWidgets.setToolbarItemImage(
+        TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS, "ui/images/show-results.svg");
   }
 
   private void minMaxExtraView() {
@@ -3762,11 +3768,12 @@ public class HopGuiWorkflowGraph extends 
HopGuiAbstractGraph
       extraViewTabFolder.setSelection(0);
     }
 
-    ToolItem toolItem = 
toolBarWidgets.findToolItem(TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS);
-    toolItem.setToolTipText(
+    toolBarWidgets.setToolbarItemToolTip(
+        TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS,
         TranslateUtil.translate(
             
"i18n:org.apache.hop.ui.hopgui:HopGui.Tooltip.HideExecutionResults", PKG));
-    toolItem.setImage(GuiResource.getInstance().getImageHideResults());
+    toolBarWidgets.setToolbarItemImage(
+        TOOLBAR_ITEM_SHOW_EXECUTION_RESULTS, "ui/images/hide-results.svg");
   }
 
   @Override
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowCheckDelegate.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowCheckDelegate.java
index 29f8a38ea1..54acebdfe0 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowCheckDelegate.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowCheckDelegate.java
@@ -35,7 +35,9 @@ import org.apache.hop.ui.core.dialog.ErrorDialog;
 import org.apache.hop.ui.core.dialog.ProgressMonitorDialog;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.file.IHopFileTypeHandler;
 import org.apache.hop.ui.hopgui.file.workflow.HopGuiWorkflowGraph;
 import org.apache.hop.workflow.WorkflowMeta;
@@ -48,8 +50,8 @@ import org.eclipse.swt.layout.FormAttachment;
 import org.eclipse.swt.layout.FormData;
 import org.eclipse.swt.layout.FormLayout;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.ToolBar;
 import org.eclipse.swt.widgets.Tree;
 import org.eclipse.swt.widgets.TreeItem;
 
@@ -116,7 +118,9 @@ public class HopGuiWorkflowCheckDelegate {
 
     // Add toolbar
     //
-    ToolBar toolbar = new ToolBar(checkComposite, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(checkComposite, SWT.WRAP | 
SWT.LEFT | SWT.HORIZONTAL);
+    Control toolbar = toolBarContainer.getControl();
     FormData fdToolBar = new FormData();
     fdToolBar.left = new FormAttachment(0, 0);
     fdToolBar.top = new FormAttachment(0, 0);
@@ -126,7 +130,7 @@ public class HopGuiWorkflowCheckDelegate {
 
     toolBarWidgets = new GuiToolbarWidgets();
     toolBarWidgets.registerGuiPluginObject(this);
-    toolBarWidgets.createToolbarWidgets(toolbar, GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
     toolbar.pack();
 
     FormData fd = new FormData();
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowLogDelegate.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowLogDelegate.java
index 772a48deb6..ca01523f0a 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowLogDelegate.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowLogDelegate.java
@@ -29,11 +29,13 @@ import org.apache.hop.ui.core.PropsUi;
 import org.apache.hop.ui.core.dialog.EnterSelectionDialog;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.widget.OsHelper;
 import org.apache.hop.ui.core.widget.StyledTextComp;
 import org.apache.hop.ui.core.widget.StyledTextVar;
 import org.apache.hop.ui.core.widget.TextComposite;
 import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.file.IHopFileTypeHandler;
 import org.apache.hop.ui.hopgui.file.pipeline.HopGuiLogBrowser;
 import org.apache.hop.ui.hopgui.file.shared.TextZoom;
@@ -47,7 +49,7 @@ import org.eclipse.swt.layout.FormAttachment;
 import org.eclipse.swt.layout.FormData;
 import org.eclipse.swt.layout.FormLayout;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.Control;
 
 @GuiPlugin(description = "Workflow Graph Log Delegate")
 public class HopGuiWorkflowLogDelegate {
@@ -74,7 +76,7 @@ public class HopGuiWorkflowLogDelegate {
   /** The number of lines in the log tab */
   private Composite workflowLogComposite;
 
-  private ToolBar toolbar;
+  private Control toolbar;
   private GuiToolbarWidgets toolBarWidgets;
 
   private HopGuiLogBrowser logBrowser;
@@ -181,7 +183,10 @@ public class HopGuiWorkflowLogDelegate {
   }
 
   private void addToolBar() {
-    toolbar = new ToolBar(workflowLogComposite, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(
+            workflowLogComposite, SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL);
+    toolbar = toolBarContainer.getControl();
     FormData fdToolBar = new FormData();
     fdToolBar.left = new FormAttachment(0, 0);
     fdToolBar.top = new FormAttachment(0, 0);
@@ -191,7 +196,7 @@ public class HopGuiWorkflowLogDelegate {
 
     toolBarWidgets = new GuiToolbarWidgets();
     toolBarWidgets.registerGuiPluginObject(this);
-    toolBarWidgets.createToolbarWidgets(toolbar, GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
     toolbar.pack();
   }
 
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/ExecutionPerspective.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/ExecutionPerspective.java
index 787927ebd0..071de715b7 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/ExecutionPerspective.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/ExecutionPerspective.java
@@ -53,6 +53,7 @@ import org.apache.hop.ui.core.dialog.ErrorDialog;
 import org.apache.hop.ui.core.dialog.MessageBox;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.metadata.MetadataEditor;
 import org.apache.hop.ui.core.metadata.MetadataManager;
 import org.apache.hop.ui.core.widget.TabFolderReorder;
@@ -60,6 +61,7 @@ import org.apache.hop.ui.core.widget.TreeMemory;
 import org.apache.hop.ui.core.widget.TreeUtil;
 import org.apache.hop.ui.hopgui.HopGui;
 import org.apache.hop.ui.hopgui.HopGuiKeyHandler;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.context.IGuiContextHandler;
 import org.apache.hop.ui.hopgui.file.IHopFileTypeHandler;
 import org.apache.hop.ui.hopgui.file.empty.EmptyFileType;
@@ -123,7 +125,7 @@ public class ExecutionPerspective implements 
IHopPerspective, TabClosable {
   private SashForm sash;
   private Tree tree;
   private CTabFolder tabFolder;
-  private ToolBar toolBar;
+  private Control toolBar;
   private GuiToolbarWidgets toolBarWidgets;
 
   private List<IExecutionViewer> viewers = new ArrayList<>();
@@ -205,10 +207,12 @@ public class ExecutionPerspective implements 
IHopPerspective, TabClosable {
 
     // Create toolbar
     //
-    toolBar = new ToolBar(composite, SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(composite, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    toolBar = toolBarContainer.getControl();
     toolBarWidgets = new GuiToolbarWidgets();
     toolBarWidgets.registerGuiPluginObject(this);
-    toolBarWidgets.createToolbarWidgets(toolBar, GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
     FormData layoutData = new FormData();
     layoutData.left = new FormAttachment(0, 0);
     layoutData.top = new FormAttachment(0, 0);
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/PipelineExecutionViewer.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/PipelineExecutionViewer.java
index 7ff8edfbc8..7b8e874e99 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/PipelineExecutionViewer.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/PipelineExecutionViewer.java
@@ -74,12 +74,14 @@ import org.apache.hop.ui.core.dialog.ErrorDialog;
 import org.apache.hop.ui.core.dialog.SelectRowDialog;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.widget.ColumnInfo;
 import org.apache.hop.ui.core.widget.TableView;
 import org.apache.hop.ui.hopgui.CanvasFacade;
 import org.apache.hop.ui.hopgui.CanvasListener;
 import org.apache.hop.ui.hopgui.HopGui;
 import org.apache.hop.ui.hopgui.HopGuiExtensionPoint;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.file.pipeline.HopGuiPipelineGraph;
 import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerPerspective;
 import org.apache.hop.ui.hopgui.shared.BaseExecutionViewer;
@@ -107,7 +109,6 @@ import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.TableItem;
 import org.eclipse.swt.widgets.Text;
-import org.eclipse.swt.widgets.ToolBar;
 import org.w3c.dom.Node;
 
 @GuiPlugin(name = "i18n::PipelineExecutionViewer.Name")
@@ -174,10 +175,12 @@ public class PipelineExecutionViewer extends 
BaseExecutionViewer
 
     // A toolbar at the top
     //
-    toolBar = new ToolBar(this, SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(this, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    toolBar = toolBarContainer.getControl();
     toolBarWidgets = new GuiToolbarWidgets();
     toolBarWidgets.registerGuiPluginObject(this);
-    toolBarWidgets.createToolbarWidgets(toolBar, GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
     FormData layoutData = new FormData();
     layoutData.left = new FormAttachment(0, 0);
     layoutData.top = new FormAttachment(0, 0);
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/WorkflowExecutionViewer.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/WorkflowExecutionViewer.java
index ebe70e501a..5b5bb25c19 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/WorkflowExecutionViewer.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/WorkflowExecutionViewer.java
@@ -68,11 +68,13 @@ import org.apache.hop.ui.core.dialog.ErrorDialog;
 import org.apache.hop.ui.core.dialog.SelectRowDialog;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.widget.ColumnInfo;
 import org.apache.hop.ui.core.widget.TableView;
 import org.apache.hop.ui.hopgui.CanvasFacade;
 import org.apache.hop.ui.hopgui.CanvasListener;
 import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.file.workflow.HopGuiWorkflowGraph;
 import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerPerspective;
 import org.apache.hop.ui.hopgui.shared.BaseExecutionViewer;
@@ -103,7 +105,6 @@ import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.TableItem;
 import org.eclipse.swt.widgets.Text;
-import org.eclipse.swt.widgets.ToolBar;
 import org.w3c.dom.Node;
 
 @GuiPlugin(name = "i18n::WorkflowExecutionViewer.Name")
@@ -172,10 +173,12 @@ public class WorkflowExecutionViewer extends 
BaseExecutionViewer
 
     // A toolbar at the top
     //
-    toolBar = new ToolBar(this, SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(this, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    toolBar = toolBarContainer.getControl();
     toolBarWidgets = new GuiToolbarWidgets();
     toolBarWidgets.registerGuiPluginObject(this);
-    toolBarWidgets.createToolbarWidgets(toolBar, GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
     FormData layoutData = new FormData();
     layoutData.left = new FormAttachment(0, 0);
     layoutData.top = new FormAttachment(0, 0);
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
index 0d9d3c87cc..0eca5f8f81 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
@@ -72,10 +72,12 @@ import org.apache.hop.ui.core.dialog.MessageBox;
 import org.apache.hop.ui.core.gui.GuiMenuWidgets;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.widget.TreeMemory;
 import org.apache.hop.ui.hopgui.HopGui;
 import org.apache.hop.ui.hopgui.HopGuiExtensionPoint;
 import org.apache.hop.ui.hopgui.HopGuiKeyHandler;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.context.IGuiContextHandler;
 import org.apache.hop.ui.hopgui.file.HopFileTypePluginType;
 import org.apache.hop.ui.hopgui.file.IHopFileType;
@@ -194,7 +196,7 @@ public class ExplorerPerspective implements 
IHopPerspective, TabClosable {
   @Getter private Tree tree;
   private TreeEditor treeEditor;
   private CTabFolder tabFolder;
-  private ToolBar toolBar;
+  private Control toolBar;
   @Getter private GuiMenuWidgets menuWidgets;
   private final List<TabItemHandler> items;
   private boolean showingHiddenFiles;
@@ -458,10 +460,12 @@ public class ExplorerPerspective implements 
IHopPerspective, TabClosable {
 
     // Create toolbar
     //
-    toolBar = new ToolBar(composite, SWT.WRAP | SWT.LEFT | SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(composite, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    toolBar = toolBarContainer.getControl();
     toolBarWidgets = new GuiToolbarWidgets();
     toolBarWidgets.registerGuiPluginObject(this);
-    toolBarWidgets.createToolbarWidgets(toolBar, GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
     FormData toolBarFormData = new FormData();
     toolBarFormData.left = new FormAttachment(0, 0);
     toolBarFormData.top = new FormAttachment(0, 0);
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/metadata/MetadataPerspective.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/metadata/MetadataPerspective.java
index 98deb654a4..49afd63d25 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/metadata/MetadataPerspective.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/metadata/MetadataPerspective.java
@@ -51,6 +51,7 @@ import org.apache.hop.ui.core.dialog.ErrorDialog;
 import org.apache.hop.ui.core.dialog.ShowMessageDialog;
 import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
+import org.apache.hop.ui.core.gui.IToolbarContainer;
 import org.apache.hop.ui.core.metadata.MetadataEditor;
 import org.apache.hop.ui.core.metadata.MetadataFileType;
 import org.apache.hop.ui.core.metadata.MetadataManager;
@@ -58,6 +59,7 @@ import org.apache.hop.ui.core.widget.TreeMemory;
 import org.apache.hop.ui.core.widget.TreeUtil;
 import org.apache.hop.ui.hopgui.HopGui;
 import org.apache.hop.ui.hopgui.HopGuiKeyHandler;
+import org.apache.hop.ui.hopgui.ToolbarFacade;
 import org.apache.hop.ui.hopgui.context.IGuiContextHandler;
 import org.apache.hop.ui.hopgui.file.IHopFileType;
 import org.apache.hop.ui.hopgui.file.IHopFileTypeHandler;
@@ -253,10 +255,12 @@ public class MetadataPerspective implements 
IHopPerspective, TabClosable {
 
     // Create toolbar
     //
-    ToolBar toolBar = new ToolBar(composite, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    IToolbarContainer toolBarContainer =
+        ToolbarFacade.createToolbarContainer(composite, SWT.WRAP | SWT.LEFT | 
SWT.HORIZONTAL);
+    Control toolBar = toolBarContainer.getControl();
     toolBarWidgets = new GuiToolbarWidgets();
     toolBarWidgets.registerGuiPluginObject(this);
-    toolBarWidgets.createToolbarWidgets(toolBar, GUI_PLUGIN_TOOLBAR_PARENT_ID);
+    toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
     FormData toolBarFormData = new FormData();
     toolBarFormData.left = new FormAttachment(0, 0);
     toolBarFormData.top = new FormAttachment(0, 0);
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/shared/BaseExecutionViewer.java 
b/ui/src/main/java/org/apache/hop/ui/hopgui/shared/BaseExecutionViewer.java
index 07b2b4d0ad..fca9a356c4 100644
--- a/ui/src/main/java/org/apache/hop/ui/hopgui/shared/BaseExecutionViewer.java
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/shared/BaseExecutionViewer.java
@@ -55,9 +55,9 @@ import org.eclipse.swt.events.MouseListener;
 import org.eclipse.swt.events.MouseMoveListener;
 import org.eclipse.swt.graphics.Cursor;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Text;
-import org.eclipse.swt.widgets.ToolBar;
 
 public abstract class BaseExecutionViewer extends DragViewZoomBase
     implements MouseListener, MouseMoveListener {
@@ -74,7 +74,7 @@ public abstract class BaseExecutionViewer extends 
DragViewZoomBase
   protected final Execution execution;
   protected ExecutionState executionState;
 
-  protected ToolBar toolBar;
+  protected Control toolBar;
   protected GuiToolbarWidgets toolBarWidgets;
   protected SashForm sash;
   protected CTabFolder tabFolder;
@@ -355,7 +355,7 @@ public abstract class BaseExecutionViewer extends 
DragViewZoomBase
    *
    * @return value of toolBar
    */
-  public ToolBar getToolBar() {
+  public Control getToolBar() {
     return toolBar;
   }
 
@@ -364,7 +364,7 @@ public abstract class BaseExecutionViewer extends 
DragViewZoomBase
    *
    * @param toolBar value of toolBar
    */
-  public void setToolBar(ToolBar toolBar) {
+  public void setToolBar(Control toolBar) {
     this.toolBar = toolBar;
   }
 

Reply via email to