1
1
import React from 'react'
2
+ import styled from 'styled-components'
2
3
import { XIcon } from '@primer/octicons-react'
3
4
import { getFocusableChild } from '@primer/behaviors/utils'
5
+ import { get } from '../constants'
4
6
import VisuallyHidden from '../_VisuallyHidden'
5
7
import { AnchoredOverlay } from '../AnchoredOverlay'
6
8
import { Button , IconButton } from '../Button'
7
- import { clsx } from 'clsx'
8
9
import theme from '../theme'
9
10
import classes from './LabelGroup.module.css'
10
11
@@ -17,6 +18,45 @@ export type LabelGroupProps = {
17
18
visibleChildCount ?: 'auto' | number
18
19
className ?: string
19
20
}
21
+
22
+ const StyledLabelGroupContainer = styled . div `
23
+ display: flex;
24
+ flex-wrap: nowrap;
25
+ gap: ${ get ( 'space.1' ) } ;
26
+ line-height: 1;
27
+ max-width: 100%;
28
+ overflow: hidden;
29
+
30
+ &[data-overflow='inline'] {
31
+ flex-wrap: wrap;
32
+ }
33
+
34
+ &[data-list] {
35
+ padding-inline-start: 0;
36
+ margin-block-start: 0;
37
+ margin-block-end: 0;
38
+ list-style-type: none;
39
+ }
40
+ `
41
+
42
+ const ItemWrapper = styled . div `
43
+ display: flex;
44
+ align-items: center;
45
+
46
+ /* This min-height matches the height of the expand/collapse button.
47
+ Without it, the labels/tokens will do a slight layout shift when expanded.
48
+ This is because the height of the first row will match the token sizes,
49
+ but the height of the second row will be the height of the collapse button.
50
+ */
51
+ min-height: 28px;
52
+
53
+ &.ItemWrapper--hidden {
54
+ order: 9999;
55
+ pointer-events: none;
56
+ visibility: hidden;
57
+ }
58
+ `
59
+
20
60
// Calculates the width of the overlay to cover the labels/tokens and the expand button.
21
61
const getOverlayWidth = (
22
62
buttonClientRect : DOMRect ,
@@ -111,7 +151,7 @@ const LabelGroup: React.FC<React.PropsWithChildren<LabelGroupProps>> = ({
111
151
children,
112
152
visibleChildCount,
113
153
overflowStyle = 'overlay' ,
114
- as : Component = 'ul' ,
154
+ as = 'ul' ,
115
155
className,
116
156
} ) => {
117
157
const containerRef = React . useRef < HTMLElement > ( null )
@@ -280,30 +320,28 @@ const LabelGroup: React.FC<React.PropsWithChildren<LabelGroupProps>> = ({
280
320
}
281
321
} , [ overflowStyle , isOverflowShown ] )
282
322
283
- const isList = Component === 'ul' || Component === 'ol'
323
+ const isList = as === 'ul' || as === 'ol'
284
324
const ToggleWrapper = isList ? 'li' : React . Fragment
285
325
286
- const ItemWrapperComponent = isList ? 'li' : 'span'
287
-
288
326
// If truncation is enabled, we need to render based on truncation logic.
289
327
return visibleChildCount ? (
290
- < Component
328
+ < StyledLabelGroupContainer
291
329
ref = { containerRef }
292
330
data-overflow = { overflowStyle === 'inline' && isOverflowShown ? 'inline' : undefined }
293
331
data-list = { isList || undefined }
294
- className = { clsx ( className , classes . Container ) }
332
+ className = { className }
333
+ as = { as }
295
334
>
296
335
{ React . Children . map ( children , ( child , index ) => (
297
- < ItemWrapperComponent
336
+ < ItemWrapper
298
337
// data-index is used as an identifier we can use in the IntersectionObserver
299
338
data-index = { index }
300
- className = { clsx ( classes . ItemWrapper , {
301
- [ classes [ 'ItemWrapper--hidden' ] ] : hiddenItemIds . includes ( index . toString ( ) ) ,
302
- } ) }
339
+ className = { hiddenItemIds . includes ( index . toString ( ) ) ? 'ItemWrapper--hidden' : undefined }
340
+ as = { isList ? 'li' : 'span' }
303
341
key = { index }
304
342
>
305
343
{ child }
306
- </ ItemWrapperComponent >
344
+ </ ItemWrapper >
307
345
) ) }
308
346
< ToggleWrapper >
309
347
{ overflowStyle === 'inline' ? (
@@ -331,15 +369,15 @@ const LabelGroup: React.FC<React.PropsWithChildren<LabelGroupProps>> = ({
331
369
</ OverlayToggle >
332
370
) }
333
371
</ ToggleWrapper >
334
- </ Component >
372
+ </ StyledLabelGroupContainer >
335
373
) : (
336
- < Component data-overflow = "inline" data-list = { isList || undefined } className = { clsx ( className , classes . Container ) } >
374
+ < StyledLabelGroupContainer data-overflow = "inline" data-list = { isList || undefined } as = { as } className = { className } >
337
375
{ isList
338
376
? React . Children . map ( children , ( child , index ) => {
339
377
return < li key = { index } > { child } </ li >
340
378
} )
341
379
: children }
342
- </ Component >
380
+ </ StyledLabelGroupContainer >
343
381
)
344
382
}
345
383
0 commit comments