diff --git a/app/assets/javascripts/analytics/shared/components/projects_dropdown_filter.vue b/app/assets/javascripts/analytics/shared/components/projects_dropdown_filter.vue
index 98193de4a12f7adc81ad16c98dd491031aa5ae3a..fc37e4139613ebff77fc976def86b081c0fa5ec6 100644
--- a/app/assets/javascripts/analytics/shared/components/projects_dropdown_filter.vue
+++ b/app/assets/javascripts/analytics/shared/components/projects_dropdown_filter.vue
@@ -1,14 +1,5 @@
 <script>
-import {
-  GlIcon,
-  GlLoadingIcon,
-  GlAvatar,
-  GlDropdown,
-  GlDropdownSectionHeader,
-  GlDropdownItem,
-  GlSearchBoxByType,
-  GlTruncate,
-} from '@gitlab/ui';
+import { GlButton, GlIcon, GlAvatar, GlCollapsibleListbox, GlTruncate } from '@gitlab/ui';
 import { debounce } from 'lodash';
 import { filterBySearchTerm } from '~/analytics/shared/utils';
 import { getIdFromGraphQLId } from '~/graphql_shared/utils';
@@ -18,17 +9,15 @@ import { n__, s__, __ } from '~/locale';
 import getProjects from '../graphql/projects.query.graphql';
 
 const sortByProjectName = (projects = []) => projects.sort((a, b) => a.name.localeCompare(b.name));
+const mapItemToListboxFormat = (item) => ({ ...item, value: item.id, text: item.name });
 
 export default {
   name: 'ProjectsDropdownFilter',
   components: {
+    GlButton,
     GlIcon,
-    GlLoadingIcon,
     GlAvatar,
-    GlDropdown,
-    GlDropdownSectionHeader,
-    GlDropdownItem,
-    GlSearchBoxByType,
+    GlCollapsibleListbox,
     GlTruncate,
   },
   props: {
@@ -94,6 +83,9 @@ export default {
     selectedProjectIds() {
       return this.selectedProjects.map((p) => p.id);
     },
+    selectedListBoxItems() {
+      return this.multiSelect ? this.selectedProjectIds : this.selectedProjectIds[0];
+    },
     hasSelectedProjects() {
       return Boolean(this.selectedProjects.length);
     },
@@ -110,6 +102,28 @@ export default {
     unselectedItems() {
       return this.availableProjects.filter(({ id }) => !this.selectedProjectIds.includes(id));
     },
+    selectedGroupOptions() {
+      return this.selectedItems.map(mapItemToListboxFormat);
+    },
+    unSelectedGroupOptions() {
+      return this.unselectedItems.map(mapItemToListboxFormat);
+    },
+    listBoxItems() {
+      if (this.selectedGroupOptions.length === 0) {
+        return this.unSelectedGroupOptions;
+      }
+
+      return [
+        {
+          text: __('Selected'),
+          options: this.selectedGroupOptions,
+        },
+        {
+          text: __('Unselected'),
+          options: this.unSelectedGroupOptions,
+        },
+      ];
+    },
   },
   watch: {
     searchTerm() {
@@ -129,32 +143,29 @@ export default {
     search: debounce(function debouncedSearch() {
       this.fetchData();
     }, DEFAULT_DEBOUNCE_AND_THROTTLE_MS),
-    getSelectedProjects(selectedProject, isSelected) {
-      return isSelected
-        ? this.selectedProjects.concat([selectedProject])
-        : this.selectedProjects.filter((project) => project.id !== selectedProject.id);
-    },
     singleSelectedProject(selectedObj, isMarking) {
       return isMarking ? [selectedObj] : [];
     },
-    setSelectedProjects(project) {
+    setSelectedProjects(payload) {
       this.selectedProjects = this.multiSelect
-        ? this.getSelectedProjects(project, !this.isProjectSelected(project))
-        : this.singleSelectedProject(project, !this.isProjectSelected(project));
+        ? payload
+        : this.singleSelectedProject(payload, !this.isProjectSelected(payload));
     },
-    onClick(project) {
+    onClick(projectId) {
+      const project = this.availableProjects.find(({ id }) => id === projectId);
       this.setSelectedProjects(project);
       this.handleUpdatedSelectedProjects();
     },
-    onMultiSelectClick(project) {
-      this.setSelectedProjects(project);
+    onMultiSelectClick(projectIds) {
+      const projects = this.availableProjects.filter(({ id }) => projectIds.includes(id));
+      this.setSelectedProjects(projects);
       this.isDirty = true;
     },
-    onSelected(project) {
+    onSelected(payload) {
       if (this.multiSelect) {
-        this.onMultiSelectClick(project);
+        this.onMultiSelectClick(payload);
       } else {
-        this.onClick(project);
+        this.onClick(payload);
       }
     },
     onHide() {
@@ -201,97 +212,65 @@ export default {
     getEntityId(project) {
       return getIdFromGraphQLId(project.id);
     },
+    setSearchTerm(val) {
+      this.searchTerm = val;
+    },
   },
   AVATAR_SHAPE_OPTION_RECT,
 };
 </script>
 <template>
-  <gl-dropdown
+  <gl-collapsible-listbox
     ref="projectsDropdown"
-    class="dropdown dropdown-projects"
     toggle-class="gl-shadow-none gl-mb-0"
+    :header-text="__('Projects')"
+    :items="listBoxItems"
+    :reset-button-label="__('Clear All')"
     :loading="loadingDefaultProjects"
-    :show-clear-all="hasSelectedProjects"
-    show-highlighted-items-title
-    highlighted-items-title-class="gl-p-3"
-    block
-    @clear-all.stop="onClearAll"
-    @hide="onHide"
+    :multiple="multiSelect"
+    :no-results-text="__('No matching results')"
+    :selected="selectedListBoxItems"
+    :searching="loading"
+    searchable
+    @hidden="onHide"
+    @reset="onClearAll"
+    @search="setSearchTerm"
+    @select="onSelected"
   >
-    <template #button-content>
-      <gl-loading-icon v-if="loadingDefaultProjects" class="gl-mr-2 gl-flex-shrink-0" />
-      <gl-avatar
-        v-if="isOnlyOneProjectSelected"
-        :src="selectedProjects[0].avatarUrl"
-        :entity-id="getEntityId(selectedProjects[0])"
-        :entity-name="selectedProjects[0].name"
-        :size="16"
-        :shape="$options.AVATAR_SHAPE_OPTION_RECT"
-        :alt="selectedProjects[0].name"
-        class="gl-display-inline-flex gl-vertical-align-middle gl-mr-2 gl-flex-shrink-0"
-      />
-      <gl-truncate :text="selectedProjectsLabel" class="gl-min-w-0 gl-flex-grow-1" />
-      <gl-icon class="gl-ml-2 gl-flex-shrink-0" name="chevron-down" />
-    </template>
-    <template #header>
-      <gl-dropdown-section-header>{{ __('Projects') }}</gl-dropdown-section-header>
-      <gl-search-box-by-type v-model.trim="searchTerm" :placeholder="__('Search')" />
-    </template>
-    <template #highlighted-items>
-      <gl-dropdown-item
-        v-for="project in selectedItems"
-        :key="project.id"
-        is-check-item
-        :is-checked="isProjectSelected(project)"
-        @click.native.capture.stop="onSelected(project)"
-      >
-        <div class="gl-display-flex">
-          <gl-avatar
-            class="gl-mr-2 gl-vertical-align-middle"
-            :alt="project.name"
-            :size="16"
-            :entity-id="getEntityId(project)"
-            :entity-name="project.name"
-            :src="project.avatarUrl"
-            :shape="$options.AVATAR_SHAPE_OPTION_RECT"
-          />
-          <div>
-            <div data-testid="project-name">{{ project.name }}</div>
-            <div class="gl-text-gray-500" data-testid="project-full-path">
-              {{ project.fullPath }}
-            </div>
-          </div>
-        </div>
-      </gl-dropdown-item>
+    <template #toggle>
+      <gl-button class="dropdown-projects">
+        <gl-avatar
+          v-if="isOnlyOneProjectSelected"
+          :src="selectedProjects[0].avatarUrl"
+          :entity-id="getEntityId(selectedProjects[0])"
+          :entity-name="selectedProjects[0].name"
+          :size="16"
+          :shape="$options.AVATAR_SHAPE_OPTION_RECT"
+          :alt="selectedProjects[0].name"
+          class="gl-display-inline-flex gl-vertical-align-middle gl-mr-2 gl-flex-shrink-0"
+        />
+        <gl-truncate :text="selectedProjectsLabel" class="gl-min-w-0 gl-flex-grow-1" />
+        <gl-icon class="gl-ml-2 gl-flex-shrink-0" name="chevron-down" />
+      </gl-button>
     </template>
-    <gl-dropdown-item
-      v-for="project in unselectedItems"
-      :key="project.id"
-      @click.native.capture.stop="onSelected(project)"
-    >
+    <template #list-item="{ item }">
       <div class="gl-display-flex">
         <gl-avatar
-          class="gl-mr-2 vertical-align-middle"
-          :alt="project.name"
+          class="gl-mr-2 gl-vertical-align-middle"
+          :alt="item.name"
           :size="16"
-          :entity-id="getEntityId(project)"
-          :entity-name="project.name"
-          :src="project.avatarUrl"
+          :entity-id="getEntityId(item)"
+          :entity-name="item.name"
+          :src="item.avatarUrl"
           :shape="$options.AVATAR_SHAPE_OPTION_RECT"
         />
         <div>
-          <div data-testid="project-name" data-qa-selector="project_name">{{ project.name }}</div>
+          <div data-testid="project-name" data-qa-selector="project_name">{{ item.name }}</div>
           <div class="gl-text-gray-500" data-testid="project-full-path">
-            {{ project.fullPath }}
+            {{ item.fullPath }}
           </div>
         </div>
       </div>
-    </gl-dropdown-item>
-    <gl-dropdown-item v-show="noResultsAvailable" class="gl-pointer-events-none text-secondary">{{
-      __('No matching results')
-    }}</gl-dropdown-item>
-    <gl-dropdown-item v-if="loading">
-      <gl-loading-icon size="lg" />
-    </gl-dropdown-item>
-  </gl-dropdown>
+    </template>
+  </gl-collapsible-listbox>
 </template>
diff --git a/ee/spec/features/groups/security/compliance_dashboards_spec.rb b/ee/spec/features/groups/security/compliance_dashboards_spec.rb
index 54a192cef535c4ac25f3c057158c2bffe5a4ae2a..a99338178054c5e4d1962ca52b5de8c75ef09c34 100644
--- a/ee/spec/features/groups/security/compliance_dashboards_spec.rb
+++ b/ee/spec/features/groups/security/compliance_dashboards_spec.rb
@@ -150,13 +150,13 @@ def set_date_range(start_date, end_date)
 
   def filter_by_project(project)
     page.within('[data-testid="violations-project-dropdown"]') do
-      find('.dropdown-toggle').click
+      find('.dropdown-projects').click
 
       find('input[aria-label="Search"]').set(project.name)
       wait_for_requests
 
-      find('.dropdown-item').click
-      find('.dropdown-toggle').click
+      find('.gl-new-dropdown-item[role="option"]').click
+      find('.dropdown-projects').click
     end
 
     page.find('body').click
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 4f0d8ba9d27ffceaed82ac89cc009ab1a19df909..03d6062830530287a9ab2668a5cba15bc4429b80 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -9684,6 +9684,9 @@ msgid_plural "Clear %{count} images from cache?"
 msgstr[0] ""
 msgstr[1] ""
 
+msgid "Clear All"
+msgstr ""
+
 msgid "Clear all repository checks"
 msgstr ""
 
@@ -41512,6 +41515,9 @@ msgstr ""
 msgid "Select type"
 msgstr ""
 
+msgid "Selected"
+msgstr ""
+
 msgid "Selected commits"
 msgstr ""
 
@@ -48066,6 +48072,9 @@ msgstr ""
 msgid "Unselect all"
 msgstr ""
 
+msgid "Unselected"
+msgstr ""
+
 msgid "Unstar"
 msgstr ""
 
diff --git a/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js b/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js
index 33801fb8552ed43ddcd7dac77db12742412f1545..364f0a2e372e256923f5fff4d01ebb21ff6dad0e 100644
--- a/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js
+++ b/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js
@@ -1,7 +1,6 @@
-import { GlDropdown, GlDropdownItem, GlTruncate, GlSearchBoxByType } from '@gitlab/ui';
+import { GlButton, GlTruncate, GlCollapsibleListbox, GlListboxItem, GlAvatar } from '@gitlab/ui';
 import { nextTick } from 'vue';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
-import { stubComponent } from 'helpers/stub_component';
+import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
 import { TEST_HOST } from 'helpers/test_constants';
 import waitForPromises from 'helpers/wait_for_promises';
 import ProjectsDropdownFilter from '~/analytics/shared/components/projects_dropdown_filter.vue';
@@ -28,18 +27,6 @@ const projects = [
   },
 ];
 
-const MockGlDropdown = stubComponent(GlDropdown, {
-  template: `
-  <div>
-    <slot name="header"></slot>
-    <div data-testid="vsa-highlighted-items">
-      <slot name="highlighted-items"></slot>
-    </div>
-    <div data-testid="vsa-default-items"><slot></slot></div>
-  </div>
-  `,
-});
-
 const defaultMocks = {
   $apollo: {
     query: jest.fn().mockResolvedValue({
@@ -53,42 +40,36 @@ let spyQuery;
 describe('ProjectsDropdownFilter component', () => {
   let wrapper;
 
-  const createComponent = (props = {}, stubs = {}) => {
+  const createComponent = ({ mountFn = shallowMountExtended, props = {}, stubs = {} } = {}) => {
     spyQuery = defaultMocks.$apollo.query;
-    wrapper = mountExtended(ProjectsDropdownFilter, {
+    wrapper = mountFn(ProjectsDropdownFilter, {
       mocks: { ...defaultMocks },
       propsData: {
         groupId: 1,
         groupNamespace: 'gitlab-org',
         ...props,
       },
-      stubs,
+      stubs: {
+        GlButton,
+        GlCollapsibleListbox,
+        ...stubs,
+      },
     });
   };
 
-  const createWithMockDropdown = (props) => {
-    createComponent(props, { GlDropdown: MockGlDropdown });
-    return waitForPromises();
-  };
-
-  const findHighlightedItems = () => wrapper.findByTestId('vsa-highlighted-items');
-  const findUnhighlightedItems = () => wrapper.findByTestId('vsa-default-items');
-  const findClearAllButton = () => wrapper.findByText('Clear all');
+  const findClearAllButton = () => wrapper.findByTestId('listbox-reset-button');
   const findSelectedProjectsLabel = () => wrapper.findComponent(GlTruncate);
 
-  const findDropdown = () => wrapper.findComponent(GlDropdown);
+  const findDropdown = () => wrapper.findComponent(GlCollapsibleListbox);
 
-  const findDropdownItems = () =>
-    findDropdown()
-      .findAllComponents(GlDropdownItem)
-      .filter((w) => w.text() !== 'No matching results');
+  const findDropdownItems = () => findDropdown().findAllComponents(GlListboxItem);
 
   const findDropdownAtIndex = (index) => findDropdownItems().at(index);
 
-  const findDropdownButton = () => findDropdown().find('.dropdown-toggle');
+  const findDropdownButton = () => findDropdown().findComponent(GlButton);
   const findDropdownButtonAvatar = () => findDropdown().find('.gl-avatar');
   const findDropdownButtonAvatarAtIndex = (index) =>
-    findDropdownAtIndex(index).find('img.gl-avatar');
+    findDropdownAtIndex(index).findComponent(GlAvatar);
   const findDropdownButtonIdentIconAtIndex = (index) =>
     findDropdownAtIndex(index).find('div.gl-avatar-identicon');
 
@@ -97,13 +78,15 @@ describe('ProjectsDropdownFilter component', () => {
   const findDropdownFullPathAtIndex = (index) =>
     findDropdownAtIndex(index).find('[data-testid="project-full-path"]');
 
-  const selectDropdownItemAtIndex = async (index) => {
-    findDropdownAtIndex(index).find('button').trigger('click');
+  const selectDropdownItemAtIndex = async (indexes, multi = true) => {
+    const payload = indexes.map((index) => projects[index]?.id).filter(Boolean);
+    findDropdown().vm.$emit('select', multi ? payload : payload[0]);
     await nextTick();
   };
 
   // NOTE: Selected items are now visually separated from unselected items
-  const findSelectedDropdownItems = () => findHighlightedItems().findAllComponents(GlDropdownItem);
+  const findSelectedDropdownItems = () =>
+    findDropdownItems().filter((component) => component.props('isSelected') === true);
 
   const findSelectedDropdownAtIndex = (index) => findSelectedDropdownItems().at(index);
   const findSelectedButtonIdentIconAtIndex = (index) =>
@@ -111,22 +94,20 @@ describe('ProjectsDropdownFilter component', () => {
   const findSelectedButtonAvatarItemAtIndex = (index) =>
     findSelectedDropdownAtIndex(index).find('img.gl-avatar');
 
-  const selectedIds = () => wrapper.vm.selectedProjects.map(({ id }) => id);
-
-  const findSearchBoxByType = () => wrapper.findComponent(GlSearchBoxByType);
-
   describe('queryParams are applied when fetching data', () => {
     beforeEach(() => {
       createComponent({
-        queryParams: {
-          first: 50,
-          includeSubgroups: true,
+        props: {
+          queryParams: {
+            first: 50,
+            includeSubgroups: true,
+          },
         },
       });
     });
 
     it('applies the correct queryParams when making an api call', async () => {
-      findSearchBoxByType().vm.$emit('input', 'gitlab');
+      findDropdown().vm.$emit('search', 'gitlab');
 
       expect(spyQuery).toHaveBeenCalledTimes(1);
 
@@ -147,17 +128,19 @@ describe('ProjectsDropdownFilter component', () => {
     const blockDefaultProps = { multiSelect: true };
 
     beforeEach(() => {
-      createComponent(blockDefaultProps);
+      createComponent({
+        props: blockDefaultProps,
+      });
     });
 
     describe('with no project selected', () => {
-      it('does not render the highlighted items', async () => {
-        await createWithMockDropdown(blockDefaultProps);
-
-        expect(findSelectedDropdownItems().length).toBe(0);
+      it('does not render the highlighted items', () => {
+        expect(findSelectedDropdownItems()).toHaveLength(0);
       });
 
       it('renders the default project label text', () => {
+        createComponent({ mountFn: mountExtended, props: blockDefaultProps });
+
         expect(findSelectedProjectsLabel().text()).toBe('Select projects');
       });
 
@@ -167,18 +150,21 @@ describe('ProjectsDropdownFilter component', () => {
     });
 
     describe('with a selected project', () => {
-      beforeEach(async () => {
-        await selectDropdownItemAtIndex(0);
+      beforeEach(() => {
+        createComponent({
+          mountFn: mountExtended,
+        });
       });
 
       it('renders the highlighted items', async () => {
-        await createWithMockDropdown(blockDefaultProps);
-        await selectDropdownItemAtIndex(0);
+        await selectDropdownItemAtIndex([0], false);
 
-        expect(findSelectedDropdownItems().length).toBe(1);
+        expect(findSelectedDropdownItems()).toHaveLength(1);
       });
 
-      it('renders the highlighted items title', () => {
+      it('renders the highlighted items title', async () => {
+        await selectDropdownItemAtIndex([0], false);
+
         expect(findSelectedProjectsLabel().text()).toBe(projects[0].name);
       });
 
@@ -187,11 +173,17 @@ describe('ProjectsDropdownFilter component', () => {
       });
 
       it('clears all selected items when the clear all button is clicked', async () => {
-        await selectDropdownItemAtIndex(1);
+        createComponent({
+          mountFn: mountExtended,
+          props: { multiSelect: true },
+        });
+        await waitForPromises();
+
+        await selectDropdownItemAtIndex([0, 1]);
 
         expect(findSelectedProjectsLabel().text()).toBe('2 projects selected');
 
-        await findClearAllButton().trigger('click');
+        await findClearAllButton().vm.$emit('click');
 
         expect(findSelectedProjectsLabel().text()).toBe('Select projects');
       });
@@ -200,27 +192,35 @@ describe('ProjectsDropdownFilter component', () => {
 
   describe('with a selected project and search term', () => {
     beforeEach(async () => {
-      await createWithMockDropdown({ multiSelect: true });
+      createComponent({
+        props: { multiSelect: true },
+      });
+      await waitForPromises();
 
-      selectDropdownItemAtIndex(0);
-      findSearchBoxByType().vm.$emit('input', 'this is a very long search string');
+      await selectDropdownItemAtIndex([0]);
+
+      findDropdown().vm.$emit('search', 'this is a very long search string');
     });
 
     it('renders the highlighted items', () => {
-      expect(findUnhighlightedItems().findAll('li').length).toBe(1);
+      expect(findSelectedDropdownItems()).toHaveLength(1);
     });
 
     it('hides the unhighlighted items that do not match the string', () => {
-      expect(findUnhighlightedItems().findAll('li').length).toBe(1);
-      expect(findUnhighlightedItems().text()).toContain('No matching results');
+      expect(wrapper.find(`[name="Selected"]`).findAllComponents(GlListboxItem).length).toBe(1);
+      expect(wrapper.find(`[name="Unselected"]`).findAllComponents(GlListboxItem).length).toBe(0);
     });
   });
 
   describe('when passed an array of defaultProject as prop', () => {
-    beforeEach(() => {
+    beforeEach(async () => {
       createComponent({
-        defaultProjects: [projects[0]],
+        mountFn: mountExtended,
+        props: {
+          defaultProjects: [projects[0]],
+        },
       });
+      await waitForPromises();
     });
 
     it("displays the defaultProject's name", () => {
@@ -232,14 +232,18 @@ describe('ProjectsDropdownFilter component', () => {
     });
 
     it('marks the defaultProject as selected', () => {
-      expect(findDropdownAtIndex(0).props('isChecked')).toBe(true);
+      expect(
+        wrapper.findAll('[role="group"]').at(0).findAllComponents(GlListboxItem).at(0).text(),
+      ).toContain(projects[0].name);
     });
   });
 
   describe('when multiSelect is false', () => {
     const blockDefaultProps = { multiSelect: false };
     beforeEach(() => {
-      createComponent(blockDefaultProps);
+      createComponent({
+        props: blockDefaultProps,
+      });
     });
 
     describe('displays the correct information', () => {
@@ -248,13 +252,12 @@ describe('ProjectsDropdownFilter component', () => {
       });
 
       it('renders an avatar when the project has an avatarUrl', () => {
-        expect(findDropdownButtonAvatarAtIndex(0).exists()).toBe(true);
+        expect(findDropdownButtonAvatarAtIndex(0).props('src')).toBe(projects[0].avatarUrl);
         expect(findDropdownButtonIdentIconAtIndex(0).exists()).toBe(false);
       });
 
-      it("renders an identicon when the project doesn't have an avatarUrl", () => {
-        expect(findDropdownButtonAvatarAtIndex(1).exists()).toBe(false);
-        expect(findDropdownButtonIdentIconAtIndex(1).exists()).toBe(true);
+      it("does not render an avatar when the project doesn't have an avatarUrl", () => {
+        expect(findDropdownButtonAvatarAtIndex(1).props('src')).toEqual(null);
       });
 
       it('renders the project name', () => {
@@ -271,37 +274,46 @@ describe('ProjectsDropdownFilter component', () => {
     });
 
     describe('on project click', () => {
-      it('should emit the "selected" event with the selected project', () => {
-        selectDropdownItemAtIndex(0);
+      it('should emit the "selected" event with the selected project', async () => {
+        await selectDropdownItemAtIndex([0], false);
 
-        expect(wrapper.emitted().selected).toEqual([[[projects[0]]]]);
+        expect(wrapper.emitted('selected')).toEqual([[[projects[0]]]]);
       });
 
       it('should change selection when new project is clicked', () => {
-        selectDropdownItemAtIndex(1);
+        selectDropdownItemAtIndex([1], false);
 
-        expect(wrapper.emitted().selected).toEqual([[[projects[1]]]]);
+        expect(wrapper.emitted('selected')).toEqual([[[projects[1]]]]);
       });
 
-      it('selection should be emptied when a project is deselected', () => {
-        selectDropdownItemAtIndex(0); // Select the item
-        selectDropdownItemAtIndex(0); // deselect it
+      it('selection should be emptied when a project is deselected', async () => {
+        await selectDropdownItemAtIndex([0], false); // Select the item
+        await selectDropdownItemAtIndex([0], false);
 
-        expect(wrapper.emitted().selected).toEqual([[[projects[0]]], [[]]]);
+        expect(wrapper.emitted('selected')).toEqual([[[projects[0]]], [[]]]);
       });
 
       it('renders an avatar in the dropdown button when the project has an avatarUrl', async () => {
-        await createWithMockDropdown(blockDefaultProps);
-        await selectDropdownItemAtIndex(0);
+        createComponent({
+          mountFn: mountExtended,
+          props: blockDefaultProps,
+        });
+        await waitForPromises();
+
+        await selectDropdownItemAtIndex([0], false);
 
         expect(findSelectedButtonAvatarItemAtIndex(0).exists()).toBe(true);
         expect(findSelectedButtonIdentIconAtIndex(0).exists()).toBe(false);
       });
 
       it("renders an identicon in the dropdown button when the project doesn't have an avatarUrl", async () => {
-        await createWithMockDropdown(blockDefaultProps);
-        await selectDropdownItemAtIndex(1);
+        createComponent({
+          mountFn: mountExtended,
+          props: blockDefaultProps,
+        });
+        await waitForPromises();
 
+        await selectDropdownItemAtIndex([1], false);
         expect(findSelectedButtonAvatarItemAtIndex(0).exists()).toBe(false);
         expect(findSelectedButtonIdentIconAtIndex(0).exists()).toBe(true);
       });
@@ -310,7 +322,9 @@ describe('ProjectsDropdownFilter component', () => {
 
   describe('when multiSelect is true', () => {
     beforeEach(() => {
-      createComponent({ multiSelect: true });
+      createComponent({
+        props: { multiSelect: true },
+      });
     });
 
     describe('displays the correct information', () => {
@@ -319,13 +333,12 @@ describe('ProjectsDropdownFilter component', () => {
       });
 
       it('renders an avatar when the project has an avatarUrl', () => {
-        expect(findDropdownButtonAvatarAtIndex(0).exists()).toBe(true);
+        expect(findDropdownButtonAvatarAtIndex(0).props('src')).toBe(projects[0].avatarUrl);
         expect(findDropdownButtonIdentIconAtIndex(0).exists()).toBe(false);
       });
 
       it("renders an identicon when the project doesn't have an avatarUrl", () => {
-        expect(findDropdownButtonAvatarAtIndex(1).exists()).toBe(false);
-        expect(findDropdownButtonIdentIconAtIndex(1).exists()).toBe(true);
+        expect(findDropdownButtonAvatarAtIndex(1).props('src')).toEqual(null);
       });
 
       it('renders the project name', () => {
@@ -342,27 +355,31 @@ describe('ProjectsDropdownFilter component', () => {
     });
 
     describe('on project click', () => {
-      it('should add to selection when new project is clicked', () => {
-        selectDropdownItemAtIndex(0);
-        selectDropdownItemAtIndex(1);
+      it('should add to selection when new project is clicked', async () => {
+        await selectDropdownItemAtIndex([0, 1]);
 
-        expect(selectedIds()).toEqual([projects[0].id, projects[1].id]);
+        expect(findSelectedDropdownItems().at(0).text()).toContain(projects[1].name);
+        expect(findSelectedDropdownItems().at(1).text()).toContain(projects[0].name);
       });
 
-      it('should remove from selection when clicked again', () => {
-        selectDropdownItemAtIndex(0);
+      it('should remove from selection when clicked again', async () => {
+        await selectDropdownItemAtIndex([0]);
 
-        expect(selectedIds()).toEqual([projects[0].id]);
+        expect(findSelectedDropdownItems().at(0).text()).toContain(projects[0].name);
 
-        selectDropdownItemAtIndex(0);
+        await selectDropdownItemAtIndex([]);
 
-        expect(selectedIds()).toEqual([]);
+        expect(findSelectedDropdownItems()).toHaveLength(0);
       });
 
       it('renders the correct placeholder text when multiple projects are selected', async () => {
-        selectDropdownItemAtIndex(0);
-        selectDropdownItemAtIndex(1);
-        await nextTick();
+        createComponent({
+          props: { multiSelect: true },
+          mountFn: mountExtended,
+        });
+        await waitForPromises();
+
+        await selectDropdownItemAtIndex([0, 1]);
 
         expect(findDropdownButton().text()).toBe('2 projects selected');
       });