@@ -15,6 +15,7 @@ import type { UUITabElement } from './uui-tab.element';
15
15
* @cssprop --uui-tab-group-dropdown-tab-text-hover - Define the tab text hover color in the dropdown
16
16
* @cssprop --uui-tab-group-dropdown-tab-text-active - Define the tab text active color in the dropdown
17
17
* @cssprop --uui-tab-group-dropdown-background - Define the background color of the dropdown
18
+ * @cssprop --uui-tab-group-gap - Define the gap between elements dropdown. Only pixel values are valid
18
19
*/
19
20
@defineElement ( 'uui-tab-group' )
20
21
export class UUITabGroupElement extends LitElement {
@@ -30,6 +31,9 @@ export class UUITabGroupElement extends LitElement {
30
31
} )
31
32
private _slottedNodes ?: HTMLElement [ ] ;
32
33
34
+ /** Stores the current gap used in the breakpoints */
35
+ #currentGap = 0 ;
36
+
33
37
/**
34
38
* Set the flex direction of the content of the dropdown.
35
39
* @type {string }
@@ -69,7 +73,16 @@ export class UUITabGroupElement extends LitElement {
69
73
}
70
74
71
75
#onResize( entries : ResizeObserverEntry [ ] ) {
72
- this . #updateCollapsibleTabs( entries [ 0 ] . contentBoxSize [ 0 ] . inlineSize ) ;
76
+ // Check if the gap css custom property has changed.
77
+ const gapCSSVar = Number . parseFloat (
78
+ this . style . getPropertyValue ( '--uui-tab-group-gap' )
79
+ ) ;
80
+ const newGap = Number . isNaN ( gapCSSVar ) ? 0 : gapCSSVar ;
81
+ if ( newGap !== this . #currentGap) {
82
+ this . #calculateBreakPoints( ) ;
83
+ } else {
84
+ this . #updateCollapsibleTabs( entries [ 0 ] . contentBoxSize [ 0 ] . inlineSize ) ;
85
+ }
73
86
}
74
87
75
88
#onSlotChange( ) {
@@ -117,13 +130,42 @@ export class UUITabGroupElement extends LitElement {
117
130
}
118
131
} ;
119
132
133
+ async #calculateBreakPoints( ) {
134
+ // Whenever a tab is added or removed, we need to recalculate the breakpoints
135
+
136
+ await this . updateComplete ; // Wait for the tabs to be rendered
137
+ const gapCSSVar = Number . parseFloat (
138
+ this . style . getPropertyValue ( '--uui-tab-group-gap' )
139
+ ) ;
140
+ const gap = Number . isNaN ( gapCSSVar ) ? 0 : gapCSSVar ;
141
+ this . #currentGap = gap ;
142
+ let childrenWidth = 0 ;
143
+
144
+ for ( let i = 0 ; i < this . #tabElements. length ; i ++ ) {
145
+ this . #tabElements[ i ] . style . display = '' ;
146
+ childrenWidth += this . #tabElements[ i ] . offsetWidth ;
147
+ this . #visibilityBreakpoints[ i ] = childrenWidth ;
148
+ // Add the gap, which will then be included in the next breakpoint:
149
+ childrenWidth += gap ;
150
+ }
151
+
152
+ const tolerance = 2 ;
153
+ this . style . maxWidth = childrenWidth - gap + tolerance + 'px' ;
154
+
155
+ this . #updateCollapsibleTabs( this . offsetWidth ) ;
156
+ }
157
+
158
+ #setTabArray( ) {
159
+ this . #tabElements = this . _slottedNodes ? this . _slottedNodes : [ ] ;
160
+ this . #calculateBreakPoints( ) ;
161
+ }
162
+
120
163
#updateCollapsibleTabs( containerWidth : number ) {
121
- const buttonWidth = this . _moreButtonElement . offsetWidth ;
164
+ const moreButtonWidth = this . _moreButtonElement . offsetWidth ;
122
165
123
- // Only update if the container is smaller than the last breakpoint
124
- const lastBreakpoint = this . #visibilityBreakpoints. slice ( - 1 ) [ 0 ] ;
125
- if ( lastBreakpoint < containerWidth && this . #hiddenTabElements. length === 0 )
126
- return ;
166
+ const containerWithoutButtonWidth =
167
+ containerWidth -
168
+ ( moreButtonWidth ? moreButtonWidth + this . #currentGap : 0 ) ;
127
169
128
170
// Do the update
129
171
// Reset the hidden tabs
@@ -135,18 +177,19 @@ export class UUITabGroupElement extends LitElement {
135
177
136
178
let hasActiveTabInDropdown = false ;
137
179
138
- for ( let i = 0 ; i < this . #visibilityBreakpoints. length ; i ++ ) {
180
+ const len = this . #visibilityBreakpoints. length ;
181
+ for ( let i = 0 ; i < len ; i ++ ) {
139
182
const breakpoint = this . #visibilityBreakpoints[ i ] ;
140
183
const tab = this . #tabElements[ i ] as UUITabElement ;
141
184
142
- // Subtract the button width when we are not at the last breakpoint
143
- const containerWidthButtonWidth =
144
- containerWidth -
145
- ( i !== this . #visibilityBreakpoints. length - 1 ? buttonWidth : 0 ) ;
146
-
147
- if ( breakpoint < containerWidthButtonWidth ) {
185
+ // If breakpoint is smaller than the container width, then show the tab.
186
+ // If last breakpoint, then we will use the containerWidth, as we do not want to include the more-button in that calculation.
187
+ if (
188
+ breakpoint <=
189
+ ( i === len - 1 ? containerWidth : containerWithoutButtonWidth )
190
+ ) {
191
+ // Show this tab:
148
192
tab . style . display = '' ;
149
- this . _moreButtonElement . style . display = 'none' ;
150
193
} else {
151
194
// Make a proxy tab to put in the hidden tabs container and link it to the original tab
152
195
const proxyTab = tab . cloneNode ( true ) as UUITabElement ;
@@ -162,16 +205,20 @@ export class UUITabGroupElement extends LitElement {
162
205
this . #hiddenTabElements. push ( proxyTab ) ;
163
206
164
207
tab . style . display = 'none' ;
165
- this . _moreButtonElement . style . display = '' ;
166
208
if ( tab . active ) {
167
209
hasActiveTabInDropdown = true ;
168
210
}
169
211
}
170
212
}
171
213
172
214
if ( this . #hiddenTabElements. length === 0 ) {
215
+ // Hide more button:
216
+ this . _moreButtonElement . style . display = 'none' ;
173
217
// close the popover
174
218
this . _popoverContainerElement . hidePopover ( ) ;
219
+ } else {
220
+ // Show more button:
221
+ this . _moreButtonElement . style . display = '' ;
175
222
}
176
223
177
224
hasActiveTabInDropdown
@@ -181,29 +228,6 @@ export class UUITabGroupElement extends LitElement {
181
228
this . requestUpdate ( ) ;
182
229
}
183
230
184
- async #calculateBreakPoints( ) {
185
- // Whenever a tab is added or removed, we need to recalculate the breakpoints
186
-
187
- await this . updateComplete ; // Wait for the tabs to be rendered
188
- let childrenWidth = 0 ;
189
-
190
- for ( let i = 0 ; i < this . #tabElements. length ; i ++ ) {
191
- this . #tabElements[ i ] . style . display = '' ;
192
- childrenWidth += this . #tabElements[ i ] . offsetWidth ;
193
- this . #visibilityBreakpoints[ i ] = childrenWidth ;
194
- }
195
-
196
- const tolerance = 2 ;
197
- this . style . width = childrenWidth + tolerance + 'px' ;
198
-
199
- this . #updateCollapsibleTabs( this . offsetWidth ) ;
200
- }
201
-
202
- #setTabArray( ) {
203
- this . #tabElements = this . _slottedNodes ? this . _slottedNodes : [ ] ;
204
- this . #calculateBreakPoints( ) ;
205
- }
206
-
207
231
#isElementTabLike( el : any ) : el is UUITabElement {
208
232
return (
209
233
typeof el === 'object' && 'active' in el && typeof el . active === 'boolean'
@@ -212,15 +236,17 @@ export class UUITabGroupElement extends LitElement {
212
236
213
237
render ( ) {
214
238
return html `
215
- <slot @slotchange = ${ this . #onSlotChange} > </ slot>
216
- <uui- butto n
217
- popovertarget= "popover-container"
218
- style = "display: none"
219
- id = "more-button"
220
- label = "More"
221
- compact >
222
- <uui- symbol- mor e> </ uui- symbol- mor e>
223
- </ uui- butto n>
239
+ <div id= "main" >
240
+ <slot @slotchange = ${ this . #onSlotChange} > </ slot>
241
+ <uui- butto n
242
+ popovertarget= "popover-container"
243
+ style = "display: none"
244
+ id = "more-button"
245
+ label = "More"
246
+ compact >
247
+ <uui- symbol- mor e> </ uui- symbol- mor e>
248
+ </ uui- butto n>
249
+ </ div>
224
250
<uui- popover- container
225
251
id= "popover-container"
226
252
popover
@@ -235,13 +261,17 @@ export class UUITabGroupElement extends LitElement {
235
261
static styles = [
236
262
css `
237
263
: host {
264
+ width : 100% ;
265
+ }
266
+
267
+ # main {
238
268
display : flex;
239
- flex-wrap : nowrap;
240
- color : var (--uui-tab-text );
241
269
height : 100% ;
242
270
min-height : 48px ;
243
271
overflow : hidden;
244
272
text-wrap : nowrap;
273
+ color : var (--uui-tab-text );
274
+ gap : var (--uui-tab-group-gap , 0 );
245
275
}
246
276
247
277
# popover-container {
0 commit comments