11import React from 'react'
2+ import styled from 'styled-components'
23import { XIcon } from '@primer/octicons-react'
34import { getFocusableChild } from '@primer/behaviors/utils'
5+ import { get } from '../constants'
46import VisuallyHidden from '../_VisuallyHidden'
57import { AnchoredOverlay } from '../AnchoredOverlay'
68import { Button , IconButton } from '../Button'
7- import { clsx } from 'clsx'
89import theme from '../theme'
910import classes from './LabelGroup.module.css'
1011
@@ -17,6 +18,45 @@ export type LabelGroupProps = {
1718 visibleChildCount ?: 'auto' | number
1819 className ?: string
1920}
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+
2060// Calculates the width of the overlay to cover the labels/tokens and the expand button.
2161const getOverlayWidth = (
2262 buttonClientRect : DOMRect ,
@@ -111,7 +151,7 @@ const LabelGroup: React.FC<React.PropsWithChildren<LabelGroupProps>> = ({
111151 children,
112152 visibleChildCount,
113153 overflowStyle = 'overlay' ,
114- as : Component = 'ul' ,
154+ as = 'ul' ,
115155 className,
116156} ) => {
117157 const containerRef = React . useRef < HTMLElement > ( null )
@@ -280,30 +320,28 @@ const LabelGroup: React.FC<React.PropsWithChildren<LabelGroupProps>> = ({
280320 }
281321 } , [ overflowStyle , isOverflowShown ] )
282322
283- const isList = Component === 'ul' || Component === 'ol'
323+ const isList = as === 'ul' || as === 'ol'
284324 const ToggleWrapper = isList ? 'li' : React . Fragment
285325
286- const ItemWrapperComponent = isList ? 'li' : 'span'
287-
288326 // If truncation is enabled, we need to render based on truncation logic.
289327 return visibleChildCount ? (
290- < Component
328+ < StyledLabelGroupContainer
291329 ref = { containerRef }
292330 data-overflow = { overflowStyle === 'inline' && isOverflowShown ? 'inline' : undefined }
293331 data-list = { isList || undefined }
294- className = { clsx ( className , classes . Container ) }
332+ className = { className }
333+ as = { as }
295334 >
296335 { React . Children . map ( children , ( child , index ) => (
297- < ItemWrapperComponent
336+ < ItemWrapper
298337 // data-index is used as an identifier we can use in the IntersectionObserver
299338 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' }
303341 key = { index }
304342 >
305343 { child }
306- </ ItemWrapperComponent >
344+ </ ItemWrapper >
307345 ) ) }
308346 < ToggleWrapper >
309347 { overflowStyle === 'inline' ? (
@@ -331,15 +369,15 @@ const LabelGroup: React.FC<React.PropsWithChildren<LabelGroupProps>> = ({
331369 </ OverlayToggle >
332370 ) }
333371 </ ToggleWrapper >
334- </ Component >
372+ </ StyledLabelGroupContainer >
335373 ) : (
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 } >
337375 { isList
338376 ? React . Children . map ( children , ( child , index ) => {
339377 return < li key = { index } > { child } </ li >
340378 } )
341379 : children }
342- </ Component >
380+ </ StyledLabelGroupContainer >
343381 )
344382}
345383
0 commit comments