You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by bo...@apache.org on 2023/11/09 19:09:28 UTC

(myfaces-tobago) branch tobago-5.x updated: feat(selectList): SelectItemGroup support for Select(One|Many)List

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

bommel pushed a commit to branch tobago-5.x
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git


The following commit(s) were added to refs/heads/tobago-5.x by this push:
     new c65938f1d7 feat(selectList): SelectItemGroup support for Select(One|Many)List
c65938f1d7 is described below

commit c65938f1d7ad96a08ccfdd0833575d190e2c541c
Author: Bernd Bohmann <bo...@apache.org>
AuthorDate: Thu Nov 9 20:09:21 2023 +0100

    feat(selectList): SelectItemGroup support for Select(One|Many)List
    
    issue: TOBAGO-2258
---
 .../renderkit/renderer/SelectManyListRenderer.java | 72 +++++++++++++++-------
 .../renderkit/renderer/SelectOneListRenderer.java  | 71 ++++++++++++++-------
 .../myfaces/tobago/renderkit/css/TobagoClass.java  |  2 +
 .../internal/util/SelectItemUtilsUnitTest.java     | 48 +++++++++++++++
 .../selectManyList/selectManyListAjax.html         |  4 +-
 .../renderer/selectOneList/selectOneListAjax.html  |  4 +-
 .../example/demo/SelectOneListboxController.java   | 19 +++---
 .../030-select/40-selectOneListbox/Listbox.xhtml   |  3 +-
 tobago-theme/src/main/scss/_tobago.scss            |  9 +++
 .../src/main/css/tobago.css                        | 14 +++++
 .../src/main/css/tobago.css.map                    |  2 +-
 .../src/main/css/tobago.min.css                    |  2 +-
 .../src/main/css/tobago.min.css.map                |  2 +-
 .../src/main/css/tobago.css                        | 14 +++++
 .../src/main/css/tobago.css.map                    |  2 +-
 .../src/main/css/tobago.min.css                    |  2 +-
 .../src/main/css/tobago.min.css.map                |  2 +-
 .../src/main/css/tobago.css                        | 14 +++++
 .../src/main/css/tobago.css.map                    |  2 +-
 .../src/main/css/tobago.min.css                    |  2 +-
 .../src/main/css/tobago.min.css.map                |  2 +-
 .../tobago-theme-speyside/src/main/css/tobago.css  | 14 +++++
 .../src/main/css/tobago.css.map                    |  2 +-
 .../src/main/css/tobago.min.css                    |  2 +-
 .../src/main/css/tobago.min.css.map                |  2 +-
 .../tobago-theme-standard/src/main/css/tobago.css  | 14 +++++
 .../src/main/css/tobago.css.map                    |  2 +-
 .../src/main/css/tobago.min.css                    |  2 +-
 .../src/main/css/tobago.min.css.map                |  2 +-
 .../tobago-theme-standard/src/main/js/tobago.js    |  2 +-
 .../src/main/js/tobago.js.map                      |  2 +-
 .../src/main/ts/tobago-select-list-base.ts         |  2 +-
 32 files changed, 262 insertions(+), 76 deletions(-)

diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyListRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyListRenderer.java
index 0393eb3ee5..317ae8a9eb 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyListRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyListRenderer.java
@@ -38,6 +38,7 @@ import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
 
 import javax.faces.context.FacesContext;
 import javax.faces.model.SelectItem;
+import javax.faces.model.SelectItemGroup;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -182,30 +183,22 @@ public class SelectManyListRenderer<T extends AbstractUISelectManyList> extends
     final Object[] values = component.getSelectedValues();
     final String[] submittedValues = getSubmittedValues(component);
     for (SelectItem item : items) {
-      Object itemValue = item.getValue();
-      // when using selectItem tag with a literal value: use the converted value
-      if (itemValue instanceof String && values != null && values.length > 0 && !(values[0] instanceof String)) {
-        itemValue = ComponentUtils.getConvertedValue(facesContext, component, (String) itemValue);
-      }
-      final String formattedValue = getFormattedValue(facesContext, (T) component, itemValue);
-      final boolean contains;
-      if (submittedValues == null) {
-        contains = ArrayUtils.contains(values, itemValue);
+      if (item instanceof SelectItemGroup) {
+        writer.startElement(HtmlElements.TR);
+        writer.writeClassAttribute(TobagoClass.SELECT__ITEM__GROUP, BootstrapClass.DISABLED);
+        writer.writeAttribute(HtmlAttributes.TABINDEX, -1);
+        writer.startElement(HtmlElements.TD);
+        writer.writeText(item.getLabel());
+        writer.endElement(HtmlElements.TD);
+        writer.endElement(HtmlElements.TR);
+        final SelectItem[] selectItems = ((SelectItemGroup) item).getSelectItems();
+        for (SelectItem selectItem : selectItems) {
+          encodeSelectItem(facesContext, writer, component, selectItem, values, submittedValues,
+              disabled || item.isDisabled(), true);
+        }
       } else {
-        contains = ArrayUtils.contains(submittedValues, formattedValue);
+        encodeSelectItem(facesContext, writer, component, item, values, submittedValues, disabled, false);
       }
-      writer.startElement(HtmlElements.TR);
-      writer.writeAttribute(DataAttributes.VALUE, formattedValue, true);
-      writer.writeClassAttribute(
-          contains ? BootstrapClass.TABLE_PRIMARY : null,
-          disabled || item.isDisabled() ? TobagoClass.DISABLED : null);
-      writer.writeAttribute(HtmlAttributes.TABINDEX, -1);
-
-      writer.startElement(HtmlElements.TD);
-      writer.writeAttribute(HtmlAttributes.VALUE, formattedValue, true);
-      writer.writeText(item.getLabel());
-      writer.endElement(HtmlElements.TD);
-      writer.endElement(HtmlElements.TR);
     }
 
     writer.endElement(HtmlElements.TBODY);
@@ -221,6 +214,41 @@ public class SelectManyListRenderer<T extends AbstractUISelectManyList> extends
     writer.endElement(HtmlElements.DIV);
   }
 
+  private void encodeSelectItem(FacesContext facesContext, TobagoResponseWriter writer, T component, SelectItem item,
+        Object[] values, String[] submittedValues, boolean disabled, boolean group) throws IOException {
+    Object itemValue = item.getValue();
+    // when using selectItem tag with a literal value: use the converted value
+    if (itemValue instanceof String && values != null && values.length > 0 && !(values[0] instanceof String)) {
+      itemValue = ComponentUtils.getConvertedValue(facesContext, component, (String) itemValue);
+    }
+    final String formattedValue = getFormattedValue(facesContext, (T) component, itemValue);
+    final boolean contains;
+    if (submittedValues == null) {
+      contains = ArrayUtils.contains(values, itemValue);
+    } else {
+      contains = ArrayUtils.contains(submittedValues, formattedValue);
+    }
+    writer.startElement(HtmlElements.TR);
+    writer.writeAttribute(DataAttributes.VALUE, formattedValue, true);
+    writer.writeClassAttribute(
+        TobagoClass.SELECT__ITEM,
+        contains ? BootstrapClass.TABLE_PRIMARY : null,
+        disabled || item.isDisabled() ? BootstrapClass.DISABLED : null);
+    writer.writeAttribute(HtmlAttributes.TABINDEX, -1);
+
+    writer.startElement(HtmlElements.TD);
+    writer.writeAttribute(HtmlAttributes.VALUE, formattedValue, true);
+    if (group) {
+      writer.startElement(HtmlElements.SPAN);
+    }
+    writer.writeText(item.getLabel());
+    if (group) {
+      writer.endElement(HtmlElements.SPAN);
+    }
+    writer.endElement(HtmlElements.TD);
+    writer.endElement(HtmlElements.TR);
+  }
+
   @Override
   protected void encodeEndField(FacesContext facesContext, T component) throws IOException {
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneListRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneListRenderer.java
index d0c62c3c47..af8bfb6c03 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneListRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneListRenderer.java
@@ -37,6 +37,7 @@ import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
 
 import javax.faces.context.FacesContext;
 import javax.faces.model.SelectItem;
+import javax.faces.model.SelectItemGroup;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -154,30 +155,22 @@ public class SelectOneListRenderer<T extends AbstractUISelectOneList> extends Se
     final Object value = component.getValue();
     final Object submittedValue = component.getSubmittedValue();
     for (SelectItem item : items) {
-      Object itemValue = item.getValue();
-      // when using selectItem tag with a literal value: use the converted value
-      if (itemValue instanceof String && value != null && !(value instanceof String)) {
-        itemValue = ComponentUtils.getConvertedValue(facesContext, component, (String) itemValue);
-      }
-      final String formattedValue = getFormattedValue(facesContext, (T) component, itemValue);
-      final boolean contains;
-      if (submittedValue != null) {
-        contains = submittedValue.equals(formattedValue);
+      if (item instanceof SelectItemGroup) {
+        writer.startElement(HtmlElements.TR);
+        writer.writeClassAttribute(TobagoClass.SELECT__ITEM__GROUP, BootstrapClass.DISABLED);
+        writer.writeAttribute(HtmlAttributes.TABINDEX, -1);
+        writer.startElement(HtmlElements.TD);
+        writer.writeText(item.getLabel());
+        writer.endElement(HtmlElements.TD);
+        writer.endElement(HtmlElements.TR);
+        final SelectItem[] selectItems = ((SelectItemGroup) item).getSelectItems();
+        for (SelectItem selectItem : selectItems) {
+          encodeSelectItem(facesContext, writer, component, selectItem, value, submittedValue,
+              disabled || item.isDisabled(), true);
+        }
       } else {
-        contains = value != null && value.equals(itemValue);
+        encodeSelectItem(facesContext, writer, component, item,  value, submittedValue, disabled, false);
       }
-      writer.startElement(HtmlElements.TR);
-      writer.writeAttribute(DataAttributes.VALUE, formattedValue, true);
-      writer.writeClassAttribute(
-          contains ? BootstrapClass.TABLE_PRIMARY : null,
-          disabled || item.isDisabled() ? TobagoClass.DISABLED : null);
-      writer.writeAttribute(HtmlAttributes.TABINDEX, -1);
-
-      writer.startElement(HtmlElements.TD);
-      writer.writeAttribute(HtmlAttributes.VALUE, formattedValue, true);
-      writer.writeText(item.getLabel());
-      writer.endElement(HtmlElements.TD);
-      writer.endElement(HtmlElements.TR);
     }
 
     writer.endElement(HtmlElements.TBODY);
@@ -193,6 +186,40 @@ public class SelectOneListRenderer<T extends AbstractUISelectOneList> extends Se
     writer.endElement(HtmlElements.DIV);
   }
 
+  private void encodeSelectItem(FacesContext facesContext, TobagoResponseWriter writer, T component, SelectItem item,
+        Object value, Object submittedValue, boolean disabled, boolean group) throws IOException {
+    Object itemValue = item.getValue();
+    // when using selectItem tag with a literal value: use the converted value
+    if (itemValue instanceof String && value != null && !(value instanceof String)) {
+      itemValue = ComponentUtils.getConvertedValue(facesContext, component, (String) itemValue);
+    }
+    final String formattedValue = getFormattedValue(facesContext, (T) component, itemValue);
+    final boolean contains;
+    if (submittedValue != null) {
+      contains = submittedValue.equals(formattedValue);
+    } else {
+      contains = value != null && value.equals(itemValue);
+    }
+    writer.startElement(HtmlElements.TR);
+    writer.writeAttribute(DataAttributes.VALUE, formattedValue, true);
+    writer.writeClassAttribute(
+        TobagoClass.SELECT__ITEM,
+        contains ? BootstrapClass.TABLE_PRIMARY : null,
+        disabled || item.isDisabled() ? BootstrapClass.DISABLED : null);
+    writer.writeAttribute(HtmlAttributes.TABINDEX, -1);
+    writer.startElement(HtmlElements.TD);
+    writer.writeAttribute(HtmlAttributes.VALUE, formattedValue, true);
+    if (group) {
+      writer.startElement(HtmlElements.SPAN);
+    }
+    writer.writeText(item.getLabel());
+    if (group) {
+      writer.endElement(HtmlElements.SPAN);
+    }
+    writer.endElement(HtmlElements.TD);
+    writer.endElement(HtmlElements.TR);
+  }
+
   @Override
   protected void encodeEndField(FacesContext facesContext, T component) throws IOException {
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java
index b94797eb94..d45e14b8be 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java
@@ -93,6 +93,8 @@ public enum TobagoClass implements CssItem {
   RESIZE("tobago-resize"),
   SECTION__CONTENT("tobago-section-content"),
   SELECT__FIELD("tobago-select-field"),
+  SELECT__ITEM("tobago-select-item"),
+  SELECT__ITEM__GROUP("tobago-select-item-group"),
   SELECTED("tobago-selected"),
   SELECTED__CONTAINER("tobago-selected-container"),
   SEPARATOR("tobago-separator"),
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/SelectItemUtilsUnitTest.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/SelectItemUtilsUnitTest.java
new file mode 100644
index 0000000000..e4daca4d43
--- /dev/null
+++ b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/SelectItemUtilsUnitTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.myfaces.tobago.internal.util;
+
+import javax.faces.model.SelectItem;
+import org.apache.myfaces.tobago.component.UISelectItem;
+import org.apache.myfaces.tobago.component.UISelectOneList;
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Iterator;
+
+public class SelectItemUtilsUnitTest extends AbstractTobagoTestBase {
+
+  @Test
+  public void simple() {
+    UISelectOneList oneList = new UISelectOneList();
+    Iterable<SelectItem> itemIterator = SelectItemUtils.getItemIterator(facesContext, oneList);
+    Assertions.assertFalse(itemIterator.iterator().hasNext());
+
+    UISelectItem item = new UISelectItem();
+    oneList.getChildren().add(item);
+    itemIterator = SelectItemUtils.getItemIterator(facesContext, oneList);
+    Iterator<SelectItem> iterator = itemIterator.iterator();
+    Assertions.assertTrue(iterator.hasNext());
+    Assertions.assertNotNull(iterator.next());
+    Assertions.assertFalse(iterator.hasNext());
+  }
+
+}
diff --git a/tobago-core/src/test/resources/renderer/selectManyList/selectManyListAjax.html b/tobago-core/src/test/resources/renderer/selectManyList/selectManyListAjax.html
index 295f2a96aa..602743654a 100644
--- a/tobago-core/src/test/resources/renderer/selectManyList/selectManyListAjax.html
+++ b/tobago-core/src/test/resources/renderer/selectManyList/selectManyListAjax.html
@@ -28,11 +28,11 @@
     <div class='tobago-options tobago-dropdown-menu' name='id'>
       <table class='table table-hover table-sm'>
         <tbody>
-          <tr data-tobago-value='Stratocaster' tabindex='-1'>
+          <tr data-tobago-value='Stratocaster' class='tobago-select-item' tabindex='-1'>
             <td value='Stratocaster'>Stratocaster
             </td>
           </tr>
-          <tr data-tobago-value='Telecaster' tabindex='-1'>
+          <tr data-tobago-value='Telecaster' class='tobago-select-item' tabindex='-1'>
             <td value='Telecaster'>Telecaster
             </td>
           </tr>
diff --git a/tobago-core/src/test/resources/renderer/selectOneList/selectOneListAjax.html b/tobago-core/src/test/resources/renderer/selectOneList/selectOneListAjax.html
index 148808fa04..6b33ddd0ff 100644
--- a/tobago-core/src/test/resources/renderer/selectOneList/selectOneListAjax.html
+++ b/tobago-core/src/test/resources/renderer/selectOneList/selectOneListAjax.html
@@ -29,11 +29,11 @@
     <div class='tobago-options tobago-dropdown-menu' name='id'>
       <table class='table table-hover table-sm'>
         <tbody>
-          <tr data-tobago-value='Stratocaster' tabindex='-1'>
+          <tr data-tobago-value='Stratocaster' class='tobago-select-item' tabindex='-1'>
             <td value='Stratocaster'>Stratocaster
             </td>
           </tr>
-          <tr data-tobago-value='Telecaster' tabindex='-1'>
+          <tr data-tobago-value='Telecaster' class='tobago-select-item' tabindex='-1'>
             <td value='Telecaster'>Telecaster
             </td>
           </tr>
diff --git a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneListboxController.java b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneListboxController.java
index ca98487feb..1e774c91c5 100644
--- a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneListboxController.java
+++ b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneListboxController.java
@@ -19,7 +19,8 @@
 
 package org.apache.myfaces.tobago.example.demo;
 
-import org.apache.myfaces.tobago.model.SelectItem;
+import javax.faces.model.SelectItemGroup;
+import javax.faces.model.SelectItem;
 
 import javax.enterprise.context.RequestScoped;
 import javax.inject.Named;
@@ -34,13 +35,15 @@ public class SelectOneListboxController implements Serializable {
   private String mountain;
 
   public SelectOneListboxController() {
-    mountains = new SelectItem[]{
-        new SelectItem("8848 m", "Everest"),
-        new SelectItem("8611 m", "K2"),
-        new SelectItem("8586 m", "Kangchenjunga"),
-        new SelectItem("8516 m", "Lhotse"),
-        new SelectItem("8481 m", "Makalu")
-    };
+    mountains = new SelectItem[] {
+        new SelectItemGroup("Mountains", "Mountains", false,
+            new SelectItem[] {
+                new SelectItem("8848 m", "Everest"),
+                new SelectItem("8611 m", "K2"),
+                new SelectItem("8586 m", "Kangchenjunga"),
+                new SelectItem("8516 m", "Lhotse"),
+                new SelectItem("8481 m", "Makalu")
+        })};
   }
 
   public String getRiver() {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/030-select/40-selectOneListbox/Listbox.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/030-select/40-selectOneListbox/Listbox.xhtml
index 3d25dfd18b..df84b7392b 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/030-select/40-selectOneListbox/Listbox.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/030-select/40-selectOneListbox/Listbox.xhtml
@@ -99,8 +99,7 @@
       <code class="language-markup">&lt;tc:selectOneListbox/></code> contain a
       <code class="language-markup">&lt;f:ajax render="selectedMountain"/></code>, which rerender the output field.</p>
     <tc:selectOneListbox id="mountainList" label="Mountains" value="#{selectOneListboxController.mountain}">
-      <tc:selectItems value="#{selectOneListboxController.mountains}" var="mountain"
-                      itemLabel="#{mountain.label}" itemValue="#{mountain.value}"/>
+      <tc:selectItems value="#{selectOneListboxController.mountains}"/>
       <f:ajax render="selectedMountain"/>
     </tc:selectOneListbox>
     <tc:out id="selectedMountain" label="Height" value="#{selectOneListboxController.mountain}"/>
diff --git a/tobago-theme/src/main/scss/_tobago.scss b/tobago-theme/src/main/scss/_tobago.scss
index 8972c0e2ea..2f2a698ae0 100644
--- a/tobago-theme/src/main/scss/_tobago.scss
+++ b/tobago-theme/src/main/scss/_tobago.scss
@@ -232,6 +232,15 @@ $tobago-flex-layout-spacing: 0.5rem;
     min-width: 0;
   }
 
+  .tobago-select-item-group {
+    font-weight: bold;
+    pointer-events: none;
+  }
+
+  .tobago-select-item span {
+    padding-left: 0.75rem;
+  }
+
   .tobago-select-field {
     display: flex;
     flex-wrap: wrap;
diff --git a/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.css b/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.css
index c8dfd3a3ea..0aaddaf7ca 100644
--- a/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.css
+++ b/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.css
@@ -13257,6 +13257,13 @@ tobago-select-one-list .list-group .list-group-item.tobago-select-field {
 tobago-select-one-list .dropdown {
   min-width: 0;
 }
+tobago-select-one-list .tobago-select-item-group {
+  font-weight: bold;
+  pointer-events: none;
+}
+tobago-select-one-list .tobago-select-item span {
+  padding-left: 0.75rem;
+}
 tobago-select-one-list .tobago-select-field {
   display: flex;
   flex-wrap: wrap;
@@ -13425,6 +13432,13 @@ tobago-select-many-list .list-group .list-group-item.tobago-select-field {
 tobago-select-many-list .dropdown {
   min-width: 0;
 }
+tobago-select-many-list .tobago-select-item-group {
+  font-weight: bold;
+  pointer-events: none;
+}
+tobago-select-many-list .tobago-select-item span {
+  padding-left: 0.75rem;
+}
 tobago-select-many-list .tobago-select-field {
   display: flex;
   flex-wrap: wrap;
diff --git a/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.css.map b/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.css.map
index 01c616e548..2fe7ecd2ed 100644
--- a/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.css.map
+++ b/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago.css","../scss/tobago-theme.scss","../scss/_custom.scss","../../../../node_modules/bootstrap/scss/mixins/_banner.scss","../../../../node_modules/bootstrap/scss/_root.scss","../../../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../../../node_modules/bootstrap/scss/mixins/_color-mode.scss","../../../../node_modules/bootstrap/scss/_reboot.scss","../../../../node_modules/bootstrap/scss/_variables.scss","../../../../node_modules/bootstrap/scss/mixins/_bo [...]
\ No newline at end of file
+{"version":3,"sources":["tobago.css","../scss/tobago-theme.scss","../scss/_custom.scss","../../../../node_modules/bootstrap/scss/mixins/_banner.scss","../../../../node_modules/bootstrap/scss/_root.scss","../../../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../../../node_modules/bootstrap/scss/mixins/_color-mode.scss","../../../../node_modules/bootstrap/scss/_reboot.scss","../../../../node_modules/bootstrap/scss/_variables.scss","../../../../node_modules/bootstrap/scss/mixins/_bo [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.min.css b/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.min.css
index 58cfc56e8e..bf47b961b5 100644
--- a/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.min.css
+++ b/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.min.css
@@ -1,2 +1,2 @@
-@charset "UTF-8";:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#ff00be;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000000;--bs-white:#ffffff;--bs-gray:#777777;--bs-gray-dark:#323232;--bs-gray-100:#f8f9fa;--bs-gray-200:#d0d0d0;--bs-gray-300:#dee2e6;--bs-gray-400:#a0a0a0;--bs-gray-500:#adb5bd;--bs-gray-600:#777777;--bs-gray-700:#495057;--bs-gray-800:#323232;--bs [...]
+@charset "UTF-8";:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#ff00be;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000000;--bs-white:#ffffff;--bs-gray:#777777;--bs-gray-dark:#323232;--bs-gray-100:#f8f9fa;--bs-gray-200:#d0d0d0;--bs-gray-300:#dee2e6;--bs-gray-400:#a0a0a0;--bs-gray-500:#adb5bd;--bs-gray-600:#777777;--bs-gray-700:#495057;--bs-gray-800:#323232;--bs [...]
 /*# sourceMappingURL=tobago.min.css.map */
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.min.css.map b/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.min.css.map
index cab13a97e5..9bc3d2b379 100644
--- a/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.min.css.map
+++ b/tobago-theme/tobago-theme-charlotteville/src/main/css/tobago.min.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago-theme-charlotteville/src/main/css/tobago.css"],"names":[],"mappings":"iBAsCA,MACA,sBACE,UAAW,QACX,YAAa,QACb,YAAa,QACb,UAAW,QACX,SAAU,QACV,YAAa,QACb,YAAa,QACb,WAAY,QACZ,UAAW,QACX,UAAW,QACX,WAAY,QACZ,WAAY,QACZ,UAAW,QACX,eAAgB,QAChB,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,aAAc,QACd,eAAgB,QAChB,aAAc,QACd,UAAW,QACX,aAAc,QACd,YAAa,QACb,WAAY,QACZ,UAAW,QACX,iBAAkB,EAAE,CAAE,GAAG,CAAE,IAC3B,mBAAoB,GAAG,CAAE,GAAG,CAA [...]
\ No newline at end of file
+{"version":3,"sources":["tobago-theme-charlotteville/src/main/css/tobago.css"],"names":[],"mappings":"iBAsCA,MACA,sBACE,UAAW,QACX,YAAa,QACb,YAAa,QACb,UAAW,QACX,SAAU,QACV,YAAa,QACb,YAAa,QACb,WAAY,QACZ,UAAW,QACX,UAAW,QACX,WAAY,QACZ,WAAY,QACZ,UAAW,QACX,eAAgB,QAChB,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,aAAc,QACd,eAAgB,QAChB,aAAc,QACd,UAAW,QACX,aAAc,QACd,YAAa,QACb,WAAY,QACZ,UAAW,QACX,iBAAkB,EAAE,CAAE,GAAG,CAAE,IAC3B,mBAAoB,GAAG,CAAE,GAAG,CAA [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.css b/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.css
index d90d10b609..90bbca8522 100644
--- a/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.css
+++ b/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.css
@@ -13284,6 +13284,13 @@ tobago-select-one-list .list-group .list-group-item.tobago-select-field {
 tobago-select-one-list .dropdown {
   min-width: 0;
 }
+tobago-select-one-list .tobago-select-item-group {
+  font-weight: bold;
+  pointer-events: none;
+}
+tobago-select-one-list .tobago-select-item span {
+  padding-left: 0.75rem;
+}
 tobago-select-one-list .tobago-select-field {
   display: flex;
   flex-wrap: wrap;
@@ -13452,6 +13459,13 @@ tobago-select-many-list .list-group .list-group-item.tobago-select-field {
 tobago-select-many-list .dropdown {
   min-width: 0;
 }
+tobago-select-many-list .tobago-select-item-group {
+  font-weight: bold;
+  pointer-events: none;
+}
+tobago-select-many-list .tobago-select-item span {
+  padding-left: 0.75rem;
+}
 tobago-select-many-list .tobago-select-field {
   display: flex;
   flex-wrap: wrap;
diff --git a/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.css.map b/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.css.map
index 30803fb291..9d275bdbf2 100644
--- a/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.css.map
+++ b/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago.css","../scss/tobago-theme.scss","../scss/_custom.scss","../../../../node_modules/bootstrap/scss/mixins/_banner.scss","../../../../node_modules/bootstrap/scss/_root.scss","../../../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../../../node_modules/bootstrap/scss/mixins/_color-mode.scss","../../../../node_modules/bootstrap/scss/_reboot.scss","../../../../node_modules/bootstrap/scss/_variables.scss","../../../../node_modules/bootstrap/scss/mixins/_bo [...]
\ No newline at end of file
+{"version":3,"sources":["tobago.css","../scss/tobago-theme.scss","../scss/_custom.scss","../../../../node_modules/bootstrap/scss/mixins/_banner.scss","../../../../node_modules/bootstrap/scss/_root.scss","../../../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../../../node_modules/bootstrap/scss/mixins/_color-mode.scss","../../../../node_modules/bootstrap/scss/_reboot.scss","../../../../node_modules/bootstrap/scss/_variables.scss","../../../../node_modules/bootstrap/scss/mixins/_bo [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.min.css b/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.min.css
index 01139b741b..e7f53b558f 100644
--- a/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.min.css
+++ b/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.min.css
@@ -1,2 +1,2 @@
-@charset "UTF-8";@font-face{font-family:Amaranth;font-style:normal;font-weight:400;src:url("../fonts/Amaranth-Regular.otf") format("opentype")}@font-face{font-family:Amaranth;font-style:normal;font-weight:700;src:url("../fonts/Amaranth-Bold.otf") format("opentype")}@font-face{font-family:Amaranth;font-style:italic;src:url("../fonts/Amaranth-Italic.otf") format("opentype")}@font-face{font-family:Amaranth;font-style:italic;font-weight:700;src:url("../fonts/Amaranth-BoldItalic.otf") format( [...]
+@charset "UTF-8";@font-face{font-family:Amaranth;font-style:normal;font-weight:400;src:url("../fonts/Amaranth-Regular.otf") format("opentype")}@font-face{font-family:Amaranth;font-style:normal;font-weight:700;src:url("../fonts/Amaranth-Bold.otf") format("opentype")}@font-face{font-family:Amaranth;font-style:italic;src:url("../fonts/Amaranth-Italic.otf") format("opentype")}@font-face{font-family:Amaranth;font-style:italic;font-weight:700;src:url("../fonts/Amaranth-BoldItalic.otf") format( [...]
 /*# sourceMappingURL=tobago.min.css.map */
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.min.css.map b/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.min.css.map
index cdb5517748..2b4de53260 100644
--- a/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.min.css.map
+++ b/tobago-theme/tobago-theme-roxborough/src/main/css/tobago.min.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago-theme-roxborough/src/main/css/tobago.css"],"names":[],"mappings":"iBAiCA,WACE,YAAa,SACb,WAAY,OACZ,YAAa,IACb,IAAK,qCAAqC,mBAE5C,WACE,YAAa,SACb,WAAY,OACZ,YAAa,IACb,IAAK,kCAAkC,mBAEzC,WACE,YAAa,SACb,WAAY,OACZ,IAAK,oCAAoC,mBAE3C,WACE,YAAa,SACb,WAAY,OACZ,YAAa,IACb,IAAK,wCAAwC,mBAE/C,mBACE,YAAa,QAAQ,CAAE,KAAK,CAAE,MAQhC,MACA,sBACE,UAAW,QACX,YAAa,QACb,YAAa,QACb,UAAW,QACX,SAAU,QACV,YAAa,QACb,YAAa,QACb,WAAY,QACZ,UAAW,QACX,UAAW,QACX,WAAY,QACZ,WAAY,KACZ,UAAW,QACX,eAA [...]
\ No newline at end of file
+{"version":3,"sources":["tobago-theme-roxborough/src/main/css/tobago.css"],"names":[],"mappings":"iBAiCA,WACE,YAAa,SACb,WAAY,OACZ,YAAa,IACb,IAAK,qCAAqC,mBAE5C,WACE,YAAa,SACb,WAAY,OACZ,YAAa,IACb,IAAK,kCAAkC,mBAEzC,WACE,YAAa,SACb,WAAY,OACZ,IAAK,oCAAoC,mBAE3C,WACE,YAAa,SACb,WAAY,OACZ,YAAa,IACb,IAAK,wCAAwC,mBAE/C,mBACE,YAAa,QAAQ,CAAE,KAAK,CAAE,MAQhC,MACA,sBACE,UAAW,QACX,YAAa,QACb,YAAa,QACb,UAAW,QACX,SAAU,QACV,YAAa,QACb,YAAa,QACb,WAAY,QACZ,UAAW,QACX,UAAW,QACX,WAAY,QACZ,WAAY,KACZ,UAAW,QACX,eAA [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.css b/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.css
index c0e2e77b11..89580967ad 100644
--- a/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.css
+++ b/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.css
@@ -13279,6 +13279,13 @@ tobago-select-one-list .list-group .list-group-item.tobago-select-field {
 tobago-select-one-list .dropdown {
   min-width: 0;
 }
+tobago-select-one-list .tobago-select-item-group {
+  font-weight: bold;
+  pointer-events: none;
+}
+tobago-select-one-list .tobago-select-item span {
+  padding-left: 0.75rem;
+}
 tobago-select-one-list .tobago-select-field {
   display: flex;
   flex-wrap: wrap;
@@ -13449,6 +13456,13 @@ tobago-select-many-list .list-group .list-group-item.tobago-select-field {
 tobago-select-many-list .dropdown {
   min-width: 0;
 }
+tobago-select-many-list .tobago-select-item-group {
+  font-weight: bold;
+  pointer-events: none;
+}
+tobago-select-many-list .tobago-select-item span {
+  padding-left: 0.75rem;
+}
 tobago-select-many-list .tobago-select-field {
   display: flex;
   flex-wrap: wrap;
diff --git a/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.css.map b/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.css.map
index beb2559872..af3324a40f 100644
--- a/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.css.map
+++ b/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago.css","../scss/tobago-theme.scss","../scss/_custom.scss","../../../../node_modules/bootstrap/scss/mixins/_banner.scss","../../../../node_modules/bootstrap/scss/_root.scss","../../../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../../../node_modules/bootstrap/scss/mixins/_color-mode.scss","../../../../node_modules/bootstrap/scss/_reboot.scss","../../../../node_modules/bootstrap/scss/_variables.scss","../../../../node_modules/bootstrap/scss/mixins/_bo [...]
\ No newline at end of file
+{"version":3,"sources":["tobago.css","../scss/tobago-theme.scss","../scss/_custom.scss","../../../../node_modules/bootstrap/scss/mixins/_banner.scss","../../../../node_modules/bootstrap/scss/_root.scss","../../../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../../../node_modules/bootstrap/scss/mixins/_color-mode.scss","../../../../node_modules/bootstrap/scss/_reboot.scss","../../../../node_modules/bootstrap/scss/_variables.scss","../../../../node_modules/bootstrap/scss/mixins/_bo [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.min.css b/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.min.css
index 5bb399cdcc..902bb785ec 100644
--- a/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.min.css
+++ b/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.min.css
@@ -1,2 +1,2 @@
-@charset "UTF-8";:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray- [...]
+@charset "UTF-8";:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray- [...]
 /*# sourceMappingURL=tobago.min.css.map */
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.min.css.map b/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.min.css.map
index ce9b6d0851..872d11a1bf 100644
--- a/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.min.css.map
+++ b/tobago-theme/tobago-theme-scarborough/src/main/css/tobago.min.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago-theme-scarborough/src/main/css/tobago.css"],"names":[],"mappings":"iBAwCA,MACA,sBACE,UAAW,QACX,YAAa,QACb,YAAa,QACb,UAAW,QACX,SAAU,QACV,YAAa,QACb,YAAa,QACb,WAAY,QACZ,UAAW,QACX,UAAW,QACX,WAAY,KACZ,WAAY,KACZ,UAAW,QACX,eAAgB,QAChB,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,aAAc,QACd,eAAgB,QAChB,aAAc,QACd,UAAW,QACX,aAAc,QACd,YAAa,QACb,WAAY,QACZ,UAAW,QACX,iBAAkB,EAAE,CAAE,GAAG,CAAE,IAC3B,mBAAoB,GAAG,CAAE,GAAG,CAAE,I [...]
\ No newline at end of file
+{"version":3,"sources":["tobago-theme-scarborough/src/main/css/tobago.css"],"names":[],"mappings":"iBAwCA,MACA,sBACE,UAAW,QACX,YAAa,QACb,YAAa,QACb,UAAW,QACX,SAAU,QACV,YAAa,QACb,YAAa,QACb,WAAY,QACZ,UAAW,QACX,UAAW,QACX,WAAY,KACZ,WAAY,KACZ,UAAW,QACX,eAAgB,QAChB,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,aAAc,QACd,eAAgB,QAChB,aAAc,QACd,UAAW,QACX,aAAc,QACd,YAAa,QACb,WAAY,QACZ,UAAW,QACX,iBAAkB,EAAE,CAAE,GAAG,CAAE,IAC3B,mBAAoB,GAAG,CAAE,GAAG,CAAE,I [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-speyside/src/main/css/tobago.css b/tobago-theme/tobago-theme-speyside/src/main/css/tobago.css
index 1dc969721d..c5658333c6 100644
--- a/tobago-theme/tobago-theme-speyside/src/main/css/tobago.css
+++ b/tobago-theme/tobago-theme-speyside/src/main/css/tobago.css
@@ -12977,6 +12977,13 @@ tobago-select-one-list .list-group .list-group-item.tobago-select-field {
 tobago-select-one-list .dropdown {
   min-width: 0;
 }
+tobago-select-one-list .tobago-select-item-group {
+  font-weight: bold;
+  pointer-events: none;
+}
+tobago-select-one-list .tobago-select-item span {
+  padding-left: 0.75rem;
+}
 tobago-select-one-list .tobago-select-field {
   display: flex;
   flex-wrap: wrap;
@@ -13145,6 +13152,13 @@ tobago-select-many-list .list-group .list-group-item.tobago-select-field {
 tobago-select-many-list .dropdown {
   min-width: 0;
 }
+tobago-select-many-list .tobago-select-item-group {
+  font-weight: bold;
+  pointer-events: none;
+}
+tobago-select-many-list .tobago-select-item span {
+  padding-left: 0.75rem;
+}
 tobago-select-many-list .tobago-select-field {
   display: flex;
   flex-wrap: wrap;
diff --git a/tobago-theme/tobago-theme-speyside/src/main/css/tobago.css.map b/tobago-theme/tobago-theme-speyside/src/main/css/tobago.css.map
index ad3ee8e51a..776efe10d6 100644
--- a/tobago-theme/tobago-theme-speyside/src/main/css/tobago.css.map
+++ b/tobago-theme/tobago-theme-speyside/src/main/css/tobago.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago.css","../scss/tobago-theme.scss","../scss/_custom.scss","../../../../node_modules/bootstrap/scss/mixins/_banner.scss","../../../../node_modules/bootstrap/scss/_root.scss","../../../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../../../node_modules/bootstrap/scss/mixins/_color-mode.scss","../../../../node_modules/bootstrap/scss/_reboot.scss","../../../../node_modules/bootstrap/scss/_variables.scss","../../../../node_modules/bootstrap/scss/_type.scss [...]
\ No newline at end of file
+{"version":3,"sources":["tobago.css","../scss/tobago-theme.scss","../scss/_custom.scss","../../../../node_modules/bootstrap/scss/mixins/_banner.scss","../../../../node_modules/bootstrap/scss/_root.scss","../../../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../../../node_modules/bootstrap/scss/mixins/_color-mode.scss","../../../../node_modules/bootstrap/scss/_reboot.scss","../../../../node_modules/bootstrap/scss/_variables.scss","../../../../node_modules/bootstrap/scss/_type.scss [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-speyside/src/main/css/tobago.min.css b/tobago-theme/tobago-theme-speyside/src/main/css/tobago.min.css
index 694d9f47fa..91414c62f4 100644
--- a/tobago-theme/tobago-theme-speyside/src/main/css/tobago.min.css
+++ b/tobago-theme/tobago-theme-speyside/src/main/css/tobago.min.css
@@ -1,2 +1,2 @@
-@charset "UTF-8";:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:rgb(58, 37, 100);--bs-pink:#d63384;--bs-red:rgb(211, 0, 64);--bs-orange:#d90;--bs-yellow:#ffc107;--bs-green:rgb(29, 163, 50);--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:rgb(120, 140, 148);--bs-gray-dark:#323232;--bs-gray-100:#f7f7f7;--bs-gray-200:#e3e4e5;--bs-gray-300:#d7d7d7;--bs-gray-400:#ced4da;--bs-gray-500:#acacac;--bs-gray-600:rgb(120, 140, 148);--bs-gray [...]
+@charset "UTF-8";:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:rgb(58, 37, 100);--bs-pink:#d63384;--bs-red:rgb(211, 0, 64);--bs-orange:#d90;--bs-yellow:#ffc107;--bs-green:rgb(29, 163, 50);--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:rgb(120, 140, 148);--bs-gray-dark:#323232;--bs-gray-100:#f7f7f7;--bs-gray-200:#e3e4e5;--bs-gray-300:#d7d7d7;--bs-gray-400:#ced4da;--bs-gray-500:#acacac;--bs-gray-600:rgb(120, 140, 148);--bs-gray [...]
 /*# sourceMappingURL=tobago.min.css.map */
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-speyside/src/main/css/tobago.min.css.map b/tobago-theme/tobago-theme-speyside/src/main/css/tobago.min.css.map
index 46cddff3e3..76438046a0 100644
--- a/tobago-theme/tobago-theme-speyside/src/main/css/tobago.min.css.map
+++ b/tobago-theme/tobago-theme-speyside/src/main/css/tobago.min.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago-theme-speyside/src/main/css/tobago.css"],"names":[],"mappings":"iBAsCA,MACA,sBACE,UAAW,QACX,YAAa,QACb,YAAa,iBACb,UAAW,QACX,SAAU,gBACV,YAAa,KACb,YAAa,QACb,WAAY,iBACZ,UAAW,QACX,UAAW,QACX,WAAY,KACZ,WAAY,KACZ,UAAW,mBACX,eAAgB,QAChB,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,mBACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,aAAc,gBACd,eAAgB,QAChB,aAAc,iBACd,UAAW,QACX,aAAc,QACd,YAAa,gBACb,WAAY,QACZ,UAAW,QACX,iBAAkB,EAAE,CAAE,EAAE,CAAE,GAC1B,mBAAoB,GAAG,CAAE,GAAG,C [...]
\ No newline at end of file
+{"version":3,"sources":["tobago-theme-speyside/src/main/css/tobago.css"],"names":[],"mappings":"iBAsCA,MACA,sBACE,UAAW,QACX,YAAa,QACb,YAAa,iBACb,UAAW,QACX,SAAU,gBACV,YAAa,KACb,YAAa,QACb,WAAY,iBACZ,UAAW,QACX,UAAW,QACX,WAAY,KACZ,WAAY,KACZ,UAAW,mBACX,eAAgB,QAChB,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,mBACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,aAAc,gBACd,eAAgB,QAChB,aAAc,iBACd,UAAW,QACX,aAAc,QACd,YAAa,gBACb,WAAY,QACZ,UAAW,QACX,iBAAkB,EAAE,CAAE,EAAE,CAAE,GAC1B,mBAAoB,GAAG,CAAE,GAAG,C [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/src/main/css/tobago.css b/tobago-theme/tobago-theme-standard/src/main/css/tobago.css
index a7b9e25bac..1a16530ec9 100644
--- a/tobago-theme/tobago-theme-standard/src/main/css/tobago.css
+++ b/tobago-theme/tobago-theme-standard/src/main/css/tobago.css
@@ -13241,6 +13241,13 @@ tobago-select-one-list .list-group .list-group-item.tobago-select-field {
 tobago-select-one-list .dropdown {
   min-width: 0;
 }
+tobago-select-one-list .tobago-select-item-group {
+  font-weight: bold;
+  pointer-events: none;
+}
+tobago-select-one-list .tobago-select-item span {
+  padding-left: 0.75rem;
+}
 tobago-select-one-list .tobago-select-field {
   display: flex;
   flex-wrap: wrap;
@@ -13409,6 +13416,13 @@ tobago-select-many-list .list-group .list-group-item.tobago-select-field {
 tobago-select-many-list .dropdown {
   min-width: 0;
 }
+tobago-select-many-list .tobago-select-item-group {
+  font-weight: bold;
+  pointer-events: none;
+}
+tobago-select-many-list .tobago-select-item span {
+  padding-left: 0.75rem;
+}
 tobago-select-many-list .tobago-select-field {
   display: flex;
   flex-wrap: wrap;
diff --git a/tobago-theme/tobago-theme-standard/src/main/css/tobago.css.map b/tobago-theme/tobago-theme-standard/src/main/css/tobago.css.map
index c3625052e7..2a5b2ce472 100644
--- a/tobago-theme/tobago-theme-standard/src/main/css/tobago.css.map
+++ b/tobago-theme/tobago-theme-standard/src/main/css/tobago.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago.css","../scss/tobago-theme.scss","../../../../node_modules/bootstrap/scss/mixins/_banner.scss","../../../../node_modules/bootstrap/scss/_root.scss","../../../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../../../node_modules/bootstrap/scss/mixins/_color-mode.scss","../../../../node_modules/bootstrap/scss/_reboot.scss","../../../../node_modules/bootstrap/scss/_variables.scss","../../../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../. [...]
\ No newline at end of file
+{"version":3,"sources":["tobago.css","../scss/tobago-theme.scss","../../../../node_modules/bootstrap/scss/mixins/_banner.scss","../../../../node_modules/bootstrap/scss/_root.scss","../../../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../../../node_modules/bootstrap/scss/mixins/_color-mode.scss","../../../../node_modules/bootstrap/scss/_reboot.scss","../../../../node_modules/bootstrap/scss/_variables.scss","../../../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../. [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/src/main/css/tobago.min.css b/tobago-theme/tobago-theme-standard/src/main/css/tobago.min.css
index 39fa797624..121235fe08 100644
--- a/tobago-theme/tobago-theme-standard/src/main/css/tobago.min.css
+++ b/tobago-theme/tobago-theme-standard/src/main/css/tobago.min.css
@@ -1,2 +1,2 @@
-@charset "UTF-8";:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray- [...]
+@charset "UTF-8";:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray- [...]
 /*# sourceMappingURL=tobago.min.css.map */
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/src/main/css/tobago.min.css.map b/tobago-theme/tobago-theme-standard/src/main/css/tobago.min.css.map
index 630edb2b3b..5bf981fa47 100644
--- a/tobago-theme/tobago-theme-standard/src/main/css/tobago.min.css.map
+++ b/tobago-theme/tobago-theme-standard/src/main/css/tobago.min.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago-theme-standard/src/main/css/tobago.css"],"names":[],"mappings":"iBAsBA,MACA,sBACE,UAAW,QACX,YAAa,QACb,YAAa,QACb,UAAW,QACX,SAAU,QACV,YAAa,QACb,YAAa,QACb,WAAY,QACZ,UAAW,QACX,UAAW,QACX,WAAY,KACZ,WAAY,KACZ,UAAW,QACX,eAAgB,QAChB,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,aAAc,QACd,eAAgB,QAChB,aAAc,QACd,UAAW,QACX,aAAc,QACd,YAAa,QACb,WAAY,QACZ,UAAW,QACX,iBAAkB,EAAE,CAAE,GAAG,CAAE,IAC3B,mBAAoB,GAAG,CAAE,GAAG,CAAE,IAC9 [...]
\ No newline at end of file
+{"version":3,"sources":["tobago-theme-standard/src/main/css/tobago.css"],"names":[],"mappings":"iBAsBA,MACA,sBACE,UAAW,QACX,YAAa,QACb,YAAa,QACb,UAAW,QACX,SAAU,QACV,YAAa,QACb,YAAa,QACb,WAAY,QACZ,UAAW,QACX,UAAW,QACX,WAAY,KACZ,WAAY,KACZ,UAAW,QACX,eAAgB,QAChB,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,aAAc,QACd,eAAgB,QAChB,aAAc,QACd,UAAW,QACX,aAAc,QACd,YAAa,QACb,WAAY,QACZ,UAAW,QACX,iBAAkB,EAAE,CAAE,GAAG,CAAE,IAC3B,mBAAoB,GAAG,CAAE,GAAG,CAAE,IAC9 [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/src/main/js/tobago.js b/tobago-theme/tobago-theme-standard/src/main/js/tobago.js
index ef609963a7..8f0c7ae17d 100644
--- a/tobago-theme/tobago-theme-standard/src/main/js/tobago.js
+++ b/tobago-theme/tobago-theme-standard/src/main/js/tobago.js
@@ -4,7 +4,7 @@
       * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
       * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
       */
-const $e=new Map,Me={set(e,t,s){$e.has(e)||$e.set(e,new Map);const n=$e.get(e);n.has(t)||0===n.size?n.set(t,s):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(n.keys())[0]}.`)},get:(e,t)=>$e.has(e)&&$e.get(e).get(t)||null,remove(e,t){if(!$e.has(e))return;const s=$e.get(e);s.delete(t),0===s.size&&$e.delete(e)}},Pe="transitionend",Be=e=>(e&&window.CSS&&window.CSS.escape&&(e=e.replace(/#([^\s"#']+)/g,((e,t)=>`#${CSS.escape(t)}`))),e),H [...]
+const $e=new Map,Me={set(e,t,s){$e.has(e)||$e.set(e,new Map);const n=$e.get(e);n.has(t)||0===n.size?n.set(t,s):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(n.keys())[0]}.`)},get:(e,t)=>$e.has(e)&&$e.get(e).get(t)||null,remove(e,t){if(!$e.has(e))return;const s=$e.get(e);s.delete(t),0===s.size&&$e.delete(e)}},Pe="transitionend",Be=e=>(e&&window.CSS&&window.CSS.escape&&(e=e.replace(/#([^\s"#']+)/g,((e,t)=>`#${CSS.escape(t)}`))),e),H [...]
 /**
      * @license
      * Copyright 2017 Google LLC
diff --git a/tobago-theme/tobago-theme-standard/src/main/js/tobago.js.map b/tobago-theme/tobago-theme-standard/src/main/js/tobago.js.map
index f8690b5e4f..7d65b9a144 100644
--- a/tobago-theme/tobago-theme-standard/src/main/js/tobago.js.map
+++ b/tobago-theme/tobago-theme-standard/src/main/js/tobago.js.map
@@ -1 +1 @@
-{"version":3,"file":"tobago.js","sources":["../ts/tobago-css.ts","../ts/tobago-bar.ts","../../../../node_modules/@popperjs/core/lib/enums.js","../../../../node_modules/@popperjs/core/lib/dom-utils/getNodeName.js","../../../../node_modules/@popperjs/core/lib/dom-utils/getWindow.js","../../../../node_modules/@popperjs/core/lib/dom-utils/instanceOf.js","../../../../node_modules/@popperjs/core/lib/modifiers/applyStyles.js","../../../../node_modules/@popperjs/core/lib/utils/getBasePlacement.j [...]
\ No newline at end of file
+{"version":3,"file":"tobago.js","sources":["../ts/tobago-css.ts","../ts/tobago-bar.ts","../../../../node_modules/@popperjs/core/lib/enums.js","../../../../node_modules/@popperjs/core/lib/dom-utils/getNodeName.js","../../../../node_modules/@popperjs/core/lib/dom-utils/getWindow.js","../../../../node_modules/@popperjs/core/lib/dom-utils/instanceOf.js","../../../../node_modules/@popperjs/core/lib/modifiers/applyStyles.js","../../../../node_modules/@popperjs/core/lib/utils/getBasePlacement.j [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/src/main/ts/tobago-select-list-base.ts b/tobago-theme/tobago-theme-standard/src/main/ts/tobago-select-list-base.ts
index 20ab4f6ce3..98c780804d 100644
--- a/tobago-theme/tobago-theme-standard/src/main/ts/tobago-select-list-base.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/ts/tobago-select-list-base.ts
@@ -80,7 +80,7 @@ export abstract class SelectListBase extends HTMLElement {
   }
 
   get enabledRows(): NodeListOf<HTMLTableRowElement> {
-    return this.tbody.querySelectorAll<HTMLTableRowElement>("tr:not(." + Css.D_NONE + ")");
+    return this.tbody.querySelectorAll<HTMLTableRowElement>("tr:not(." + Css.D_NONE + "):not(." + Css.DISABLED);
   }
 
   get preselectedRow(): HTMLTableRowElement {