radix-ui / primitives

Radix Primitives is an open-source UI component library for building high-quality, accessible design systems and web apps. Maintained by @workos.
https://radix-ui.com/primitives
MIT License
15.22k stars 753 forks source link

[New Primitive] `Combobox` #1342

Open benoitgrelard opened 2 years ago

benoitgrelard commented 2 years ago

Mentioned in #1270 and #1334

kieranm commented 2 years ago

In our app we've had to implement...

Comboboxes in modals

Screenshot 2022-05-01 at 16 07 51

Comboboxes in menus (right-click context menu and dropdown menus)

Screenshot 2022-05-01 at 16 09 39

Comboboxes in select menus in forms

Screenshot 2022-05-01 at 16 10 11

If the team aren't already working on this, we would be happy to contribute back to the library! But it would be good to understand how comboboxes would fit in compatibly with the existing dialogs, selects, context menus, etc.

Would each of these components expose their own combobox functionality (something like ContextMenu.Search, Select.Search), or would there be a common combobox component that could just be plugged in to any other component?

It might also be a good idea to think about how this would fit in with the existing type-ahead logic.

Thanks!

yuriburk commented 2 years ago

@kieranm could you provide a example code?

jordie23 commented 2 years ago

To add a use case, not sure if this is the right component for it or whether it'd be part of the Select component, but we basically just want to be able to use Select with the ability to select multiple options.

laozhu commented 2 years ago

Is combobox on the road? I should make it by myself for now.

benoitgrelard commented 2 years ago

Hey @laozhu, nothing started on Combobox yet.

asherccohen commented 2 years ago

Same here, building some additional features on top of Select, cases mentioned above are exactly what we have in mind too.

djalmaaraujo commented 2 years ago

We are actively replacing our components with radix components in our library; this filtered/searchable component, similar to what react-select does, would be amazing.

selfish commented 2 years ago

@kieranm could you share your implementation? Is it based on Radix's select?

statusunknown418 commented 2 years ago

I'm really upvoting this, since headlessui/react already has an implementation but is broken for now

asherccohen commented 2 years ago

I'm under the same impression, I tried it too and it doesn't feel ready to be used. Also, the fact that their examples are using tailwind doesn't really help for a headless solution.

Kind Regards Asher


From: Alvaro Aquije @.> Sent: Thursday, August 4, 2022 5:27:36 PM To: radix-ui/primitives @.> Cc: Asher Cohen @.>; Comment @.> Subject: Re: [radix-ui/primitives] [New Primitive] Combobox (Issue #1342)

I'm really upvoting this, since headlessui/react already has an implementation but is broken for now

β€” Reply to this email directly, view it on GitHubhttps://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fradix-ui%2Fprimitives%2Fissues%2F1342%23issuecomment-1205410410&data=05%7C01%7C%7Ca0c542530b96454ee76308da762ddc6e%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637952236599313563%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=3zduzpCdtqQ4vCHr4mzmqCCSZBeVjQEBLSivLhp8WM4%3D&reserved=0, or unsubscribehttps://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAIIV4EMFNCYZHKWIOFI5WPLVXPOORANCNFSM5UIGGUFA&data=05%7C01%7C%7Ca0c542530b96454ee76308da762ddc6e%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637952236599469787%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=VnlAi1Xa0nHkYr6quYsKgt%2FHhnC3Zo%2Bknr8%2BCGqMv2s%3D&reserved=0. You are receiving this because you commented.Message ID: @.***>

thiagovilla commented 1 year ago

Please implement this! From the Discord server.

cabello commented 1 year ago

I use headlessui combobox for two things: command bar (cmd+k) and emoji autocomplete (when you type : in github, slack). For the second use case it broke my textarea: https://github.com/tailwindlabs/headlessui/issues/1718 I will likely implement this manually. Just sharing the use cases, I think that could help in the event this is implemented.

Screenshots for reference.

A shortcut (cmd+k) makes a dialog with this combobox show up, it can be filtered using fuzzy (outside the concern of the component) and navigated with arrows, enter to select.

CleanShot 2022-09-27 at 11 17 33@2x

Same combobox component, shows up once you hit a threshold :as (colon followed by at least these many letters), you can navigate up/down, the issue I have right now is that Combobox hijacks left/right arrows so I lose the textarea functionality.

CleanShot 2022-09-27 at 11 17 54@2x
Code-Victor commented 1 year ago

is there any workaround with radix UI only?

dm-camelonta commented 1 year ago

Agree, would be nice to have a combobox in Radix.

kof commented 1 year ago

I have been using downshift in the meantime and it made me realize how hard it is to create a combobox that is truly reusable for all the purposes. Its a weird component in general, it can be used for autocomplete, filtering, search, be always open or as a dropdown etc. All those cases change the behavior for focus management and input update dramatically.

At this point I would even consider that radix shouldn't implement a combobox but rather create a documentation on using radix together with downshift.

oskarrough commented 1 year ago

Also worth noting: based on the Open UI research on the "select" component, Microsoft and Chromium (afaik) have started work on a new, additional <selectmenu> element.

djalmaaraujo commented 1 year ago

We decided to go with Autcomplete components when there are more than 15 options to show. This is somehow a recommendation from our A11Y specialist. We implemented using the UK's autocomplete component and provided a react way using our API's.

Reference: https://vip-design-system-components.netlify.app/?path=/story/form-autocomplete--default

If we want to show less than 15 options, we use a simple browser Select component.

If we need to show more, we are sticking with the pattern of using the Autocomplete.

This combination seems to be the most optimized accessible options to our customers, and with the simpler API.

πŸ€™

kieranm commented 1 year ago

We have recently moved to CmdK which uses Radix under the hood. It can be used for modals or popovers. https://github.com/pacocoursey/cmdk

joaom00 commented 1 year ago

If anyone wants to know how to use Radix + Cmdk, here an example.

smol-honk commented 1 year ago

Super interested in getting a primitive for this!

PeerRich commented 1 year ago

lets get this cake! Is there somehow a way we can sponsor this PR or similar? Expedite the engineering of it?

wongmrdev commented 1 year ago

Is using DropdownMenu bad practice for multiselect?

benoitgrelard commented 1 year ago

Is using DropdownMenu bad practice for multiselect?

As is, yes unless you re-write a bunch of accessibility yourself, they wouldn't carry the same semantic unfortunately.

wongmrdev commented 1 year ago

What do you mean by accessibility?

What does carrying the same semantic mean?

what are our options for multiselect?

benoitgrelard commented 1 year ago

The accessibility/semantic of dropdown menu are carrying are those of a "menu button" aria pattern, not a "listbox" pattern. Additionally, menus don't hold a value (or values, in the case of select). Also, they are not form elements, so wouldn't participate in form events like change events bubbling etc.

Ultimately, they may "look" similar, but they are not the same component.

luchsamapparat commented 1 year ago

What do you mean by accessibility?

https://developer.mozilla.org/en-US/docs/Learn/Accessibility/What_is_accessibility

What does carrying the same semantic mean?

https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML#good_semantics

Accessibility is one of the main selling points of Radix: https://www.radix-ui.com/docs/primitives/overview/accessibility

wongmrdev commented 1 year ago

@benoitgrelard Thanks for the detailed explanation. It seems like it's not illegal to use the DropdownMenu if accessibility in my app is not a concern (Thanks @luchsamapparat for the definitions). I can use the DropdownMenu, modified with added state control, until a MultiSelect is implementented in radix-ui.

benoitgrelard commented 1 year ago

… if accessibility in my app is not a concern

Accessibility is always a concern of any app, as you do not know who will end up using the app. Perhaps the only case where it could be considered not a concern is if you are developing an app only for your own self to consume and if you are able (any of us could end up with a disability in the future too…)

vincent-schroeder commented 1 year ago

Is there a plan for when the Combobox will be available?

chaance commented 1 year ago

Hey @benoitgrelard, is there any interest in working with outside collaborators on this one? I've got a need and would happily help out if y'all still intend to ship this!

Because ... I get it πŸ˜…

Difficulty: Hard
Raid55 commented 1 year ago

i'm out here representing the 415 and showing vivid interest for Combobox. Everyone loves that Linear feel, it's an undeniable craze...

Aside from that I wanted to ask if there was a typeahead API or further reading about it's implementation? I see it briefly mentioned as a feature on various component pages. Does typeahead hold a state that could be accessed? This would help me implement something like showing the typed characters in header-label, without the actual input box.

Great job with Radix btw.

cloud-walker commented 1 year ago

I'm with @chaance in this!

I would love to help in any way possible.

I think that the problem with Combobox is that its a broad concept, that cover a lot of scenarios:

  1. I want the search input to be the trigger of the listbox popover
  2. I want both the search input and the listbox visible without a popover
  3. I want a button trigger that spawn a popover with both search input and listbox
  4. Multiple values support
  5. Items may come from an async operation (loading state, error state, etc.)
  6. Probably I'm missing a lot of other scenarios..

I'm certainly not an accessibility expert, but my impression is that maybe a single abstraction to rule all use cases maybe not the best way to tackle the problem, maybe we should try to split in more abstractions?

benoitgrelard commented 1 year ago

Hey @benoitgrelard, is there any interest in working with outside collaborators on this one? I've got a need and would happily help out if y'all still intend to ship this!

Because ... I get it πŸ˜… Difficulty: Hard

Hey @chaance! Yes, Combobox is definitely something we'd like to add to the library.

I think that the problem with Combobox is that its a broad concept, that cover a lot of scenarios:

I want the search input to be the trigger of the listbox popover I want both the search input and the listbox visible without a popover I want a button trigger that spawn a popover with both search input and listbox Multiple values support Items may come from an async operation (loading state, error state, etc.) Probably I'm missing a lot of other scenarios..

Following what @cloud-walker talks about here, I feel like perhaps a good way to start getting the ball rolling here would be to create some very high-level prototypes of APIs (away from full keyboard/accessibility/etc concerns for now) so we can narrow down our focus. We need to learn a few things so we can decide what we are building, ie. one component supporting multiple use-case, multiple components, etc.

Would that be something you could start looking at @chaance? Feel free to DM me on Discord too btw!

✌️

filiptammergard commented 1 year ago

Happy to see things are happening here @benoitgrelard @chaance!

I think some inspiration could be taken from the React Aria ComboBox: https://react-spectrum.adobe.com/react-aria/ComboBox.html

The APG Combobox pattern is also a great source of knowledge, where a few examples are listed. The "Editable Combobox With List Autocomplete Example" is what I would expect of a Radix Combobox primitive, providing some flexibility on when the popover opens. Multi-selection is out of scope IMO – probably deserves its own primitive.

Would be great if you could keep us posted on what you're thinking. Also happy to help out in any way possible!

ciampo commented 1 year ago

FWIW, I also think that Ariakit has a good and flexible implementation Combobox component: https://ariakit.org/components/combobox

kiastorm commented 1 year ago

I'd love the ability to have non-selectable items within the popover that trigger actions instead.

This is useful for something like

"Select a filter (option) or create a new filter (action/link)"

Here's something similar I found in GitLab:

image

I just requested this feature for the Select here: https://github.com/radix-ui/primitives/issues/2120, but maybe its better suited for the ComboBox (or both)?

To support this, it seems the SelectContent would render with role="dialog" and then have an additional component SelectOptionList or SelectListBox to outline the role="listbox"?

<button id="popover-trigger" aria-haspopup="dialog" aria-controls="popover-content">
  Filter 1
</button>

<div id="popover-content" role="dialog" aria-modal="true" aria-labelledby="popover-title" aria-describedby="popover-description">
  <h2 id="popover-title">Select a filter or create one</h2>
  <p id="popover-description">This popover contains a listbox and action items for selecting or creating a filter.</p>
  <div role="listbox" aria-label="Select a filter">
    <div role="option" aria-selected="true">Filter 1</div>
    <div role="option">Filter 2</div>
    <div role="option">Filter 3</div>
  </div>
  <div role="group">
    <button type="button" role="button">Create a filter</button>
    <button type="button" role="button">Manage filters</button>
  </div>
</div>

which I'd imagine would look something like

<ComboBox>
  <ComboBox.ButtonTrigger>
    <ComboBox.Value />
  </ComboBox.ButtonTrigger>

  <ComboBox.Content>
    <ComboBox.Title>Select a filter or create one</h2>
    <ComboBox.Description>This popover contains a listbox and action items for selecting or creating a filter</ComboBox.Description>
    <ComboBox.ListBox>
      <ComboBox.Option value="filter-1">
        Filter 1
      </ComboBox.Option>
      <ComboBox.Option value="filter-2">
        Filter 2
      </ComboBox.Option>
    </ComboBox.ListBox>
    <ComboBox.Separator />
    <ComboBox.Group>
      <ComboBox.Item onClick={onCreateFilterClick}>
        Create a filter
      </ComboBox.Item>
      <ComboBox.Item asChild>
        <a href="/filters/manage">
          Manage filters...
        </a>
      </ComboBox.Item>
    </ComboBox.Group>
  </ComboBox.Content>
</ComboBox>
its-monotype commented 1 year ago

I believe the Combobox component by Kobalte for SolidJS is well-designed and highly adaptable. You can find more information about it at: https://kobalte.dev/docs/core/components/combobox

yaguzmang commented 1 year ago

Hi! Are there any updates on this? It would be great to have this primitive. Is there any way the community can help?

landondurnan commented 1 year ago

In case this helps anyone else, I saw that shadcn has a Combobox component based on Radix and cmdk component by pacocoursey.

It's not exactly what I'm looking for in a combobox, but I'm taking some inspiration from this component composition to see if I can create a multi-select version (similar to downshift multiple selection)

I definitely love the UI / UX that a combobox would be able to provide, there's a lot of similar components in Radix already so it seems achievable, but the range of flexibility required to meet the needs of any UI likely will require something that is highly composable. Love the brainstorming in this thread already.

bergold commented 1 year ago

@landondurnan checkout Fancy Box by @mxkaske for an example of a multi-select based on this cmdk+radix-ui combo. Might be a good inspiration as well.

Link: https://craft.mxkaske.dev/post/fancy-box

CanRau commented 1 year ago

Experimented with combining Downshift + Tanstack Virtual which in general worked though got more complex trying to get sub commands working the way I want so currently sticking with cmdk in a radix dialog, based on ShadCN πŸ”₯

yuki16bit commented 1 year ago

OMG, I'm facing the same challenge. I have to put comboboxes inside of select and dropdown in a very limited time because our designers believe that these kinds of UI/UX are perfect for users (well..., I agree with them too πŸ˜ƒ).

ζˆͺεœ– 2023-06-12 δΈ‹εˆ3 55 39

I'm currently trying to use ariakit/react to implement it, but since our project primarily uses Radix UI, I'm really looking forward to seeing the Combobox primitive being released πŸ™ ❀️

charrondev commented 1 year ago

I'd be interested in giving this a shot:

I'm envisioning an API similar to <Select /> but with a few key variations and options, following the guidelines here https://www.w3.org/WAI/ARIA/apg/patterns/combobox/

Notably I intend to implement only the "Listbox" popup type described there and not the Grid or tree popups.

It would differ from the <Select /> primitive in a few ways.

New Input Element

There will be an additional required <ComboBox.Input /> component that can be placed wherever desired. This will hold the value the list is being filtered by. Some people may choose to display this in place place of the trigger or inside the Content.

Multiple Values

There will be an additional prop on the root allowMultipleValues. When set a user will be able to select multiple values. The type signatures of the onValueChange will now require a function signature accepting an array of strings.

Dynamic/Async Content

Comboboxes are often used with a dynamic list of items that needs to be fetched asynchronously and can't all be displayed at once. To indicate that you will be needing this add the async prop to the <ComboxBox.Root async />.

The <ComboBox.Content /> will then accept function children in addition to ReactNode children of the following signature: (filter: string) => React.ReactNode. These functions will be called with the current input value on every render to generate additional children.

The <ComboBox.Value> component will no longer accept empty children as we don't necessarily have an item that can be portalled up here. Instead children will be required an must be either a ReactNode or a function with the following signature (for uncontrolled component usage) (values: string[]) => React.ReactNode. Any asynchronous loading of these values need to be handled by the developer using the component.

Filtered Content

The rendered children of <ComboBox.Content /> will be iterated in order and have an additional filtering pass where a case-insensitive String.prototype.includes() call is performed on the ComboBox.ItemText value of each one. If the item text does not include the current filter then the item will not be rendered.

Loading indicator

If a content function is performing dynamic data fetching it may need a way to indicate that results are loading. In this case, a <ComboBox.LoadingIndicator> with react children may be rendered. These will be announced in an accessible way to screen readers. The visual appearance and determination of when this should appear will not be controlled by the ComboBox and instead delegated to the function rendering it.

No Results

Since the results are being filtered care it is possible no results will be matching our input filter. An optional <ComboBox.NoResultsMessage>Message Here</ComboBox.NoResultsMessage> can be placed which will conditionally render when there are no matched results.

Example Structure

const ComboBoxItem = React.forwardRef(({ children, className, ...props }, forwardedRef) => {
    return (
      <ComboBox.Item className={classnames('ComboBox.Item', className)} {...props} ref={forwardedRef}>
        <ComboBox.ItemText>{children}</ComboBox.ItemText>
        <ComboBox.ItemIndicator className="ComboBox.ItemIndicator">
          <CheckIcon />
        </ComboBox.ItemIndicator>
      </ComboBox.Item>
    );
  });

Static Values


function MyComboBox() {
    return (
        <ComboxBox.Root>
            <ComboxBox.Trigger aria-label="Food">
                <ComboxBox.Value placeholder="Select a fruit…" />
                <ComboxBox.Icon>
                    <ChevronDownIcon />
                </ComboxBox.Icon>
            </ComboxBox.Trigger>
            <ComboxBox.Portal>
                <ComboxBox.Content>
                    <ComboBox.Input
                        placeholder="Filter fruits"
                        aria-label="Filter fruits"
                    />
                    <ComboxBox.ScrollUpButton>
                        <ChevronUpIcon />
                    </ComboxBox.ScrollUpButton>
                    <ComboxBox.Viewport>
                        <ComboxBox.Group>
                            <ComboxBox.Label>Fruits</ComboxBox.Label>
                            <ComboBoxItem value="apple">Apple</ComboBoxItem>
                            <ComboBoxItem value="banana">Banana</ComboBoxItem>
                            <ComboBoxItem value="blueberry">
                                Blueberry
                            </ComboBoxItem>
                            <ComboBoxItem value="grapes">Grapes</ComboBoxItem>
                            <ComboBoxItem value="pineapple">
                                Pineapple
                            </ComboBoxItem>
                        </ComboxBox.Group>

                        <ComboxBox.Separator />

                        <ComboxBox.Group>
                            <ComboxBox.Label>Vegetables</ComboxBox.Label>
                            <ComboBoxItem value="aubergine">
                                Aubergine
                            </ComboBoxItem>
                            <ComboBoxItem value="broccoli">
                                Broccoli
                            </ComboBoxItem>
                            <ComboBoxItem value="carrot" disabled>
                                Carrot
                            </ComboBoxItem>
                            <ComboBoxItem value="courgette">
                                Courgette
                            </ComboBoxItem>
                            <ComboBoxItem value="leek">Leek</ComboBoxItem>
                        </ComboxBox.Group>

                        <ComboxBox.Separator />

                        <ComboxBox.Group>
                            <ComboxBox.Label>Meat</ComboxBox.Label>
                            <ComboBoxItem value="beef">Beef</ComboBoxItem>
                            <ComboBoxItem value="chicken">Chicken</ComboBoxItem>
                            <ComboBoxItem value="lamb">Lamb</ComboBoxItem>
                            <ComboBoxItem value="pork">Pork</ComboBoxItem>
                        </ComboxBox.Group>
                    </ComboxBox.Viewport>
                    <ComboxBox.ScrollDownButton>
                        <ChevronDownIcon />
                    </ComboxBox.ScrollDownButton>
                </ComboxBox.Content>
            </ComboxBox.Portal>
        </ComboxBox.Root>
    );
}

Dynamic Values


function MyOptionLoader(props: { filter: string }) {
    // Not provided by the combobox. This example uses the `react-query` and `axios` libraries to perform data fetching.
    const myResults = useQuery<Array<{ label: string; value: string }>>({
        queryFn: pDebounce(async () => {
            const response = await axios.get(`/api/my-api?query=${props.filter}`);
            return response.data;
        }, 100),
        queryKey: ["autocomplete", props.filter],
    });

    if (!myResults.data) {
        return (
            <ComboBox.LoadingIndicator>
                <LoadingSpinner />
            </ComboBox.LoadingIndicator>
        );
    }

    return (
        <>
            {myResults.data.map((item, i) => {
                return (
                    <ComboBoxItem key={i} value={item.value}>
                        {item.label}
                    </ComboBoxItem>
                );
            })}
            {myResults.isFetching && (
                // Even though we might have started fetching a set of data.
                <ComboBox.LoadingIndicator>
                    <LoadingSpinner />
                </ComboBox.LoadingIndicator>
            )}
        </>
    );
}

function MyComboBox() {
    const [values, setValues] = useState<string[]>([]);

    return (
        <ComboxBox.Root async value={values} onValueChange={setValues}>
            <ComboxBox.Trigger aria-label="Food">
                <ComboxBox.Value placeholder="Select a fruit…">
                    {values.map((value) => (
                        // One notable pitfal here, we may not have necessarily loaded our "values" from anywhere yet. This will be the responsibility of the end user to reflect some kind of loading indicators here or fetch the data if it is
                        <span>{value}</span>
                    ))}
                </ComboxBox.Value>
                <ComboxBox.Icon>
                    <ChevronDownIcon />
                </ComboxBox.Icon>
            </ComboxBox.Trigger>
            <ComboxBox.Portal>
                <ComboxBox.Content>
                    {(filter: string) => {
                        return (
                            <>
                                <ComboBox.Input placeholder="Filter fruits" aria-label="Filter fruits" />
                                <ComboxBox.ScrollUpButton>
                                    <ChevronUpIcon />
                                </ComboxBox.ScrollUpButton>
                                <ComboxBox.Viewport>
                                    <MyOptionLoader filter={filter} />
                                </ComboxBox.Viewport>
                                <ComboxBox.ScrollDownButton>
                                    <ChevronDownIcon />
                                </ComboxBox.ScrollDownButton>
                            </>
                        );
                    }}
                </ComboxBox.Content>
            </ComboxBox.Portal>
        </ComboxBox.Root>
    );
}
franzheidl commented 1 year ago

Is there any update on this?

We are currently using Radix Select under the hood for the Select component in our design system, and we urgently need combobox functionality.

As a spike, we have included a text input as the first item in Select.Content and simply filter the option values by whatever is being typed in the field, which works reasonably well. However, Radix managing the focus (as desirable as it is for a standard Select) kind of keeps us from progressing here: In order to focus the field, the user has to click into it. We have not yet found a way to focus the input when the Select content opens.

Also, when typing one keystroke into the field, Radix will do what it needs to do (jumping to and focussing the first Select Option beginning with the typed letter) in order to implement standard select behaviour, however this would require the user to click into the input field yet again in order to type in more letters to filter by a string that is longer than a single character. In order to override this beahviour, we would need to have control over the focus, at least as long as there is no ComboBox in Radix-UI.

I am aware of this issue https://github.com/radix-ui/primitives/issues/1602, and we have found that Radix internally uses utilities called focus-scope and focus-guard, which come with a Read Me discouraging their use outside of the core radix-ui library, but which could – potentially – help us to manage the focus as we need, at least so we can implement a stop-gap version of a combobox / select with an input. We have not yet managed to use these with what we need to achieve, either.

Any hints on what the plans are to move on with ComboBox if any, or any other info as to how to manage the focus ourselves would be highly appreciated. πŸ™

iampeter commented 1 year ago

@franzheidl maybe this could help you: https://ui.shadcn.com/docs/components/combobox

bzenky commented 1 year ago

Is there any update on this?

We are currently using Radix Select under the hood for the Select component in our design system, and we urgently need combobox functionality.

As a spike, we have included a text input as the first item in Select.Content and simply filter the option values by whatever is being typed in the field, which works reasonably well. However, Radix managing the focus (as desirable as it is for a standard Select) kind of keeps us from progressing here: In order to focus the field, the user has to click into it. We have not yet found a way to focus the input when the Select content opens.

Also, when typing one keystroke into the field, Radix will do what it needs to do (jumping to and focussing the first Select Option beginning with the typed letter) in order to implement standard select behaviour, however this would require the user to click into the input field yet again in order to type in more letters to filter by a string that is longer than a single character. In order to override this beahviour, we would need to have control over the focus, at least as long as there is no ComboBox in Radix-UI.

I am aware of this issue #1602, and we have found that Radix internally uses utilities called focus-scope and focus-guard, which come with a Read Me discouraging their use outside of the core radix-ui library, but which could – potentially – help us to manage the focus as we need, at least so we can implement a stop-gap version of a combobox / select with an input. We have not yet managed to use these with what we need to achieve, either.

Any hints on what the plans are to move on with ComboBox if any, or any other info as to how to manage the focus ourselves would be highly appreciated. πŸ™

Same here, just passed by the same situation, comboBox will be a very welcome component.

charliematters commented 1 year ago

Personally I down-voted your comment as I felt it didn't add anything positive to the issue. Radix is great, and this feature would be fantastic, but it is fundamentally a free service provided by people we can assume are not paid to do this.

Perhaps I've misread your tone, but I'm not sure what other purpose your message had?

I'm happy with the shadcn alternative which appears to retain the radix and accessibility benefits

kieranm commented 1 year ago

"Still waiting", "where is this", "me too" etc are unhelpful comments. I don't know how you meant it, but other people and the maintainers might think you are entitled and are likely to ignore you. It also notifies everyone subscribed and adds nothing we didn't already know. It is important to call it out because, if people don't, it just encourages others to add to the spam (as we can see above!).

Just leave an upvote on the main post like everyone else, please! Everyone here is very friendly (as this whole thread demonstrates) but also we should strive to keep the discussion high quality and it is absolutely right to give feedback with downvotes when people deviate from that.

t-keshi commented 12 months ago

I understand that my implementation might not be elegant, but it works well for my specific use case.

multi-select-example: https://codesandbox.io/p/sandbox/optimistic-edison-g98wgy

charrondev commented 10 months ago

Just a bit of an update since I last proposed an implementation and started working on it. I got a chunk of the way there but it's quite complex and I won't have time to get a draft PR up until Thanksgiving most likely.