Skip to content

Select: add support for multiple selections#643

Open
mkernohanbc wants to merge 16 commits intomainfrom
feature/select
Open

Select: add support for multiple selections#643
mkernohanbc wants to merge 16 commits intomainfrom
feature/select

Conversation

@mkernohanbc
Copy link
Copy Markdown
Contributor

@mkernohanbc mkernohanbc commented Mar 4, 2026

This PR makes significant (non-breaking) changes to Select, and minor changes to Tag. See the Vite kitchen sink app for examples. Changes are also documented in Storybook.

The impetus for this was the addition of support for multi-select in React Aria v1.13.0.

Summary of changes in this PR:

  • Select now supports toggling between single or multiple select via the selectionMode prop
  • Added visual indicator for selected items in the ListBox
  • Changed flex behaviour for Select so that it adjusts to its parent container and can grow vertically to show multiple rows
  • <SelectValue> can now wrap over multiple lines, instead of being truncated with ellipsis
  • Adjusted small style for Select to properly use typography.regular.small.body
  • Added a new xsmall Tag variant
  • Updated Tag to properly spread its props

In single-select mode, Select behaves as it currently does (showing the currently-selected value as a text string inside the Select button.)

When selectionMode is set to multiple, it instead renders a <TagGroup> inside the button:

Screenshot 2026-03-04 at 11 22 46 AM

This means that selected items are:

  • Visually separated
  • De-selectable without re-opening the dropdown

Both the dropdown and the TagGroup are fully operable via keyboard:

Screen.Recording.2026-03-04.at.10.48.29.AM.mov

To prevent an accessibility violation from having interactive tags nested inside a button, this PR uses createPortal to render the <TagGroup> outside the Select <Button>. This adds additional styling complexity, but achieves the desired visual structure accessibly.

An alternative approach (f1d97d6) would be to render a <Group> instead of a <Button> when in multi-select mode. However, this approach:

  • Breaks the sizing logic of the popover, because the var(--trigger-width) used to size the popover no longer works
  • Forces a fundamental change in behaviour between Select modes, because in multi-select the dropdown could only be activated by pressing a small button, rather than by pressing anywhere on the Select object

@mkernohanbc mkernohanbc added this to the Components v0.7.0 milestone Mar 4, 2026
@mkernohanbc mkernohanbc self-assigned this Mar 4, 2026
@mkernohanbc mkernohanbc added the Components Changes or issues affect the design-system-react-components package label Mar 4, 2026
@Philip-Cheung
Copy link
Copy Markdown

Screenshot 2026-03-04 at 1 41 10 PM The component crashed when I clicked on the "sections" control.

@mkernohanbc
Copy link
Copy Markdown
Contributor Author

The component crashed when I clicked on the "sections" control.

That story is rendering for me (including switching modes and adding/removing selections), suggesting it might be a local Storybook issue on your end? Try killing and restarting Storybook (might also need to do the 'delete node_modules/npm i step if it's still bugging out after that.)

@Philip-Cheung
Copy link
Copy Markdown

Screenshot 2026-03-04 at 1 45 34 PM

When I add selections into the input, does it expand by default as more items are added? Can I set a fixed width? I have a hunch a lot of folks are not going to like that behaviour as it messes up their forms/design

@Philip-Cheung
Copy link
Copy Markdown

The component crashed when I clicked on the "sections" control.

That story is rendering for me (including switching modes and adding/removing selections), suggesting it might be a local Storybook issue on your end? Try killing and restarting Storybook (might also need to do the 'delete node_modules/npm i step if it's still bugging out after that.)

I tried restarting the local but I can replicate the issue

@mkernohanbc
Copy link
Copy Markdown
Contributor Author

When I add selections into the input, does it expand by default as more items are added? Can I set a fixed width? I have a hunch a lot of folks are not going to like that behaviour as it messes up their forms/design

In this example, it's inside a flex container, so its width is constrained by the structure of the page. If there are too many items for the width, it can wrap to a new line cleanly:

Screenshot 2026-03-04 at 1 49 31 PM

@Philip-Cheung
Copy link
Copy Markdown

When I add selections into the input, does it expand by default as more items are added? Can I set a fixed width? I have a hunch a lot of folks are not going to like that behaviour, as it messes up their forms/design.

In this example, it's inside a flex container, so its width is constrained by the structure of the page. If there are too many items for the width, it can wrap to a new line cleanly:

Screenshot 2026-03-04 at 1 49 31 PM

While I do see the benefit of implementing it this way, I have a couple of concerns as someone who’s used this sort of component in a variety of applications. For web apps, we generally expect it not to wrap onto a new line, as it can disrupt the layout in a wide range of use cases such as filter controls, settings, and forms. Especially in designs with limited vertical space, a new line can significantly interfere with the layout.

Maybe we could introduce a control that allows you to choose the overflow behavior of the multi-select when its contents exceed the container? The Ant design system link I shared with you this morning basically figured out every possible way you can implement a multi select.

@mkernohanbc mkernohanbc linked an issue Mar 31, 2026 that may be closed by this pull request
Copy link
Copy Markdown
Contributor

@ty2k ty2k left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots going on in this component now! I think the createPortal() stuff works nicely for using the TagGroup inside of the Select for multi-select. Overall, I can't really break this visually and it seems like the keyboard navigation is solid. Great stuff!

Couple thoughts beyond the specific line number comments below:

  1. IMO, I think we need a visual indicator of some kind in multi-select mode when overflow is set to scroll and there is more information to be viewed. I see we're hiding the scrollbar here, but maybe there's an opportunity for something like the Gov.bc.ca gradient on the breadcrumbs, as an example? I think there's a risk of hiding information with this style in this general. I would personally opt for the overflow: wrap or a checkbox list in this situation.

  2. There's a pixel or so worth of vertical layout shift happening in multi-select mode when there is nothing selected vs the first option is selected. This seems to be the case whether using size medium or small. When we're in multi-select mode, can we set a different min-height equal to the height of the tags to accommodate?

Image Image

Comment thread packages/react-components/src/components/Select/Select.css Outdated
Comment thread packages/react-components/src/components/Select/Select.css Outdated
Copy link
Copy Markdown
Contributor

@ty2k ty2k left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One visual height issue remains on this when we're in multi-select and moving between having no options selected and having one option selected.

color: var(--icons-color-danger);
/* Sizing */
.bcds-react-aria-Select.small .bcds-react-aria-Select--Button {
min-height: 32px;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following up on the comments here, I think this value needs to change to accommodate the extra ~1px happening when we're in multi-select mode with one option selected.

What I suggest is adding a class on the Select to indicate that you're in multi-select mode, and then choosing one of these:

  1. To keep all of the fields the same height, you could start playing with the padding inside of the Select button to accommodate the extra ~1px of height the Tag causes.

  2. If you don't care if the overall height of the Select field in multi-select mode is slightly taller than other components, you can set this min-height to 40px and the equivalent medium min-height to 46px.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Components Changes or issues affect the design-system-react-components package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add multi-select support to Select

3 participants