You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lo...@apache.org on 2020/10/23 18:39:31 UTC

[myfaces-tobago] 05/13: TOBAGO-1633: Use TypeScript instead of JavaScript. Simplify Renderers: remove "inside" new tag tobago-buttons

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

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

commit 10a7ab7a08265185e29503abf8296349a1dd813d
Author: Udo Schnurpfeil <ud...@irian.eu>
AuthorDate: Fri Oct 23 08:49:54 2020 +0200

    TOBAGO-1633: Use TypeScript instead of JavaScript.
    Simplify Renderers: remove "inside"
    new tag tobago-buttons
---
 tobago-core/npm/scss/_tobago.scss                  |  3 +
 .../myfaces/tobago/component/RendererTypes.java    |  2 -
 .../renderer/ButtonInsideButtonsRenderer.java      | 34 ----------
 .../renderkit/renderer/ButtonsRenderer.java        | 12 ++--
 .../renderkit/renderer/CommandRendererBase.java    |  5 +-
 .../taglib/component/ButtonTagDeclaration.java     |  2 +-
 .../taglib/component/LinkTagDeclaration.java       |  2 +-
 .../tobago/renderkit/html/HtmlElements.java        |  1 +
 .../internal/config/AbstractTobagoTestBase.java    |  8 +++
 .../renderer/ButtonsRendererUnitTest.java          | 72 ++++++++++++++++++++++
 .../renderer/buttons/separator-inside-buttons.html | 41 ++++++++++++
 .../renderer/links/link-inside-links-sub.html      |  3 +
 .../040-command/20-buttons/Button_Group.xhtml      |  4 ++
 .../npm/dist/css/tobago.css                        |  2 +-
 .../tobago-theme-standard/npm/dist/css/tobago.css  |  2 +-
 .../npm/dist/css/tobago.css.map                    |  2 +-
 .../npm/dist/css/tobago.min.css                    |  2 +-
 .../npm/dist/css/tobago.min.css.map                |  2 +-
 18 files changed, 144 insertions(+), 55 deletions(-)

diff --git a/tobago-core/npm/scss/_tobago.scss b/tobago-core/npm/scss/_tobago.scss
index d0b070a..c8c1d5d 100644
--- a/tobago-core/npm/scss/_tobago.scss
+++ b/tobago-core/npm/scss/_tobago.scss
@@ -124,6 +124,9 @@ tobago-behavior {
 
 /* buttons, links ------------------------------------------------------- */
 .tobago-buttons {
+}
+
+tobago-buttons {
   > .tobago-button {
     display: inline-block;
   }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/component/RendererTypes.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/component/RendererTypes.java
index f97e451..98d94c1 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/component/RendererTypes.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/component/RendererTypes.java
@@ -29,7 +29,6 @@ public enum RendererTypes {
   Bar,
   Box,
   Button,
-  ButtonInsideButtons,
   ButtonInsideIn,
   ButtonInsideInAfter,
   Buttons,
@@ -113,7 +112,6 @@ public enum RendererTypes {
   public static final String BAR = "Bar";
   public static final String BOX = "Box";
   public static final String BUTTON = "Button";
-  public static final String BUTTON_INSIDE_BUTTONS = "ButtonInsideButtons";
   public static final String BUTTON_INSIDE_IN = "ButtonInsideIn";
   public static final String BUTTON_INSIDE_IN_AFTER = "ButtonInsideInAfter";
   public static final String BUTTONS = "Buttons";
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonInsideButtonsRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonInsideButtonsRenderer.java
deleted file mode 100644
index 42c8799..0000000
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonInsideButtonsRenderer.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.renderkit.renderer;
-
-import org.apache.myfaces.tobago.internal.component.AbstractUIButton;
-import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
-import org.apache.myfaces.tobago.renderkit.css.CssItem;
-
-import javax.faces.context.FacesContext;
-
-public class ButtonInsideButtonsRenderer<T extends AbstractUIButton> extends ButtonRenderer<T> {
-
-  @Override
-  protected CssItem[] getOuterCssItems(final FacesContext facesContext, final T command) {
-    return new CssItem[]{BootstrapClass.BTN_GROUP};
-  }
-}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonsRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonsRenderer.java
index ca5fc40..7e66b0a 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonsRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonsRenderer.java
@@ -22,7 +22,6 @@ package org.apache.myfaces.tobago.internal.renderkit.renderer;
 import org.apache.myfaces.tobago.component.RendererTypes;
 import org.apache.myfaces.tobago.context.Markup;
 import org.apache.myfaces.tobago.internal.component.AbstractUIBadge;
-import org.apache.myfaces.tobago.internal.component.AbstractUIButton;
 import org.apache.myfaces.tobago.internal.component.AbstractUIButtons;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
 import org.apache.myfaces.tobago.layout.Orientation;
@@ -46,11 +45,11 @@ public class ButtonsRenderer<T extends AbstractUIButtons> extends RendererBase<T
     final Markup markup = component.getMarkup();
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
 
-    writer.startElement(HtmlElements.DIV);
+    writer.startElement(HtmlElements.TOBAGO_BUTTONS);
     writer.writeIdAttribute(component.getClientId(facesContext));
 
     writer.writeClassAttribute(
-        TobagoClass.BUTTONS,
+        null,
         TobagoClass.BUTTONS.createMarkup(markup),
         Orientation.vertical.equals(component.getOrientation())
             ? BootstrapClass.BTN_GROUP_VERTICAL : BootstrapClass.BTN_GROUP,
@@ -72,10 +71,7 @@ public class ButtonsRenderer<T extends AbstractUIButtons> extends RendererBase<T
   public void encodeChildrenInternal(final FacesContext facesContext, final T component) throws IOException {
     for (final UIComponent child : component.getChildren()) {
       if (child.isRendered()) {
-        if (child instanceof AbstractUIButton) {
-          child.setRendererType(RendererTypes.ButtonInsideButtons.name());
-          child.encodeAll(facesContext);
-        } else if (child instanceof AbstractUIBadge) {
+        if (child instanceof AbstractUIBadge) {
           child.setRendererType(RendererTypes.BadgeInsideButtons.name());
           child.encodeAll(facesContext);
         } else {
@@ -88,6 +84,6 @@ public class ButtonsRenderer<T extends AbstractUIButtons> extends RendererBase<T
   @Override
   public void encodeEndInternal(final FacesContext facesContext, final T component) throws IOException {
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
-    writer.endElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.TOBAGO_BUTTONS);
   }
 }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
index 38c5f4b..993588c 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
@@ -233,7 +233,6 @@ public abstract class CommandRendererBase<T extends AbstractUICommand> extends D
     final String clientId = command.getClientId(facesContext);
     final boolean parentOfCommands = command.isParentOfCommands();
     final boolean dropdownSubmenu = this instanceof LinkInsideCommandRenderer;
-    final boolean childOfButtonGroup = this instanceof ButtonInsideButtonsRenderer;
 
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
 
@@ -242,9 +241,7 @@ public abstract class CommandRendererBase<T extends AbstractUICommand> extends D
       writer.writeIdAttribute(clientId);
 
       final CssItem first;
-      if (childOfButtonGroup) {
-        first = null;
-      } else if (dropdownSubmenu) {
+      if (dropdownSubmenu) {
         first = TobagoClass.DROPDOWN__SUBMENU;
       } else {
         first = BootstrapClass.DROPDOWN;
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ButtonTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ButtonTagDeclaration.java
index 7028a89..2a3057b 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ButtonTagDeclaration.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ButtonTagDeclaration.java
@@ -62,7 +62,7 @@ import javax.faces.component.UICommand;
         "org.apache.myfaces.tobago.component.SupportsAccessKey"
     },
     componentFamily = UICommand.COMPONENT_FAMILY,
-    rendererType = {RendererTypes.BUTTON, RendererTypes.BUTTON_INSIDE_BUTTONS, RendererTypes.BUTTON_INSIDE_IN,
+    rendererType = {RendererTypes.BUTTON, RendererTypes.BUTTON_INSIDE_IN,
         RendererTypes.BUTTON_INSIDE_IN_AFTER},
     allowedChildComponenents = "NONE",
     facets = {
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LinkTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LinkTagDeclaration.java
index a7a0413..e96be42 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LinkTagDeclaration.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LinkTagDeclaration.java
@@ -59,7 +59,7 @@ import javax.faces.component.UICommand;
     uiComponentFacesClass = "javax.faces.component.UICommand",
     interfaces = "org.apache.myfaces.tobago.component.SupportsAccessKey",
     componentFamily = UICommand.COMPONENT_FAMILY,
-    rendererType = {RendererTypes.LINK, RendererTypes.LINK_INSIDE_COMMAND, RendererTypes.LINK_INSIDE_LINKS},
+    rendererType = {RendererTypes.LINK, RendererTypes.LINK_INSIDE_COMMAND},
     allowedChildComponenents = "NONE",
     facets = {
         @Facet(
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java
index e60f251..6eb610a 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java
@@ -135,6 +135,7 @@ public enum HtmlElements {
 
   TOBAGO_BAR("tobago-bar"),
   TOBAGO_BEHAVIOR("tobago-behavior"),
+  TOBAGO_BUTTONS("tobago-buttons"),
   TOBAGO_DATE("tobago-date"),
   TOBAGO_DROPDOWN("tobago-dropdown"),
   TOBAGO_FILE("tobago-file"),
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/AbstractTobagoTestBase.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/AbstractTobagoTestBase.java
index fbb0d5f..a81ae08 100644
--- a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/AbstractTobagoTestBase.java
+++ b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/AbstractTobagoTestBase.java
@@ -35,18 +35,22 @@ import org.apache.myfaces.tobago.component.UIOut;
 import org.apache.myfaces.tobago.component.UIPanel;
 import org.apache.myfaces.tobago.component.UIPopup;
 import org.apache.myfaces.tobago.component.UISegmentLayout;
+import org.apache.myfaces.tobago.component.UISeparator;
 import org.apache.myfaces.tobago.component.UIStyle;
 import org.apache.myfaces.tobago.context.TobagoContext;
 import org.apache.myfaces.tobago.internal.renderkit.renderer.ButtonRenderer;
 import org.apache.myfaces.tobago.internal.renderkit.renderer.ButtonsRenderer;
 import org.apache.myfaces.tobago.internal.renderkit.renderer.GridLayoutRenderer;
 import org.apache.myfaces.tobago.internal.renderkit.renderer.InRenderer;
+import org.apache.myfaces.tobago.internal.renderkit.renderer.LinkInsideCommandRenderer;
 import org.apache.myfaces.tobago.internal.renderkit.renderer.LinkRenderer;
 import org.apache.myfaces.tobago.internal.renderkit.renderer.LinksRenderer;
 import org.apache.myfaces.tobago.internal.renderkit.renderer.OutRenderer;
 import org.apache.myfaces.tobago.internal.renderkit.renderer.PanelRenderer;
 import org.apache.myfaces.tobago.internal.renderkit.renderer.PopupRenderer;
 import org.apache.myfaces.tobago.internal.renderkit.renderer.SegmentLayoutRenderer;
+import org.apache.myfaces.tobago.internal.renderkit.renderer.SeparatorInsideCommandRenderer;
+import org.apache.myfaces.tobago.internal.renderkit.renderer.SeparatorRenderer;
 import org.apache.myfaces.tobago.internal.renderkit.renderer.StyleRenderer;
 import org.apache.myfaces.tobago.internal.webapp.HtmlResponseWriter;
 import org.junit.jupiter.api.AfterEach;
@@ -108,6 +112,7 @@ public abstract class AbstractTobagoTestBase extends AbstractJsfTestCase {
     application.addComponent(Tags.button.componentType(), UIButton.class.getName());
     application.addComponent(Tags.buttons.componentType(), UIButtons.class.getName());
     application.addComponent(Tags.popup.componentType(), UIPopup.class.getName());
+    application.addComponent(Tags.separator.componentType(), UISeparator.class.getName());
     application.addComponent(Tags.style.componentType(), UIStyle.class.getName());
     application.addComponent(Tags.gridLayout.componentType(), UIGridLayout.class.getName());
     application.addComponent(Tags.segmentLayout.componentType(), UISegmentLayout.class.getName());
@@ -117,10 +122,13 @@ public abstract class AbstractTobagoTestBase extends AbstractJsfTestCase {
     renderKit.addRenderer(UIOut.COMPONENT_FAMILY, RendererTypes.OUT, new OutRenderer());
     renderKit.addRenderer(UIPanel.COMPONENT_FAMILY, RendererTypes.PANEL, new PanelRenderer());
     renderKit.addRenderer(UILink.COMPONENT_FAMILY, RendererTypes.LINK, new LinkRenderer());
+    renderKit.addRenderer(UILink.COMPONENT_FAMILY, RendererTypes.LINK_INSIDE_COMMAND, new LinkInsideCommandRenderer());
     renderKit.addRenderer(UILinks.COMPONENT_FAMILY, RendererTypes.LINKS, new LinksRenderer());
     renderKit.addRenderer(UIButton.COMPONENT_FAMILY, RendererTypes.BUTTON, new ButtonRenderer());
     renderKit.addRenderer(UIButtons.COMPONENT_FAMILY, RendererTypes.BUTTONS, new ButtonsRenderer());
     renderKit.addRenderer(UIPopup.COMPONENT_FAMILY, RendererTypes.POPUP, new PopupRenderer());
+    renderKit.addRenderer(UISeparator.COMPONENT_FAMILY, RendererTypes.SEPARATOR, new SeparatorRenderer());
+    renderKit.addRenderer(UISeparator.COMPONENT_FAMILY, RendererTypes.SEPARATOR_INSIDE_COMMAND, new SeparatorInsideCommandRenderer());
     renderKit.addRenderer(UIStyle.COMPONENT_FAMILY, RendererTypes.STYLE, new StyleRenderer());
     renderKit.addRenderer(UIGridLayout.COMPONENT_FAMILY, RendererTypes.GRID_LAYOUT, new GridLayoutRenderer());
     renderKit.addRenderer(UISegmentLayout.COMPONENT_FAMILY, RendererTypes.SEGMENT_LAYOUT, new SegmentLayoutRenderer());
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonsRendererUnitTest.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonsRendererUnitTest.java
new file mode 100644
index 0000000..0663751
--- /dev/null
+++ b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonsRendererUnitTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.component.Tags;
+import org.apache.myfaces.tobago.component.UIButton;
+import org.apache.myfaces.tobago.component.UIButtons;
+import org.apache.myfaces.tobago.component.UILink;
+import org.apache.myfaces.tobago.component.UISeparator;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+public class ButtonsRendererUnitTest extends RendererTestBase {
+
+  @Test
+  public void separatorInsideButtons() throws IOException {
+    final UIButtons l = (UIButtons) ComponentUtils.createComponent(
+        facesContext, Tags.buttons.componentType(), RendererTypes.Buttons, "list");
+    final UIButton c = (UIButton) ComponentUtils.createComponent(
+        facesContext, Tags.button.componentType(), RendererTypes.Button, "id");
+    c.setLabel("button");
+    l.getChildren().add(c);
+
+    final UILink sub1 = (UILink) ComponentUtils.createComponent(
+        facesContext, Tags.link.componentType(), RendererTypes.Link, "sub1");
+    sub1.setLabel("sub1");
+    final UISeparator separator1 = (UISeparator) ComponentUtils.createComponent(
+        facesContext, Tags.separator.componentType(), RendererTypes.Separator, "separator1");
+    final UILink sub2 = (UILink) ComponentUtils.createComponent(
+        facesContext, Tags.link.componentType(), RendererTypes.Link, "sub2");
+    sub2.setLabel("sub2");
+    final UISeparator separator2 = (UISeparator) ComponentUtils.createComponent(
+        facesContext, Tags.separator.componentType(), RendererTypes.Separator, "separator2");
+    final UILink sub3 = (UILink) ComponentUtils.createComponent(
+        facesContext, Tags.link.componentType(), RendererTypes.Link, "sub3");
+    sub3.setLabel("sub3");
+
+    c.getChildren().add(sub1);
+    c.getChildren().add(separator1);
+    c.getChildren().add(sub2);
+    c.getChildren().add(separator2);
+    c.getChildren().add(sub3);
+
+    l.getChildren().add(c);
+
+    l.encodeAll(facesContext);
+
+    Assert.assertEquals(loadHtml("renderer/buttons/separator-inside-buttons.html"), formattedResult());
+  }
+
+}
diff --git a/tobago-core/src/test/resources/renderer/buttons/separator-inside-buttons.html b/tobago-core/src/test/resources/renderer/buttons/separator-inside-buttons.html
new file mode 100644
index 0000000..2835d4d
--- /dev/null
+++ b/tobago-core/src/test/resources/renderer/buttons/separator-inside-buttons.html
@@ -0,0 +1,41 @@
+<!--
+ * 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.
+-->
+<!--
+CSS class of "tobago-dropdown" has changed from btn-group to dropdown
+-->
+<tobago-buttons id='list' class='btn-group' role='group'>
+  <tobago-dropdown id='id' class='dropdown'>
+    <button type='button' id='id::command' name='id' data-toggle='dropdown' class='tobago-button btn btn-secondary dropdown-toggle'>
+      <tobago-behavior event='click' decoupled='decoupled'>
+      </tobago-behavior><span>button</span></button>
+    <div class='dropdown-menu' aria-labelledby='id::command' name='id'>
+      <button type='button' id='sub1' name='sub1' class='tobago-link dropdown-item'>
+        <tobago-behavior event='click' decoupled='decoupled'>
+        </tobago-behavior><span>sub1</span></button>
+      <div id='separator1' class='tobago-separator dropdown-divider'>
+      </div>
+      <button type='button' id='sub2' name='sub2' class='tobago-link dropdown-item'>
+        <tobago-behavior event='click' decoupled='decoupled'>
+        </tobago-behavior><span>sub2</span></button>
+      <div id='separator2' class='tobago-separator dropdown-divider'>
+      </div>
+      <button type='button' id='sub3' name='sub3' class='tobago-link dropdown-item'>
+        <tobago-behavior event='click' decoupled='decoupled'>
+        </tobago-behavior><span>sub3</span></button>
+    </div>
+  </tobago-dropdown>
+</tobago-buttons>
\ No newline at end of file
diff --git a/tobago-core/src/test/resources/renderer/links/link-inside-links-sub.html b/tobago-core/src/test/resources/renderer/links/link-inside-links-sub.html
index fc95c8e..ad2a0f2 100644
--- a/tobago-core/src/test/resources/renderer/links/link-inside-links-sub.html
+++ b/tobago-core/src/test/resources/renderer/links/link-inside-links-sub.html
@@ -25,6 +25,9 @@ CSS class nav-item has moved from "tobago-dropdown" to "li"
           <tobago-behavior event='click' decoupled='decoupled'>
           </tobago-behavior><span>apache</span></button>
         <div class='dropdown-menu' aria-labelledby='id::command' name='id'>
+          <a id='sub' name='sub' href='https://www.apache.org/' class='tobago-link dropdown-item nav-link'>
+            <tobago-behavior event='click' omit='omit' decoupled='decoupled'>
+            </tobago-behavior><span>sub</span></a>
         </div>
       </tobago-dropdown>
     </li>
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/20-buttons/Button_Group.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/20-buttons/Button_Group.xhtml
index 97a9742..e6e0023 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/20-buttons/Button_Group.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/20-buttons/Button_Group.xhtml
@@ -63,6 +63,8 @@
   &lt;tc:button label="Dropdown" omit="true">
     &lt;tc:link label="Action 1"/>
     ...
+    &lt;tc:separator/>
+    &lt;tc:link label="Other Action"/>
   &lt;/tc:button>
   &lt;tc:button label="Center"/>
   &lt;tc:button label="Right"/>
@@ -75,6 +77,8 @@
           <tc:link label="Action 3.1"/>
           <tc:link label="Action 3.2"/>
         </tc:link>
+        <tc:separator/>
+        <tc:link label="Other Action"/>
       </tc:button>
       <tc:button label="Center"/>
       <tc:button label="Right"/>
diff --git a/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.css b/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.css
index 62537d5..e61740a 100644
--- a/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.css
+++ b/tobago-theme/tobago-theme-charlotteville/npm/dist/css/tobago.css
@@ -10295,7 +10295,7 @@ tobago-behavior {
 }
 
 /* buttons, links ------------------------------------------------------- */
-.tobago-buttons > .tobago-button {
+tobago-buttons > .tobago-button {
   display: inline-block;
 }
 
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css
index 271e99a..551cc50 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css
+++ b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css
@@ -10274,7 +10274,7 @@ tobago-behavior {
 }
 
 /* buttons, links ------------------------------------------------------- */
-.tobago-buttons > .tobago-button {
+tobago-buttons > .tobago-button {
   display: inline-block;
 }
 
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css.map b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css.map
index 54d621e..9bb6711 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css.map
+++ b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.css.map
@@ -1 +1 @@
-{"version":3,"sources":["tobago.css","../../scss/tobago-theme.scss","../../node_modules/bootstrap/scss/bootstrap.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","../../node_modules/bootstrap/scss/_variables.scss","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../ [...]
\ No newline at end of file
+{"version":3,"sources":["tobago.css","../../scss/tobago-theme.scss","../../node_modules/bootstrap/scss/bootstrap.scss","../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","../../node_modules/bootstrap/scss/_variables.scss","../../node_modules/bootstrap/scss/vendor/_rfs.scss","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../ [...]
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css
index 0429ef6..e42eb67 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css
+++ b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css
@@ -1,2 +1,2 @@
-@charset "UTF-8";:root{--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-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#343a40;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto, [...]
+@charset "UTF-8";:root{--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-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#343a40;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto, [...]
 /*# sourceMappingURL=tobago.min.css.map */
\ No newline at end of file
diff --git a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css.map b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css.map
index b69ae40..6011a50 100644
--- a/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css.map
+++ b/tobago-theme/tobago-theme-standard/npm/dist/css/tobago.min.css.map
@@ -1 +1 @@
-{"version":3,"sources":["../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","dist/css/tobago.css","../../node_modules/bootstrap/scss/vendor/_rfs.scss","tobago.css","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.scss","../../node_modules/bootstrap/scss/mixins/_image.scss","../../node_mod [...]
\ No newline at end of file
+{"version":3,"sources":["../../node_modules/bootstrap/scss/_root.scss","../../node_modules/bootstrap/scss/_reboot.scss","dist/css/tobago.css","../../node_modules/bootstrap/scss/vendor/_rfs.scss","tobago.css","../../node_modules/bootstrap/scss/mixins/_border-radius.scss","../../node_modules/bootstrap/scss/_type.scss","../../node_modules/bootstrap/scss/mixins/_lists.scss","../../node_modules/bootstrap/scss/_images.scss","../../node_modules/bootstrap/scss/mixins/_image.scss","../../node_mod [...]
\ No newline at end of file