Combobox
vs. Multi-Select vs. Listbox vs. Dual Listbox? How they are different,
what purpose they serve, and how to choose the right one. Brought to you
by Design Patterns For AI Interfaces, friendly video courses on UX and design patterns by Vitaly.
So
what’s the difference between combobox, multiselect, listbox, and
dropdown? While all these UI components might appear similar, they serve
different purposes. The choice often comes down to the number of available options and their visibility.
Let’s see how they differ, what purpose they serve, and how to choose the right one — avoiding misunderstandings and wrong expectations along the way.
And the confusion begins: Listbox, Combobox, Multiselect, Dual Listbox.
Not All List Patterns Are The Same
All
the UI components highlighted above have exactly one thing in
common: they support users’ interactions with lists. However, they do so
slightly differently.
Let’s take a look at each, one by one:
Dropdown → list is hidden until it’s triggered.
Combobox → type to filter + select 1 option.
Multiselect → type to filter + select many options.
Listbox → all list options visible by default (+ scroll).
Dual listbox → move items between 2 listboxes.
Watson design system with grouping inside of its combobox pattern.
In other words, Combobox combines a text input field with a dropdown list, so users can type to filter and select a single option. With Multiselect, users can select many options (often displayed as pills or chips).
Listboxes display all list options visible by default, often with scrolling. It’s helpful when users need to see all available choices immediately. Dual listbox (also called transfer list) is a variation of a listbox that allows users to move items between two listboxes (left ↔ right), typically for bulk selection.
Never Hide Frequently Used Options
As mentioned above, the choice of the right UI component depends on 2 factors:
how many list options are available, and if all these options need to
be visible by default. All lists could have tree structures, nesting,
and group selection, too.
There is one principle that I’ve been following for years for any UI component: never hide frequently used options. If users rely on a particular selection frequently, there is very little value in hiding it from them.
We could either make it pre-selected, or (if there are only 2–3 frequently used options) show them as chips or buttons,
and then show the rest of the list on interaction. In general, it’s a
good idea to always display popular options — even if it might clutter
the UI.
How To Choose Which?
Not every list needs a complex selection method. For lists with fewer than 5 items, simple radio buttons or checkboxes usually work best. But if users need to select from a large list of options (e.g., 200+ items), combobox + multiselect are helpful because of the faster filtering (e.g., country selection).
A matrix of options, broken down by single- or multi-selection and static or scrollable view. By Anna Kaley, from NN/g.
Listboxes are helpful when people need to access many options at once, especially if they need to choose many options from that list as well. They could be helpful for frequently used filters.
Dual
listbox in action: it can be very helpful when assigning tasks or
permissions. That’s why it’s “Transfer List”. Example from Mantine.
Dual listbox
is often overlooked and ignored. But it can be very helpful for complex
tasks, e..g bulk selection, or assigning roles, tasks,
responsibilities. It’s the only UI component that allows users to review
their full selection list side-by-side with the source list before
committing (also called “Transfer list”).
In fact, dual listbox is often faster, more accurate, and more accessible than drag-and-drop.
Usability Considerations
One important note to keep in mind is that all list types need to support keyboard navigation
(e.g., ↑/↓ arrow keys) for accessibility. Some people will almost
always rely uponthe keyboard to select options once they start typing.
Keyboard navigation is often in use with any kind of lists. Example: Watson.
Beyond that:
For lists with 7+ options, consider adding “Select All” and “Clear All” functionalities to streamline user interaction.
For lengthy lists with a combobox, expose all options to users on click/tap, as otherwise they might never be seen,
Most important, don’t display non-interactive elements as buttons to avoid confusion — and don’t display interactive elements as static labels.
Wrapping Up: Not Everything Is A Dropdown
Names matter. A vertical list of options is typically described as a “dropdown” — but often it’s a bit too generic to be meaningful. “Dropdown” hints that the list is hidden by default. “Multiselect” implies multi-selection (checkbox) within a list. “Combobox” implies text input. And “Listbox” is simply a list of selectable items, visible at all times.
The goal isn’t to be consistent with the definitions above for the sake of it. But rather to align intentions — speak the same language when deciding on, designing, building, and then using these UI components.
It should work for everyone
— designers, engineers, and end users — as long as static labels don’t
look like interactive buttons, and radio buttons don’t act like
checkboxes.
AI
coding tools like agents can be valuable allies in everyday development
work. They help handle time-consuming grunt work, guide you through
large legacy codebases, and offer low-risk ways to implement features in
previously unfamiliar programming languages. Here are practical,
easy-to-apply techniques to help you use these tools to improve your
workflow.
Over the last two years, my team at Work & Co
and I have been testing out and gradually integrating AI coding tools
like Copilot, Cursor, Claude, and ChatGPT to help us ship web
experiences that are used by the masses. Admittedly, after some initial
skepticism and a few aha moments, various AI tools have found their way
into my daily use. Over time, the list of applications where we found it
made sense to let AI take over started to grow, so I decided to share
some practical use cases for AI tools for what I call the “responsible developer”.
What do I mean by a responsible developer?
We
have to make sure that we deliver quality code as expected by our
stakeholders and clients. Our contributions (i.e., pull requests) should
not become a burden on our colleagues who will have to review and test
our work. Also, in case you work for a company: The tools we use need to
be approved by our employer. Sensitive aspects like security and
privacy need to be handled properly: Don’t paste secrets, customer data
(PII), or proprietary code into tools without policy approval. Treat it
like code from a stranger on the internet. Always test and verify.
Note: This
article assumes some very basic familiarity with AI coding tools like
Copilot inside VSCode or Cursor. If all of this sounds totally new and
unfamiliar to you, the Github Copilot video tutorials can be a fantastic starting point for you.
View of VSCode with Copilot Chat open in the right panel.
Helpful Applications Of AI Coding Tools
Note: The following examples will mainly focus on working in JavaScript-based web applications like React, Vue, Svelte, or Angular.
Getting An Understanding Of An Unfamiliar Codebase #
It’s
not uncommon to work on established codebases, and joining a large
legacy codebase can be intimidating. Simply open your project and your
AI agent (in my case, Copilot Chat in VSCode) and start asking questions
just like you would ask a colleague. In general, I like to talk to any
AI agent just as I would to a fellow human.
Here is a more refined example prompt:
“Give
me a high-level architecture overview: entrypoints, routing, auth, data
layer, build tooling. Then list 5 files to read in order. Treat
explanations as hypotheses and confirm by jumping to referenced files.”
You can keep asking follow-up questions like “How does the routing work in detail?” or “Talk me through the authentication process and methods” and it will lead you to helpful directions to shine some light into the dark of an unfamiliar codebase.
Triaging Breaking Changes When Upgrading Dependencies
Updating
npm packages, especially when they come with breaking changes, can be
tedious and time-consuming work, and make you debug a fair amount of
regressions. I recently had to upgrade the data visualization library plotly.js
up one major release version from version 2 to 3, and as a result of
that, the axis labeling in some of the graphs stopped working.
I went on to ask ChatGPT:
“I
updated my Angular project that uses Plotly. I updated the plotly.js —
dist package from version 2.35.2 to 3.1.0 — and now the labels on the x
and y axis are gone. What happened?”
The agent came back with a solution promptly (see for yourself below).
Note: I still verified the explanation against the official migration guide before shipping the fix.
Replicating Refactors Safely Across Files
Growing
codebases most certainly unveil opportunities for code consolidation.
For example, you notice code duplication across files that can be
extracted into a single function or component. As a result, you decide
to create a shared component that can be included instead and perform
that refactor in one file. Now, instead of manually carrying out those
changes to your remaining files, you ask your agent to roll out the
refactor for you.
Agents let you select multiple files as context.
Once the refactor for one file is done, I can add both the refactored
and untouched files into context and prompt the agent to roll out the
changes to other files like this: “Replicate the changes I made in file A to file B as well”.
Implementing Features In Unfamiliar Technologies
One
of my favorite aha-moments using AI coding tools was when it helped me
create a quite complex animated gradient animation in GLSL, a language I
have been fairly unfamiliar with. On a recent project, our designers
came up with an animated gradient as a loading state on a 3D object. I
really liked the concept and wanted to deliver something unique and
exciting to our clients. The problem: I only had two days to implement
it, and GLSL has quite the steep learning curve.
Again, an AI tool
(in this case, ChatGPT) came in handy, and I started quite simply
prompting it to create a standalone HTML file for me that renders a
canvas and a very simple animated color gradient. Step after step, I
prompted the AI to add more finesse to it until I arrived at a decent
result so I could start integrating the shader into my actual codebase.
The end result: Our clients were super happy, and we delivered a complex feature in a small amount of time thanks to AI.
Writing Tests
In
my experience, there’s rarely enough time on projects to continuously
write and maintain a proper suite of unit and integration tests, and on
top of that, many developers don’t really enjoy the task of writing
tests. Prompting your AI helper to set up and write tests for you is
entirely possible and can be done in a small amount of time. Of course,
you, as a developer, should still make sure that your tests actually
take a look at the critical parts of your application and follow
sensible testing principles, but you can “outsource” the writing of the
tests to our AI helper.
Example prompt:
“Write unit tests for this function using Jest. Cover happy path, edge cases, and failure modes. Explain why each test exists.”
You can even pass along testing guru Kent C. Dodds’ testing best practices as guidelines to your agent, like below:
Somewhat
similar to the shader example mentioned earlier, I was recently tasked
to analyze code duplication in a codebase and compare before and after a
refactor. Certainly not a trivial task if you don’t want to go the
time-consuming route of comparing files manually. With the help of
Copilot, I created a script that analyzed code duplication for me,
arranged and ordered the output in a table, and exported it to Excel.
Then I took it a step further. When our code refactor was done, I
prompted the agent to take my existing Excel sheet as the baseline, add
in the current state of duplication in separate columns, and calculate
the delta.
Updating Code Written A Long Time Ago
Recently, an old client of mine hit me up, as over time, a few features weren’t working properly on his website anymore.
The
catch: The website was built almost ten years ago, and the JavaScript
and SCSS were using rather old compile tools like requireJS, and the
setup required an older version of Node.js that wouldn’t even run on my
2025 MacBook.
Updating the whole build process by hand would have taken me days, so I decided to prompt the AI agent, “Can you update the JS and SCSS build process to a lean 2025 stack like Vite?”
It sure did, and after around an hour of refining with the agent, I had
my SCSS and JS build switched to Vite, and I was able to focus on
actual bugfixing. Just make sure to properly validate the output and
compiled files when doing such integral changes to your build process.
Summarizing And Drafting
Would
you like to summarize all your recent code changes in one sentence for a
commit message, or have a long list of commits and would like to sum
them up in three bullet points? No problem, let the AI take care of it,
but please make sure to proofread it.
An example prompt is as simple as messaging a fellow human: “Please sum up my recent changes in concise bullet points”.
My
advice here would be to use GPT for writing with caution, and as with
code, please check the output before sending or submitting.
Recommendations And Best Practices
Prompting
One
of the not-so-obvious benefits of using AI is that the more specific
and tailored your prompts are, the better the output. The process of
prompting an AI agent forces us to formulate our requirements as specifically as possible before we write and code. This is why, as a general rule, I highly recommend being as specific as possible with your prompting.
Ryan
Florence, co-author of Remix, suggests a simple yet powerful way to
improve this process by finishing your initial prompt with the sentence:
“Before we start, do you have any questions for me?”
At
this point, the AI usually comes back with helpful questions where you
can clarify your specific intent, guiding the agent to provide you with a
more tailored approach for your task.
Using
version control like git not only comes in handy when collaborating as a
team on a single codebase but also to provide you as an individual
contributor with stable points to roll back to in case of an emergency.
Due to its non-deterministic nature, AI can sometimes go rogue and make
changes that are simply not helpful for what you are trying to achieve
and eventually break things irreparably.
Splitting up your work into multiple commits
will help you create stable points that you can revert to in case
things go sideways. And your teammates will thank you as well, as they
will have an easier time reviewing your code when it is split up into
semantically well-structured chunks.
This
is more of a general best practice, but in my opinion, it becomes even
more important when using AI tools for development work: Be the first critical reviewer of your code.
Make sure to take some time to go over your changes line by line, just
like you would review someone else’s code, and only submit your work
once it passes your own self-review.
“Two things are both
true to me right now: AI agents are amazing and a huge productivity
boost. They are also massive slop machines if you turn off your brain
and let go completely.”
In
my opinion, AI coding tools can improve our productivity as developers
on a daily basis and free up mental capacity for more planning and
high-level thinking. They force us to articulate our desired outcome
with meticulous detail.
Any AI can, at times, hallucinate, which
basically means it lies in a confident tone. So please make sure to
check and test, especially when you are in doubt. AI is not a silver
bullet, and I believe, excellence and the ability to solve problems as a
developer will never go out of fashion.
For developers who are
just starting out in their career these tools can be highly tempting to
do the majority of the work for them. What may get lost here is the
often draining and painful work through bugs and issues that are tricky
to debug and solve, aka “the grind”. Even Cursor AI’s very own Lee
Robinson questions this in one of his posts:
AI
coding tools are evolving at a fast pace, and I am excited for what
will come next. I hope you found this article and its tips helpful and
are excited to try out some of these for yourself.