Skip to content

Commit dbedf1c

Browse files
committed
fix(Taglist): hide all tags for small containers
1 parent a7f2979 commit dbedf1c

File tree

3 files changed

+75
-72
lines changed

3 files changed

+75
-72
lines changed

packages/ui/src/components/TagList/__tests__/__snapshots__/index.test.tsx.snap

Lines changed: 44 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ exports[`tagList > hide items after maxLength 1`] = `
106106
</div>
107107
</div>
108108
<div
109-
aria-controls="_r_12_"
110-
aria-describedby="_r_12_"
109+
aria-controls="_r_11_"
110+
aria-describedby="_r_11_"
111111
class="styles__w40vpo9"
112112
tabindex="-1"
113113
>
@@ -314,8 +314,8 @@ exports[`tagList > renders correctly a scrollable popover with non default popov
314314
</div>
315315
</div>
316316
<div
317-
aria-controls="_r_2i_"
318-
aria-describedby="_r_2i_"
317+
aria-controls="_r_2h_"
318+
aria-describedby="_r_2h_"
319319
class="styles__w40vpo9"
320320
tabindex="-1"
321321
>
@@ -345,19 +345,8 @@ exports[`tagList > renders correctly and add ellipsis to the first tag as it too
345345
<div
346346
class="styles__1f9zr5y2 styles__1f9zr5y4"
347347
data-testid="taglist-container"
348-
style="--_1f9zr5y0: 0px;"
349-
>
350-
<span
351-
class="ellipsed styles__1f9zr5y5 styles__d6zknp0 styles_sentiment_neutral__d6zknp5"
352-
data-testid=""
353-
>
354-
<span
355-
class="styles__d6zknp1c style__m4c9ow0 style_oneLine_true__m4c9ow3 style_prominence_default__m4c9ow4 style_variant_caption__m4c9owp style_undefined_compound_0__m4c9ow1a"
356-
>
357-
scaleway is the best cloud provider ever invented
358-
</span>
359-
</span>
360-
</div>
348+
style="--_1f9zr5y0: 50px;"
349+
/>
361350
<div
362351
style="position: absolute; visibility: hidden; white-space: nowrap; pointer-events: none;"
363352
>
@@ -377,6 +366,20 @@ exports[`tagList > renders correctly and add ellipsis to the first tag as it too
377366
</span>
378367
</div>
379368
</div>
369+
<div
370+
aria-controls="_r_j_"
371+
aria-describedby="_r_j_"
372+
class="styles__w40vpo9"
373+
tabindex="-1"
374+
>
375+
<span
376+
class="styles__1f9zr5y6"
377+
data-testid="taglist-open"
378+
tabindex="0"
379+
>
380+
+1
381+
</span>
382+
</div>
380383
</div>
381384
</div>
382385
</DocumentFragment>
@@ -396,18 +399,7 @@ exports[`tagList > renders correctly and ignore custom threshold as it does not
396399
class="styles__1f9zr5y2 styles__1f9zr5y4"
397400
data-testid="taglist-container"
398401
style="--_1f9zr5y0: 50px;"
399-
>
400-
<span
401-
class="ellipsed styles__1f9zr5y5 styles__d6zknp0 styles_sentiment_neutral__d6zknp5"
402-
data-testid=""
403-
>
404-
<span
405-
class="styles__d6zknp1c style__m4c9ow0 style_oneLine_true__m4c9ow3 style_prominence_default__m4c9ow4 style_variant_caption__m4c9owp style_undefined_compound_0__m4c9ow1a"
406-
>
407-
scaleway
408-
</span>
409-
</span>
410-
</div>
402+
/>
411403
<div
412404
style="position: absolute; visibility: hidden; white-space: nowrap; pointer-events: none;"
413405
>
@@ -438,8 +430,8 @@ exports[`tagList > renders correctly and ignore custom threshold as it does not
438430
</div>
439431
</div>
440432
<div
441-
aria-controls="_r_i_"
442-
aria-describedby="_r_i_"
433+
aria-controls="_r_h_"
434+
aria-describedby="_r_h_"
443435
class="styles__w40vpo9"
444436
tabindex="-1"
445437
>
@@ -448,7 +440,7 @@ exports[`tagList > renders correctly and ignore custom threshold as it does not
448440
data-testid="taglist-open"
449441
tabindex="0"
450442
>
451-
+2
443+
+3
452444
</span>
453445
</div>
454446
</div>
@@ -522,8 +514,8 @@ exports[`tagList > renders correctly with copiable 1`] = `
522514
style="--_1f9zr5y0: 0px;"
523515
>
524516
<div
525-
aria-controls="_r_1c_"
526-
aria-describedby="_r_1c_"
517+
aria-controls="_r_1b_"
518+
aria-describedby="_r_1b_"
527519
class="styles__w40vpo9"
528520
tabindex="0"
529521
>
@@ -540,8 +532,8 @@ exports[`tagList > renders correctly with copiable 1`] = `
540532
</button>
541533
</div>
542534
<div
543-
aria-controls="_r_1e_"
544-
aria-describedby="_r_1e_"
535+
aria-controls="_r_1d_"
536+
aria-describedby="_r_1d_"
545537
class="styles__w40vpo9"
546538
tabindex="0"
547539
>
@@ -566,8 +558,8 @@ exports[`tagList > renders correctly with copiable 1`] = `
566558
data-testid="taglist-measure-container"
567559
>
568560
<div
569-
aria-controls="_r_18_"
570-
aria-describedby="_r_18_"
561+
aria-controls="_r_17_"
562+
aria-describedby="_r_17_"
571563
class="styles__w40vpo9"
572564
tabindex="0"
573565
>
@@ -584,8 +576,8 @@ exports[`tagList > renders correctly with copiable 1`] = `
584576
</button>
585577
</div>
586578
<div
587-
aria-controls="_r_1a_"
588-
aria-describedby="_r_1a_"
579+
aria-controls="_r_19_"
580+
aria-describedby="_r_19_"
589581
class="styles__w40vpo9"
590582
tabindex="0"
591583
>
@@ -808,8 +800,8 @@ exports[`tagList > renders correctly with custom threshold and extra tags and ma
808800
</div>
809801
</div>
810802
<div
811-
aria-controls="_r_n_"
812-
aria-describedby="_r_n_"
803+
aria-controls="_r_m_"
804+
aria-describedby="_r_m_"
813805
class="styles__w40vpo9"
814806
tabindex="-1"
815807
>
@@ -842,8 +834,8 @@ exports[`tagList > renders correctly with icons 1`] = `
842834
style="--_1f9zr5y0: 0px;"
843835
>
844836
<div
845-
aria-controls="_r_1k_"
846-
aria-describedby="_r_1k_"
837+
aria-controls="_r_1j_"
838+
aria-describedby="_r_1j_"
847839
class="styles__w40vpo9"
848840
tabindex="0"
849841
>
@@ -860,8 +852,8 @@ exports[`tagList > renders correctly with icons 1`] = `
860852
</button>
861853
</div>
862854
<div
863-
aria-controls="_r_1m_"
864-
aria-describedby="_r_1m_"
855+
aria-controls="_r_1l_"
856+
aria-describedby="_r_1l_"
865857
class="styles__w40vpo9"
866858
tabindex="0"
867859
>
@@ -886,8 +878,8 @@ exports[`tagList > renders correctly with icons 1`] = `
886878
data-testid="taglist-measure-container"
887879
>
888880
<div
889-
aria-controls="_r_1g_"
890-
aria-describedby="_r_1g_"
881+
aria-controls="_r_1f_"
882+
aria-describedby="_r_1f_"
891883
class="styles__w40vpo9"
892884
tabindex="0"
893885
>
@@ -904,8 +896,8 @@ exports[`tagList > renders correctly with icons 1`] = `
904896
</button>
905897
</div>
906898
<div
907-
aria-controls="_r_1i_"
908-
aria-describedby="_r_1i_"
899+
aria-controls="_r_1h_"
900+
aria-describedby="_r_1h_"
909901
class="styles__w40vpo9"
910902
tabindex="0"
911903
>
@@ -994,8 +986,8 @@ exports[`tagList > renders correctly with multiline 1`] = `
994986
</div>
995987
</div>
996988
<div
997-
aria-controls="_r_17_"
998-
aria-describedby="_r_17_"
989+
aria-controls="_r_16_"
990+
aria-describedby="_r_16_"
999991
class="styles__w40vpo9"
1000992
tabindex="-1"
1001993
>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
import { consoleLightTheme } from '@ultraviolet/themes'
22

33
export const TAGS_GAP = consoleLightTheme.space['1']
4+
5+
export const DEFAULT_POPOVER_MAX_HEIGHT = '16rem'
6+
export const MIN_TAG_WIDTH = 40 // in px

packages/ui/src/components/TagList/index.tsx

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,11 @@ import { useEffect, useMemo, useRef, useState } from 'react'
77
import { Popover } from '../Popover'
88
import { Tag } from '../Tag'
99

10-
import { TAGS_GAP } from './constant'
10+
import { DEFAULT_POPOVER_MAX_HEIGHT, MIN_TAG_WIDTH, TAGS_GAP } from './constant'
1111
import { popoverTriggerWidthVar, tagListStyle } from './styles.css'
1212

1313
import type { ComponentProps, CSSProperties, ReactNode } from 'react'
1414

15-
const DEFAULT_POPOVER_MAX_HEIGHT = '16rem'
16-
const MIN_TAG_WIDTH = 32 // in px
17-
1815
export type TagType = string | { label: string; icon: ReactNode }
1916

2017
type TagListProps = {
@@ -140,10 +137,10 @@ export const TagList = ({
140137
const toMeasureElements: HTMLCollection =
141138
measureRef.current.children[0].children
142139

143-
const [firstTag, ...restOfToMeasureElements] = [...toMeasureElements]
140+
const toMeasureElementsArray = [...toMeasureElements]
144141

145142
const { measuredVisibleTags, measuredHiddenTags } =
146-
restOfToMeasureElements.reduce(
143+
toMeasureElementsArray.reduce(
147144
(
148145
accumulator: {
149146
measuredVisibleTags: TagType[]
@@ -157,29 +154,40 @@ export const TagList = ({
157154
measuredHiddenTags: TagType[]
158155
accumulatedWidth: number
159156
} => {
157+
const tagWidth = (currentValue as HTMLDivElement).offsetWidth
158+
const gap = index > 0 ? Number.parseInt(TAGS_GAP, 10) : 0
160159
const newAccumulatedWidth =
161-
accumulator.accumulatedWidth +
162-
(currentValue as HTMLDivElement).offsetWidth +
163-
Number.parseInt(TAGS_GAP, 10)
160+
accumulator.accumulatedWidth + tagWidth + gap
161+
162+
const minWidthAccumulatedWidth =
163+
accumulator.accumulatedWidth + MIN_TAG_WIDTH + gap
164+
165+
// The tag fits (with or without needing shrinking)
166+
if (minWidthAccumulatedWidth <= parentWidth) {
167+
return {
168+
accumulatedWidth: newAccumulatedWidth,
169+
measuredHiddenTags: accumulator.measuredHiddenTags,
170+
measuredVisibleTags: [
171+
...accumulator.measuredVisibleTags,
172+
tags[index],
173+
],
174+
}
175+
}
164176

177+
// The tag doesn't fit at all (available space < min-width)
165178
return {
166-
accumulatedWidth: newAccumulatedWidth,
179+
accumulatedWidth: accumulator.accumulatedWidth,
167180
measuredHiddenTags: [
168181
...accumulator.measuredHiddenTags,
169-
newAccumulatedWidth > parentWidth && tags[index + 1],
170-
].filter(Boolean) as TagType[],
171-
measuredVisibleTags: [
172-
...accumulator.measuredVisibleTags,
173-
newAccumulatedWidth <= parentWidth && tags[index + 1],
174-
].filter(Boolean) as TagType[],
182+
tags[index],
183+
],
184+
measuredVisibleTags: accumulator.measuredVisibleTags,
175185
}
176186
},
177187
{
178-
accumulatedWidth:
179-
(firstTag as HTMLDivElement).offsetWidth +
180-
Number.parseInt(TAGS_GAP, 10),
188+
accumulatedWidth: 0,
181189
measuredHiddenTags: [],
182-
measuredVisibleTags: [tags[0]], // we need to always show one tag
190+
measuredVisibleTags: [],
183191
},
184192
)
185193

0 commit comments

Comments
 (0)