Skip to content

Commit 0c71e15

Browse files
feat(multi-select): add collapsedSelection prop
When enabled, displays "X selected" text instead of individual selection chips, providing a more compact representation.
1 parent 426f7c9 commit 0c71e15

3 files changed

Lines changed: 46 additions & 1 deletion

File tree

components/select/src/multi-select/input.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { colors } from '@dhis2/ui-constants'
33
import cx from 'classnames'
44
import PropTypes from 'prop-types'
55
import React from 'react'
6+
import i18n from '../locales/index.js'
67
import {
78
InputClearButton,
89
InputPlaceholder,
@@ -22,6 +23,7 @@ const Input = ({
2223
className,
2324
disabled,
2425
inputMaxHeight = '100px',
26+
collapsedSelection,
2527
}) => {
2628
const hasSelection = selected.length > 0
2729
const onClear = (e) => {
@@ -40,7 +42,15 @@ const Input = ({
4042
dataTest={`${dataTest}-placeholder`}
4143
/>
4244
)}
43-
{hasSelection && (
45+
{hasSelection && collapsedSelection && (
46+
<span
47+
className="collapsed-selection-text"
48+
data-test={`${dataTest}-selection-count`}
49+
>
50+
{i18n.t('{{count}} selected', { count: selected.length })}
51+
</span>
52+
)}
53+
{hasSelection && !collapsedSelection && (
4454
<div className="root-input">
4555
{/* the wrapper div above is necessary to enforce wrapping on overflow */}
4656
<SelectionList
@@ -81,6 +91,11 @@ const Input = ({
8191
.root-right {
8292
margin-inline-start: auto;
8393
}
94+
95+
.collapsed-selection-text {
96+
flex: 1;
97+
user-select: none;
98+
}
8499
`}</style>
85100

86101
<style jsx>{`
@@ -97,6 +112,7 @@ Input.propTypes = {
97112
className: PropTypes.string,
98113
clearText: requiredIf((props) => props.clearable, PropTypes.string),
99114
clearable: PropTypes.bool,
115+
collapsedSelection: PropTypes.bool,
100116
disabled: PropTypes.bool,
101117
inputMaxHeight: PropTypes.string,
102118
options: PropTypes.node,

components/select/src/multi-select/multi-select.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const MultiSelect = ({
3737
noMatchText,
3838
initialFocus,
3939
dense,
40+
collapsedSelection,
4041
dataTest = 'dhis2-uicore-multiselect',
4142
}) => {
4243
// If the select is filterable, use a filterable menu
@@ -65,6 +66,7 @@ const MultiSelect = ({
6566
placeholder={placeholder}
6667
prefix={prefix}
6768
inputMaxHeight={inputMaxHeight}
69+
collapsedSelection={collapsedSelection}
6870
/>
6971
}
7072
menu={menu}
@@ -114,6 +116,8 @@ MultiSelect.propTypes = {
114116
clearText: requiredIf((props) => props.clearable, PropTypes.string),
115117
/** Adds a 'clear' option to the menu */
116118
clearable: PropTypes.bool,
119+
/** When true, shows "X selected" text instead of individual chips */
120+
collapsedSelection: PropTypes.bool,
117121
dataTest: PropTypes.string,
118122
dense: PropTypes.bool,
119123
disabled: PropTypes.bool,

components/select/src/multi-select/multi-select.prod.stories.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,31 @@ export const ShiftedIntoView = (args) => (
367367
</>
368368
)
369369

370+
export const CollapsedSelection = () => {
371+
const [selected, setSelected] = React.useState(['1', '3', '5'])
372+
return (
373+
<div style={{ maxWidth: 400 }}>
374+
<MultiSelect
375+
className="select"
376+
selected={selected}
377+
onChange={({ selected }) => setSelected(selected)}
378+
collapsedSelection
379+
prefix="Prefix text"
380+
clearable
381+
clearText="Clear all"
382+
>
383+
<MultiSelectOption value="1" label="option one" />
384+
<MultiSelectOption value="2" label="option two" />
385+
<MultiSelectOption value="3" label="option three" />
386+
<MultiSelectOption value="4" label="option four" />
387+
<MultiSelectOption value="5" label="option five" />
388+
<MultiSelectOption value="6" label="option six" />
389+
</MultiSelect>
390+
</div>
391+
)
392+
}
393+
CollapsedSelection.storyName = 'Collapsed selection'
394+
370395
export const RTL = (args) => {
371396
useEffect(() => {
372397
document.body.dir = 'rtl'

0 commit comments

Comments
 (0)