diff --git a/packages/main/src/Tab.hbs b/packages/main/src/Tab.hbs index 50eb4be3dad5..585351c89b8b 100644 --- a/packages/main/src/Tab.hbs +++ b/packages/main/src/Tab.hbs @@ -1,3 +1,7 @@
- + + + {{#each tabs}} + + {{/each}}
diff --git a/packages/main/src/Tab.js b/packages/main/src/Tab.js index a4da30a7c5ed..1c11f0eb788a 100644 --- a/packages/main/src/Tab.js +++ b/packages/main/src/Tab.js @@ -21,16 +21,42 @@ import overflowCss from "./generated/themes/TabInOverflow.css.js"; */ const metadata = { tag: "ui5-tab", + managedSlots: true, + languageAware: true, slots: /** @lends sap.ui.webcomponents.main.Tab.prototype */ { /** - * Defines the tab content. + * Holds the content associated with this tab. + * * @type {Node[]} - * @slot * @public + * @slot */ "default": { type: Node, + propertyName: "content", + invalidateOnChildChange: { + properties: true, + slots: false, + }, + }, + + /** + * Defines hierarchies with nested sub tabs. + *

+ * Note: Use ui5-tab and ui5-tab-separator for the intended design. + * + * @type {sap.ui.webcomponents.main.ITab[]} + * @public + * @slot subTabs + */ + subTabs: { + type: HTMLElement, + individualSlots: true, + invalidateOnChildChange: { + properties: true, + slots: false, + }, }, }, properties: /** @lends sap.ui.webcomponents.main.Tab.prototype */ { @@ -122,6 +148,14 @@ const metadata = { _selected: { type: Boolean, }, + + _realTab: { + type: Object, + }, + + _isTopLevelTab: { + type: Boolean, + }, }, events: /** @lends sap.ui.webcomponents.main.Tab.prototype */ { }, @@ -199,6 +233,31 @@ class Tab extends UI5Element { return this.getAttribute("stable-dom-ref") || `${this._id}-stable-dom-ref`; } + get requiresExpandButton() { + return this.subTabs.length > 0 && this._isTopLevelTab && this._hasOwnContent; + } + + get isSingleClickArea() { + return this.subTabs.length > 0 && this._isTopLevelTab && !this._hasOwnContent; + } + + get isOnSelectedTabPath() { + return this._realTab === this || this.tabs.some(subTab => subTab.isOnSelectedTabPath); + } + + get _effectiveSlotName() { + return this.isOnSelectedTabPath ? this._individualSlot : "disabled-slot"; + } + + get _defaultSlotName() { + return this._realTab === this ? "" : "disabled-slot"; + } + + get _hasOwnContent() { + return this.content.some(node => (node.nodeType !== Node.COMMENT_NODE + && (node.nodeType !== Node.TEXT_NODE || node.nodeValue.trim().length !== 0))); + } + /** * Returns the DOM reference of the tab that is placed in the header. * Note: If you need a DOM ref to the tab content please use the getDomRef method. @@ -238,13 +297,18 @@ class Tab extends UI5Element { } get effectiveSelected() { - return this.selected || this._selected; + const subItemSelected = this.tabs.some(elem => elem.effectiveSelected); + return this.selected || this._selected || subItemSelected; } get effectiveHidden() { return !this.effectiveSelected; } + get tabs() { + return this.subTabs.filter(tab => !tab.isSeparator); + } + get ariaLabelledBy() { const labels = []; @@ -298,6 +362,10 @@ class Tab extends UI5Element { classes.push(`ui5-tab-strip-item--${this.design.toLowerCase()}`); } + if (this.isSingleClickArea) { + classes.push(`ui5-tab-strip-item--singleClickArea`); + } + return classes.join(" "); } @@ -322,11 +390,15 @@ class Tab extends UI5Element { classes.push("ui5-tab-overflow-item--disabled"); } + if (this.selected) { + classes.push("ui5-tab-overflow-item--selectedSubTab"); + } + return classes.join(" "); } get overflowState() { - return this.disabled ? "Inactive" : "Active"; + return (this.disabled || this.isSingleClickArea) ? "Inactive" : "Active"; } } diff --git a/packages/main/src/TabContainer.hbs b/packages/main/src/TabContainer.hbs index 3e258455c7a7..cad3aa03c046 100644 --- a/packages/main/src/TabContainer.hbs +++ b/packages/main/src/TabContainer.hbs @@ -66,18 +66,16 @@ {{#*inline "contentArea"}}
- {{#each items}} - {{#unless this.isSeparator}} -
- -
- {{/unless}} - {{/each}} +
+ {{#each items}} + + {{/each}} +
{{/inline}} diff --git a/packages/main/src/TabContainer.js b/packages/main/src/TabContainer.js index f0dca43cc9b2..fc31757fd6a9 100644 --- a/packages/main/src/TabContainer.js +++ b/packages/main/src/TabContainer.js @@ -257,6 +257,11 @@ const metadata = { type: Object, multiple: true, }, + + _overflowItems: { + type: Object, + multiple: true, + }, }, events: /** @lends sap.ui.webcomponents.main.TabContainer.prototype */ { @@ -291,9 +296,14 @@ const metadata = { * The ui5-tabcontainer can hold two types of entities: * * + *

Hierarchies

+ * Multiple sub tabs could be placed underneath one main tab. Nesting allows deeper hierarchies with indentations + * to indicate the level of each nested tab. When a tab has both sub tabs and own content its click area is split + * to allow the user to display the content or alternatively to expand / collapse the list of sub tabs. + * *

CSS Shadow Parts

* * CSS Shadow Parts allow developers to style elements inside the Shadow DOM. @@ -373,29 +383,18 @@ class TabContainer extends UI5Element { onBeforeRendering() { // update selected tab - const tabs = this._getTabs(); - if (tabs.length) { - const selectedTabs = tabs.filter(tab => tab.selected); + this._allItemsAndSubItems = this._getAllSubItems(this.items, []); + if (this._allItemsAndSubItems.length) { + const selectedTabs = this._allItemsAndSubItems.filter(tab => tab.selected); if (selectedTabs.length) { this._selectedTab = selectedTabs[0]; } else { - this._selectedTab = tabs[0]; + this._selectedTab = this._allItemsAndSubItems[0]; this._selectedTab._selected = true; } } - // Set external properties to items - this.items.filter(item => !item.isSeparator).forEach((item, index, arr) => { - item._isInline = this.tabLayout === TabLayout.Inline; - item._mixedMode = this.mixedMode; - item._posinset = index + 1; - item._setsize = arr.length; - item._getTabContainerHeaderItemCallback = _ => { - return this.getDomRef().querySelector(`#${item._id}`); - }; - item._itemSelectCallback = this._onItemSelect.bind(this); - item._getRealDomRef = () => this.getDomRef().querySelector(`*[data-ui5-stable=${item.stableDomRef}]`); - }); + this._setItemsExternalProperties(this.items); if (!this._animationRunning) { this._contentCollapsed = this.collapsed; @@ -420,15 +419,94 @@ class TabContainer extends UI5Element { ResizeHandler.deregister(this._getHeader(), this._handleResize); } - _onTabStripClick(event) { + _setItemsExternalProperties(items) { + items.filter(item => !item.isSeparator).forEach((item, index, arr) => { + item._isInline = this.tabLayout === TabLayout.Inline; + item._mixedMode = this.mixedMode; + item._posinset = index + 1; + item._setsize = arr.length; + item._getTabContainerHeaderItemCallback = _ => this.getDomRef().querySelector(`#${item._id}`); + item._itemSelectCallback = this._onItemSelect.bind(this); + item._getRealDomRef = () => this.getDomRef().querySelector(`*[data-ui5-stable=${item.stableDomRef}]`); + item._realTab = this._selectedTab; + item._isTopLevelTab = this.items.some(i => i === item); + walk(items, tab => { + tab._realTab = item._realTab; + }); + }); + } + + async _onTabStripClick(event) { const tab = getTab(event.target); if (!tab) { return; } + event.preventDefault(); + event.stopPropagation(); + if (event.target.hasAttribute("ui5-button")) { + this._onTabExpandButtonClick(event); + return; + } + + if (!tab._realTab._hasOwnContent && tab._realTab.tabs.length) { + this._overflowItems = []; + this._overflowItems = tab._realTab.subTabs; + this._addStyleIndent(this._overflowItems, false); + + this.responsivePopover = await this._respPopover(); + if (this.responsivePopover.opened) { + this.responsivePopover.close(); + } else { + this._setInitialFocus(this._getSelectedInPopover()); + } + this.responsivePopover.showAt(tab); + return; + } this._onHeaderItemSelect(tab); } + async _onTabExpandButtonClick(event) { + event.stopPropagation(); + event.preventDefault(); + let button = event.target; + let tabInstance = button.tab; + + if (tabInstance) { + tabInstance.focus(); + } + + if ((event.type === "keydown") && !event.target._realTab.isSingleClickArea) { + button = event.target.querySelectorAll(".ui5-tab-expand-button")[0]; + tabInstance = event.target._realTab; + } + + // if clicked between the expand button and the tab + if (!tabInstance) { + this._onHeaderItemSelect(button.parentElement); + return; + } + + this._overflowItems = tabInstance.subTabs; + this._addStyleIndent(this._overflowItems, false); + + this.responsivePopover = await this._respPopover(); + if (this.responsivePopover.opened) { + this.responsivePopover.close(); + } else { + this._setInitialFocus(this._getSelectedInPopover()); + } + this.responsivePopover.showAt(button); + } + + _setInitialFocus(selectedInPopover) { + if (selectedInPopover.length) { + this.responsivePopover.initialFocus = selectedInPopover[0].id; + } else { + this.responsivePopover.initialFocus = this.responsivePopover.content[0].items.filter(item => item.classList.contains("ui5-tab-overflow-item"))[0].id; + } + } + _onTabStripKeyDown(event) { const tab = getTab(event.target); if (!tab) { @@ -436,12 +514,24 @@ class TabContainer extends UI5Element { } if (isEnter(event)) { - this._onHeaderItemSelect(tab); + if (tab._realTab.isSingleClickArea) { + this._onTabStripClick(event); + } else { + this._onHeaderItemSelect(tab); + } } - // Prevent Scrolling if (isSpace(event)) { - event.preventDefault(); + event.preventDefault(); // prevent scrolling + } + + if (isDown(event)) { + if (tab._realTab.requiresExpandButton) { + this._onTabExpandButtonClick(event); + } + if (tab._realTab.isSingleClickArea) { + this._onTabStripClick(event); + } } } @@ -452,7 +542,12 @@ class TabContainer extends UI5Element { } if (isSpace(event)) { - this._onHeaderItemSelect(tab); + event.preventDefault(); + if (tab._realTab.isSingleClickArea) { + this._onTabStripClick(event); + } else { + this._onHeaderItemSelect(tab); + } } } @@ -466,23 +561,40 @@ class TabContainer extends UI5Element { } } - _onOverflowListItemClick(event) { + async _onOverflowListItemClick(event) { event.preventDefault(); // cancel the item selection const { item } = event.detail; this._onItemSelect(item); - this.responsivePopover.close(); + await this.responsivePopover.close(); + this._setItemsForStrip(); - this.shadowRoot.querySelector(`#${item.id}`).focus(); + + const selectedTopLevel = this._getRootTab(this._selectedTab); + + selectedTopLevel.focus(); + } + + _getAllSubItems(items, result, level = 1) { + items.forEach(item => { + if (item.hasAttribute("ui5-tab") || item.hasAttribute("ui5-tab-separator")) { + item._level = level; + result.push(item); + if (item.subTabs) { + this._getAllSubItems(item.subTabs, result, level + 1); + } + } + }); + return result; } _onItemSelect(target) { - const selectedIndex = findIndex(this.items, item => item._id === target.id); - const selectedTabIndex = findIndex(this._getTabs(), item => item._id === target.id); - const selectedTab = this.items[selectedIndex]; + const selectedIndex = findIndex(this._allItemsAndSubItems, item => item.__id === target.id); + const selectedTabIndex = findIndex(this._allItemsAndSubItems, item => item.__id === target.id); + const selectedTab = this._allItemsAndSubItems[selectedIndex]; // update selected items - this.items + this._allItemsAndSubItems .forEach((item, index) => { const selected = selectedIndex === index; item.selected = selected; @@ -566,8 +678,7 @@ class TabContainer extends UI5Element { const overflowAttr = isEndOverflow ? "end-overflow" : "start-overflow"; - this._startOverflowItems = []; - this._endOverflowItems = []; + this._overflowItems = []; this.items.forEach(item => { if (item.getTabInStripDomRef() && item.getTabInStripDomRef().hasAttribute(overflowAttr)) { @@ -578,12 +689,14 @@ class TabContainer extends UI5Element { let button; if (isEndOverflow) { button = this.overflowButton[0] || overflow.querySelector("[ui5-button]"); - this._endOverflowItems = items; + this._overflowItems = items; + this._addStyleIndent(this._overflowItems, true); } if (isStartOverflow) { button = this.startOverflowButton[0] || overflow.querySelector("[ui5-button]"); - this._startOverflowItems = items; + this._overflowItems = items; + this._addStyleIndent(this._overflowItems, true); } this.responsivePopover = await this._respPopover(); @@ -595,14 +708,32 @@ class TabContainer extends UI5Element { } } + _getSelectedInPopover() { + return this.responsivePopover.content[0].items.filter(item => (item._realTab && item._realTab.selected)); + } + + _addStyleIndent(tabs, isOverflow) { + walk(tabs, tab => { + let level = tab._level; + if (!isOverflow) { + level -= 1; + } + + if (tab._level > 1 && tab.isSeparator) { + level -= 1; + } + + tab._style = { + "--_ui5-indentation-level": level / 2, + }; + }); + } + async _onOverflowKeyDown(event) { const isEndOverflow = event.currentTarget.classList.contains("ui5-tc__overflow--end"); const isStartOverflow = event.currentTarget.classList.contains("ui5-tc__overflow--start"); - switch (true) { - case isDown(event): - case isStartOverflow && isLeft(event): - case isEndOverflow && isRight(event): + if (isDown(event) || (isStartOverflow && isLeft(event)) || (isEndOverflow && isRight(event))) { await this._onOverflowClick(event); } } @@ -657,14 +788,24 @@ class TabContainer extends UI5Element { } this._itemNavigation._init(); - this._itemNavigation.setCurrentItem(this._selectedTab); + this._itemNavigation.setCurrentItem(this._getRootTab(this._selectedTab)); + } + + _getRootTab(tab) { + while (tab.hasAttribute("ui5-tab")) { + if (tab.parentElement.hasAttribute("ui5-tabcontainer")) { + break; + } + tab = tab.parentElement; + } + return tab; } _updateEndOverflow(itemsDomRefs) { // show end overflow this._getEndOverflow().removeAttribute("hidden"); - - const selectedTabDomRef = this._selectedTab.getTabInStripDomRef(); + const selectedTab = this._getRootTab(this._selectedTab); + const selectedTabDomRef = selectedTab.getTabInStripDomRef(); const containerWidth = this._getTabStrip().offsetWidth; const selectedItemIndexAndWidth = this._getSelectedItemIndexAndWidth(itemsDomRefs, selectedTabDomRef); @@ -680,7 +821,8 @@ class TabContainer extends UI5Element { _updateStartAndEndOverflow(itemsDomRefs) { let containerWidth = this._getTabStrip().offsetWidth; - const selectedTabDomRef = this._selectedTab.getTabInStripDomRef(); + const selectedTab = this._getRootTab(this._selectedTab); + const selectedTabDomRef = selectedTab.getTabInStripDomRef(); const selectedItemIndexAndWidth = this._getSelectedItemIndexAndWidth(itemsDomRefs, selectedTabDomRef); const hasStartOverflow = this._hasStartOverflow(containerWidth, itemsDomRefs, selectedItemIndexAndWidth); const hasEndOverflow = this._hasEndOverflow(containerWidth, itemsDomRefs, selectedItemIndexAndWidth); @@ -1088,6 +1230,15 @@ const findIndex = (arr, predicate) => { return -1; }; +const walk = (tabs, callback) => { + [...tabs].forEach(tab => { + callback(tab); + if (tab.subTabs) { + walk(tab.subTabs, callback); + } + }); +}; + TabContainer.define(); export default TabContainer; diff --git a/packages/main/src/TabContainerPopover.hbs b/packages/main/src/TabContainerPopover.hbs index 29f47bd14f49..b6234c095a71 100644 --- a/packages/main/src/TabContainerPopover.hbs +++ b/packages/main/src/TabContainerPopover.hbs @@ -8,15 +8,9 @@ class="ui5-tab-container-responsive-popover" > - {{#if _endOverflowItems.length}} - {{#each _endOverflowItems}} - {{this.overflowPresentation}} - {{/each}} - {{else}} - {{#each _startOverflowItems}} - {{this.overflowPresentation}} - {{/each}} - {{/if}} + {{#each _overflowItems}} + {{overflowPresentation}} + {{/each}} - + \ No newline at end of file diff --git a/packages/main/src/TabInOverflow.hbs b/packages/main/src/TabInOverflow.hbs index bbc4752c47d3..b2aa90daf88c 100644 --- a/packages/main/src/TabInOverflow.hbs +++ b/packages/main/src/TabInOverflow.hbs @@ -6,16 +6,23 @@ aria-disabled="{{this.effectiveDisabled}}" aria-selected="{{this.effectiveSelected}}" aria-labelledby="{{this.ariaLabelledBy}}" + ._realTab="{{this}}" + style="{{this._style}}" > -
- {{#if this.icon}} - - {{/if}} +
+
+ {{#if this.icon}} + + {{/if}} - {{this.text}} + {{this.text}} - {{#if this.additionalText}} - ({{this.additionalText}}) - {{/if}} + {{#if this.additionalText}} + ({{this.additionalText}}) + {{/if}} +
+{{#each subTabs}} + {{overflowPresentation}} +{{/each}} diff --git a/packages/main/src/TabInStrip.hbs b/packages/main/src/TabInStrip.hbs index 9f4cc9e7f2e6..54b4286fb9ec 100644 --- a/packages/main/src/TabInStrip.hbs +++ b/packages/main/src/TabInStrip.hbs @@ -4,12 +4,13 @@ role="tab" aria-posinset="{{this._posinset}}" aria-setsize="{{this._setsize}}" - aria-controls="ui5-tc-contentItem-{{this._posinset}}" + aria-controls="ui5-tc-content" aria-selected="{{this.effectiveSelected}}" aria-disabled="{{this.effectiveDisabled}}" ?disabled="{{this.effectiveDisabled}}" aria-labelledby="{{this.ariaLabelledBy}}" data-ui5-stable="{{this.stableDomRef}}" + ._realTab="{{this}}" > {{#if this.icon}}
@@ -26,10 +27,26 @@ {{this.displayText}} + {{#if this.isSingleClickArea}} + + + + {{/if}} {{/if}} +
-
+ {{#if this.requiresExpandButton}} +
+ + +
+ {{/if}} {{#*inline additionalText}} {{#if this.additionalText}} diff --git a/packages/main/src/TabSeparatorInOverflow.hbs b/packages/main/src/TabSeparatorInOverflow.hbs index f9abf06039b8..cb1e353bc2da 100644 --- a/packages/main/src/TabSeparatorInOverflow.hbs +++ b/packages/main/src/TabSeparatorInOverflow.hbs @@ -4,5 +4,6 @@ role="separator" class="{{classes}}" disabled + style="{{this._style}}" > \ No newline at end of file diff --git a/packages/main/src/themes/TabContainer.css b/packages/main/src/themes/TabContainer.css index 7a6ac9c53291..1fc4c624891c 100644 --- a/packages/main/src/themes/TabContainer.css +++ b/packages/main/src/themes/TabContainer.css @@ -103,6 +103,27 @@ display: none; } +.ui5-tab-expand-button > [ui5-button] { + height: 1.5rem; + min-width: 1.5rem; + margin-top: 0.25rem; + margin-left: 0.625rem; +} +.ui5-tab-single-click-icon { + margin-left: 0.625rem; + float: right; +} + +.ui5-tab-strip-item--singleClickArea { + margin-top: 2px; +} + +.ui5-tab-expand-button>[ui5-button]:hover { + background-color: var(--sapButton_Hover_Background); +} +.ui5-tab-expand-button>[ui5-button]:active { + background-color: var(--sapButton_Active_Background); +} /*** Responsive paddings ***/ :host([media-range="S"]) .ui5-tc__header { diff --git a/packages/main/src/themes/TabInOverflow.css b/packages/main/src/themes/TabInOverflow.css index 732a58c05ed3..b89148e1827e 100644 --- a/packages/main/src/themes/TabInOverflow.css +++ b/packages/main/src/themes/TabInOverflow.css @@ -34,9 +34,18 @@ .ui5-tab-overflow-itemContent { display: flex; align-items: center; - padding: 0 0.5rem; + padding-right: 0.5rem; height: var(--_ui5_tc_item_text); pointer-events: none; + font-size: 0.875rem; +} + +.ui5-tab-overflow-itemContent-wrapper { + padding-left: calc(var(--_ui5-indentation-level, 0) * 1rem); +} + +.ui5-tab-overflow-item--selectedSubTab { + background-color: var(--sapList_SelectionBackgroundColor); } .ui5-tab-overflow-item [ui5-icon] { diff --git a/packages/main/src/themes/TabInStrip.css b/packages/main/src/themes/TabInStrip.css index 293e91ebb1be..3eaff8a01b8b 100644 --- a/packages/main/src/themes/TabInStrip.css +++ b/packages/main/src/themes/TabInStrip.css @@ -44,15 +44,14 @@ .ui5-tab-strip-item--selected.ui5-tab-strip-item--textOnly { color: var(--_ui5_tc_headeritem_text_selected_color); } +.ui5-tab-strip-item--selected .ui5-tab-single-click-icon>[ui5-icon] { + color: var(--_ui5_tc_headeritem_text_selected_color); +} .ui5-tab-strip-item:hover:not(.ui5-tab-strip-item--selected).ui5-tab-strip-item--textOnly { color: var(--_ui5_tc_headerItem_text_hover_color); } -.ui5-tab-strip-item:hover.ui5-tab-strip-item--selected.ui5-tab-strip-item--textOnly { - color: var(--_ui5_tc_headeritem_text_selected_hover_color); -} - /* the outline when hover or selected */ .ui5-tab-strip-item--textOnly:hover .ui5-tab-strip-itemContent::after, .ui5-tab-strip-item--mixedMode:hover .ui5-tab-strip-itemContent::after, @@ -371,4 +370,16 @@ [dir=rtl] .ui5-tab-strip-item--mixedMode .ui5-tab-strip-itemAdditionalText { margin-right: 0; margin-left: 0.5rem; +} + +.ui5-tab-strip-item--selected:not(.ui5-tab-strip-item--withIcon) .ui5-tab-expand-button>[ui5-button]::after { + content: ""; + position: absolute; + bottom: 1px; + left: 12px; + right: 16px; + border-bottom: var(--_ui5_tc_headerItemContent_border_bottom); + border-radius: var(--_ui5_tc_headerItemContent_border_radius); + background-color: var(--_ui5_tc_headerItemContent_border_bg); + height: var(--_ui5_tc_headerItemContent_border_height); } \ No newline at end of file diff --git a/packages/main/src/themes/TabSeparatorInOverflow.css b/packages/main/src/themes/TabSeparatorInOverflow.css index ce23450dd07d..67166a187a5a 100644 --- a/packages/main/src/themes/TabSeparatorInOverflow.css +++ b/packages/main/src/themes/TabSeparatorInOverflow.css @@ -1,7 +1,8 @@ .ui5-tc__separator { min-height: 0.25rem; border-bottom: 0.0625rem solid var(--sapGroup_TitleBorderColor); - margin: 0 0.5rem; + margin-left: calc(var(--_ui5-indentation-level, 0) * 1rem); + margin-right: 0.5rem; } [ui5-list]>.ui5-tc__separator:first-child { min-height: 0.5rem; diff --git a/packages/main/test/pages/TabContainer.html b/packages/main/test/pages/TabContainer.html index 463b5d4f739e..3df3a1c27606 100644 --- a/packages/main/test/pages/TabContainer.html +++ b/packages/main/test/pages/TabContainer.html @@ -26,14 +26,116 @@

ui5-tabcontainer

+ Compact +
+

Nested Tabs

+ + + Button 1 + + + + Button 2 + + Button 21 + + + Button 211 + + + + + + Button 2121 + + Button 212 + + + + + Text for 2.2 + + + + + + Button 31 + + + + Button 4 + + + Button 41 + + + Button 411 + + Button 4111 + + Button 41111 + + + + + + + + Tab Content + Tab Content + + Tab Content + Tab Content + Tab Content + Tab Content + Tab 10.1 Content + Tab 10.1.1 Content + + Tab Content + + + + + + + + + + + 1 + 1.1 + + 2 + 2.1 + 2.1.1 + + 2.2 + + + + + + + + + +
- Compact

Text only End Overflow

- - + + Button 2.1 + Button 2.2 + Button 2.3 + + + + + Button 3 + + @@ -223,6 +325,7 @@

Text only

+

Scrollable child

Toggle style @@ -549,8 +652,8 @@

No paddings for the Content

Text only Start And End Overflow Custom Overflow Buttons

- Start - End + Start + End @@ -584,7 +687,6 @@

Text only Start And End Overflow Custom Overflow Buttons

-