diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index 386ed6bd0a1945e0eddf2d4a10d25441d499821d..d7aea7b7290d206cd75f5e3253131a4bbb890f78 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -2,7 +2,7 @@
 import { GlModal, GlAlert } from '@gitlab/ui';
 import { mapGetters, mapActions, mapState } from 'vuex';
 import ListLabel from '~/boards/models/label';
-import { TYPE_ITERATION, TYPE_MILESTONE, TYPE_USER } from '~/graphql_shared/constants';
+import { TYPE_ITERATION, TYPE_MILESTONE } from '~/graphql_shared/constants';
 import { convertToGraphQLId } from '~/graphql_shared/utils';
 import { getParameterByName, visitUrl } from '~/lib/utils/url_utility';
 import { __, s__ } from '~/locale';
@@ -21,7 +21,6 @@ const boardDefaults = {
   milestone_id: undefined,
   iteration_id: undefined,
   assignee: {},
-  assignee_id: undefined,
   weight: null,
   hide_backlog_list: false,
   hide_closed_list: false,
@@ -190,9 +189,7 @@ export default {
     issueBoardScopeMutationVariables() {
       return {
         weight: this.board.weight,
-        assigneeId: this.board.assignee?.id
-          ? convertToGraphQLId(TYPE_USER, this.board.assignee.id)
-          : null,
+        assigneeId: this.board.assignee?.id || null,
         milestoneId:
           this.board.milestone?.id || this.board.milestone?.id === 0
             ? convertToGraphQLId(TYPE_MILESTONE, this.board.milestone.id)
@@ -306,6 +303,11 @@ export default {
         }
       });
     },
+    setAssignee(assigneeId) {
+      this.board.assignee = {
+        id: assigneeId,
+      };
+    },
   },
 };
 </script>
@@ -373,6 +375,7 @@ export default {
         :weights="weights"
         @set-iteration="setIteration"
         @set-board-labels="setBoardLabels"
+        @set-assignee="setAssignee"
       />
     </form>
   </gl-modal>
diff --git a/app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql b/app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..e345fe97281bee5b14c165a4f44a3f00f9a9dcea
--- /dev/null
+++ b/app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql
@@ -0,0 +1,15 @@
+#import "../fragments/user.fragment.graphql"
+#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
+
+query usersSearch($search: String!, $fullPath: ID!) {
+  workspace: group(fullPath: $fullPath) {
+    users: groupMembers(search: $search, relations: [DIRECT, INHERITED]) {
+      nodes {
+        user {
+          ...User
+          ...UserAvailability
+        }
+      }
+    }
+  }
+}
diff --git a/ee/app/assets/javascripts/boards/components/assignee_select.vue b/ee/app/assets/javascripts/boards/components/assignee_select.vue
index 21a40e94e8b598b298552032b9d42e634fe6af68..40adb8673153e6d42d19b6adb15809ed61b92b7c 100644
--- a/ee/app/assets/javascripts/boards/components/assignee_select.vue
+++ b/ee/app/assets/javascripts/boards/components/assignee_select.vue
@@ -1,21 +1,34 @@
 <script>
-import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
-import UsersSelect from '~/users_select';
+import {
+  GlButton,
+  GlDropdown,
+  GlDropdownForm,
+  GlDropdownDivider,
+  GlDropdownItem,
+  GlSearchBoxByType,
+  GlLoadingIcon,
+} from '@gitlab/ui';
+import { isEmpty } from 'lodash';
+import { mapActions, mapGetters } from 'vuex';
+import searchGroupUsers from '~/graphql_shared/queries/group_users_search.query.graphql';
+import searchProjectUsers from '~/graphql_shared/queries/users_search.query.graphql';
+import { s__ } from '~/locale';
+import { ASSIGNEES_DEBOUNCE_DELAY } from '~/sidebar/constants';
 import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
 
 export default {
   components: {
     UserAvatarImage,
+    GlButton,
+    GlDropdown,
+    GlDropdownForm,
+    GlDropdownDivider,
+    GlDropdownItem,
+    GlSearchBoxByType,
     GlLoadingIcon,
-    GlIcon,
   },
+  inject: ['fullPath'],
   props: {
-    anyUserText: {
-      type: String,
-      required: false,
-      default: __('Any user'),
-    },
     board: {
       type: Object,
       required: true,
@@ -25,150 +38,200 @@ export default {
       required: false,
       default: false,
     },
-    fieldName: {
-      type: String,
-      required: true,
-    },
     groupId: {
       type: Number,
       required: false,
       default: 0,
     },
-    label: {
-      type: String,
-      required: true,
-    },
-    placeholderText: {
-      type: String,
-      required: false,
-      default: __('Select user'),
-    },
     projectId: {
       type: Number,
       required: false,
       default: 0,
     },
-    selected: {
-      type: Object,
-      required: false,
-      default: () => null,
-    },
-    wrapperClass: {
-      type: String,
-      required: false,
-      default: '',
+  },
+  data() {
+    return {
+      search: '',
+      searchUsers: [],
+      selected: this.board.assignee,
+      isEditing: false,
+      isDropdownShowing: false,
+    };
+  },
+  apollo: {
+    searchUsers: {
+      query() {
+        return this.isProjectBoard ? searchProjectUsers : searchGroupUsers;
+      },
+      variables() {
+        return {
+          fullPath: this.fullPath,
+          search: this.search,
+          first: 20,
+        };
+      },
+      skip() {
+        return !this.isEditing;
+      },
+      update(data) {
+        // TODO Remove null filter (BE fix required)
+        // https://gitlab.com/gitlab-org/gitlab/-/issues/329750
+        return data.workspace?.users?.nodes.filter((x) => x?.user).map(({ user }) => user) || [];
+      },
+      debounce: ASSIGNEES_DEBOUNCE_DELAY,
+      error() {
+        this.setError({ message: this.$options.i18n.errorSearchingUsers });
+      },
     },
   },
   computed: {
-    hasValue() {
-      return this.selected && this.selected.id > 0;
+    ...mapGetters(['isProjectBoard']),
+    isLoading() {
+      return this.$apollo.queries.searchUsers.loading;
     },
-    selectedId() {
-      return this.selected ? this.selected.id : null;
+    isSearchEmpty() {
+      return this.search === '' && !this.isLoading;
     },
-  },
-  watch: {
-    selected() {
-      this.initSelect();
+    selectedIsEmpty() {
+      return isEmpty(this.selected);
+    },
+    noUsersFound() {
+      return !this.isSearchEmpty && this.users.length === 0;
+    },
+    users() {
+      const filteredUsers = this.searchUsers.filter(
+        (user) => user.name.includes(this.search) || user.username.includes(this.search),
+      );
+
+      // TODO this de-duplication is temporary (BE fix required)
+      // https://gitlab.com/gitlab-org/gitlab/-/issues/327822
+      return filteredUsers
+        .concat(this.searchUsers)
+        .reduce(
+          (acc, current) => (acc.some((user) => current.id === user.id) ? acc : [...acc, current]),
+          [],
+        );
     },
-  },
-  mounted() {
-    this.initSelect();
   },
   methods: {
-    initSelect() {
-      this.userDropdown = new UsersSelect(null, this.$refs.dropdown, {
-        handleClick: this.selectUser,
-      });
-    },
-    selectUser(user, isMarking) {
-      let assignee = user;
-      if (!isMarking) {
-        // correctly select "unassigned" in Assignee dropdown
-        assignee = {
-          id: undefined,
-        };
+    ...mapActions(['setError']),
+    selectAssignee(user) {
+      this.selected = user;
+      this.toggleEdit();
+      this.$emit('set-assignee', user?.id || null);
+    },
+    toggleEdit() {
+      if (!this.isEditing && !this.isDropdownShowing) {
+        this.isEditing = true;
+        this.showDropdown();
+      } else {
+        this.isEditing = false;
+        this.isDropdownShowing = false;
       }
-      // eslint-disable-next-line vue/no-mutating-props
-      this.board.assignee_id = assignee.id;
-      // eslint-disable-next-line vue/no-mutating-props
-      this.board.assignee = assignee;
+    },
+    isSelected(user) {
+      return this.selected?.username === user.username;
+    },
+    showDropdown() {
+      this.$refs.editDropdown.show();
+      this.isDropdownShowing = true;
+    },
+    setFocus() {
+      this.$refs.search.focusInput();
+    },
+    hideDropdown() {
+      this.isEditing = false;
     },
   },
+  i18n: {
+    label: s__('BoardScope|Assignee'),
+    anyAssignee: s__('BoardScope|Any assignee'),
+    selectAssignee: s__('BoardScope|Select assignee'),
+    noMatchingResults: s__('BoardScope|No matching results'),
+    errorSearchingUsers: s__(
+      'BoardScope|An error occurred while searching for users, please try again.',
+    ),
+    edit: s__('BoardScope|Edit'),
+  },
 };
 </script>
 
 <template>
-  <div :class="wrapperClass" class="block">
+  <div class="block assignee">
     <div class="title gl-mb-3">
-      {{ label }}
-      <button v-if="canEdit" type="button" class="edit-link btn btn-blank float-right">
-        {{ __('Edit') }}
-      </button>
+      {{ $options.i18n.label }}
+      <gl-button
+        v-if="canEdit"
+        variant="link"
+        class="edit-link float-right gl-text-gray-900!"
+        @click="toggleEdit"
+      >
+        {{ $options.i18n.edit }}
+      </gl-button>
     </div>
-    <div class="value">
-      <div v-if="hasValue" class="media gl-display-flex gl-align-items-center">
-        <div class="align-center">
-          <user-avatar-image :img-src="selected.avatar_url" :size="32" />
-        </div>
-        <div class="media-body">
-          <div class="bold author">{{ selected.name }}</div>
-          <div class="username">@{{ selected.username }}</div>
+    <div v-if="!isEditing" data-testid="selected-assignee">
+      <div v-if="!selectedIsEmpty" class="gl-display-flex gl-align-items-center">
+        <user-avatar-image :img-src="selected.avatarUrl || selected.avatar_url" :size="32" />
+        <div>
+          <div class="gl-font-weight-bold">{{ selected.name }}</div>
+          <div>@{{ selected.username }}</div>
         </div>
       </div>
-      <div v-else class="text-secondary">{{ anyUserText }}</div>
+      <div v-else class="gl-text-gray-500">{{ $options.i18n.anyAssignee }}</div>
     </div>
 
-    <div class="selectbox" style="display: none">
-      <div class="dropdown">
-        <!-- eslint-disable @gitlab/vue-no-data-toggle -->
-        <button
-          ref="dropdown"
-          :data-field-name="fieldName"
-          :data-dropdown-title="placeholderText"
-          :data-any-user="anyUserText"
-          :data-group-id="groupId"
-          :data-project-id="projectId"
-          :data-selected="selectedId"
-          class="dropdown-menu-toggle wide"
-          data-toggle="dropdown"
-          aria-expanded="false"
-          type="button"
-        >
-          <span class="dropdown-toggle-text">{{ placeholderText }}</span>
-          <gl-icon
-            name="chevron-down"
-            class="gl-absolute gl-top-3 gl-right-3 gl-text-gray-500"
-            :size="16"
-          />
-        </button>
-        <!-- eslint-enable @gitlab/vue-no-data-toggle -->
-
-        <div
-          class="dropdown-menu dropdown-select dropdown-menu-paging dropdown-menu-user dropdown-menu-selectable dropdown-menu-author"
-        >
-          <div class="dropdown-input">
-            <input
-              autocomplete="off"
-              class="dropdown-input-field"
-              :placeholder="__('Search')"
-              type="search"
-            />
-            <gl-icon
-              name="search"
-              class="dropdown-input-search gl-absolute gl-top-3 gl-right-5 gl-text-gray-300 gl-pointer-events-none"
-            />
-            <gl-icon
-              name="close"
-              class="dropdown-input-clear js-dropdown-input-clear gl-absolute gl-top-3 gl-right-5 gl-text-gray-500"
-            />
-          </div>
-          <div class="dropdown-content"></div>
-          <div class="dropdown-loading">
-            <gl-loading-icon size="sm" />
-          </div>
-        </div>
-      </div>
-    </div>
+    <gl-dropdown
+      v-show="isEditing"
+      ref="editDropdown"
+      :text="$options.i18n.selectAssignee"
+      lazy
+      menu-class="gl-w-full!"
+      class="gl-w-full"
+      @shown="setFocus"
+      @hide="hideDropdown"
+    >
+      <template #header>
+        <gl-search-box-by-type ref="search" v-model.trim="search" class="js-dropdown-input-field" />
+      </template>
+      <gl-dropdown-form class="gl-relative gl-min-h-7">
+        <gl-loading-icon
+          v-if="isLoading"
+          size="md"
+          class="gl-absolute gl-left-0 gl-top-0 gl-right-0"
+        />
+        <template v-else>
+          <gl-dropdown-item
+            v-if="isSearchEmpty"
+            :is-checked="selectedIsEmpty"
+            :is-check-centered="true"
+            @click="selectAssignee(null)"
+          >
+            <span :class="selectedIsEmpty ? 'gl-pl-0' : 'gl-pl-6'" class="gl-font-weight-bold">
+              {{ $options.i18n.anyAssignee }}
+            </span>
+          </gl-dropdown-item>
+          <gl-dropdown-divider />
+          <gl-dropdown-item
+            v-for="user in users"
+            :key="user.id"
+            :is-checked="isSelected(user)"
+            :is-check-centered="true"
+            :is-check-item="true"
+            :avatar-url="user.avatar_url || user.avatarUrl"
+            :secondary-text="user.username"
+            data-testid="unselected-user"
+            @click="selectAssignee(user)"
+          >
+            {{ user.name }}
+          </gl-dropdown-item>
+          <gl-dropdown-item v-if="noUsersFound" class="gl-pl-6!">
+            {{ $options.i18n.noMatchingResults }}
+          </gl-dropdown-item>
+        </template>
+      </gl-dropdown-form>
+      <template #footer>
+        <slot name="footer"></slot>
+      </template>
+    </gl-dropdown>
   </div>
 </template>
diff --git a/ee/app/assets/javascripts/boards/components/board_scope.vue b/ee/app/assets/javascripts/boards/components/board_scope.vue
index be0da9ba3e0aa812a006d067ec1b2786b855bddc..2054cffd323189a86c38409c988036097de3016f 100644
--- a/ee/app/assets/javascripts/boards/components/board_scope.vue
+++ b/ee/app/assets/javascripts/boards/components/board_scope.vue
@@ -134,15 +134,10 @@ export default {
       <assignee-select
         v-if="isIssueBoard"
         :board="board"
-        :selected="board.assignee"
         :can-edit="canAdminBoard"
         :project-id="projectId"
         :group-id="groupId"
-        any-user-text="Any assignee"
-        field-name="assignee_id"
-        label="Assignee"
-        placeholder-text="Select assignee"
-        wrapper-class="assignee"
+        @set-assignee="$emit('set-assignee', $event)"
       />
 
       <!-- eslint-disable vue/no-mutating-props -->
diff --git a/ee/spec/features/boards/scoped_issue_board_spec.rb b/ee/spec/features/boards/scoped_issue_board_spec.rb
index fa1e30b5afa25f73424a19ccee84874a19efdd49..5ba58069afe9f3d413f24da9b66684afdfd3d58a 100644
--- a/ee/spec/features/boards/scoped_issue_board_spec.rb
+++ b/ee/spec/features/boards/scoped_issue_board_spec.rb
@@ -229,7 +229,7 @@
         edit_board.click
 
         expect(find('.milestone .value')).to have_content(milestone.title)
-        expect(find('.assignee .value')).to have_content(user.name)
+        expect(find('[data-testid="selected-assignee"]')).to have_content(user.name)
         expect(find('.weight .value')).to have_content(2)
       end
 
@@ -564,7 +564,7 @@ def click_value(filter, value)
             click_button value
           end
         else
-          click_link value
+          click_on value
         end
       end
     end
diff --git a/ee/spec/frontend/boards/components/assignee_select_spec.js b/ee/spec/frontend/boards/components/assignee_select_spec.js
index 7b1cc05513949e7a935d002b099a5b09120b4c59..a52b96a102f44812c4df6fe8629d15c060b52894 100644
--- a/ee/spec/frontend/boards/components/assignee_select_spec.js
+++ b/ee/spec/frontend/boards/components/assignee_select_spec.js
@@ -1,117 +1,152 @@
-import MockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
-
+import { GlButton, GlDropdown } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import Vuex from 'vuex';
 import AssigneeSelect from 'ee/boards/components/assignee_select.vue';
-import { boardObj } from 'jest/boards/mock_data';
-
-import boardsStore from '~/boards/stores/boards_store';
-import IssuableContext from '~/issuable_context';
-import axios from '~/lib/utils/axios_utils';
 
-let vm;
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
 
-function selectedText() {
-  return vm.$el.querySelector('.value').innerText.trim();
-}
-
-function activeDropdownItem(index) {
-  const items = document.querySelectorAll('.is-active');
-  if (!items[index]) return '';
-  return items[index].innerText.trim();
-}
+import { boardObj } from 'jest/boards/mock_data';
+import { projectMembersResponse, groupMembersResponse, mockUser2 } from 'jest/sidebar/mock_data';
 
-const assignee = {
-  id: 1,
-  name: 'first assignee',
-};
+import defaultStore from '~/boards/stores';
+import searchGroupUsersQuery from '~/graphql_shared/queries/group_users_search.query.graphql';
+import searchProjectUsersQuery from '~/graphql_shared/queries/users_search.query.graphql';
+import { ASSIGNEES_DEBOUNCE_DELAY } from '~/sidebar/constants';
 
-const assignee2 = {
-  id: 2,
-  name: 'second assignee',
-};
+const localVue = createLocalVue();
+localVue.use(VueApollo);
 
 describe('Assignee select component', () => {
-  beforeEach((done) => {
-    setFixtures('<div class="test-container"></div>');
-    boardsStore.create();
-
-    // eslint-disable-next-line no-new
-    new IssuableContext();
-
-    const Component = Vue.extend(AssigneeSelect);
-    vm = new Component({
+  let wrapper;
+  let fakeApollo;
+  let store;
+
+  const selectedText = () => wrapper.find('[data-testid="selected-assignee"]').text();
+  const findEditButton = () => wrapper.findComponent(GlButton);
+  const findDropdown = () => wrapper.findComponent(GlDropdown);
+
+  const usersQueryHandlerSuccess = jest.fn().mockResolvedValue(projectMembersResponse);
+  const groupUsersQueryHandlerSuccess = jest.fn().mockResolvedValue(groupMembersResponse);
+
+  const createStore = ({ isGroupBoard = false, isProjectBoard = false } = {}) => {
+    store = new Vuex.Store({
+      ...defaultStore,
+      getters: {
+        isGroupBoard: () => isGroupBoard,
+        isProjectBoard: () => isProjectBoard,
+      },
+    });
+  };
+
+  const createComponent = ({ props = {}, usersQueryHandler = usersQueryHandlerSuccess } = {}) => {
+    fakeApollo = createMockApollo([
+      [searchProjectUsersQuery, usersQueryHandler],
+      [searchGroupUsersQuery, groupUsersQueryHandlerSuccess],
+    ]);
+    wrapper = shallowMount(AssigneeSelect, {
+      localVue,
+      store,
+      apolloProvider: fakeApollo,
       propsData: {
         board: boardObj,
-        assigneePath: '/test/issue-boards/assignees.json',
         canEdit: true,
-        label: 'Assignee',
-        selected: {},
-        fieldName: 'assignee_id',
-        anyUserText: 'Any assignee',
+        ...props,
       },
-    }).$mount('.test-container');
+      provide: {
+        fullPath: 'gitlab-org',
+      },
+    });
 
-    setImmediate(done);
-  });
+    // We need to mock out `showDropdown` which
+    // invokes `show` method of BDropdown used inside GlDropdown.
+    jest.spyOn(wrapper.vm, 'showDropdown').mockImplementation();
+  };
 
-  describe('canEdit', () => {
-    it('hides Edit button', (done) => {
-      vm.canEdit = false;
-      Vue.nextTick(() => {
-        expect(vm.$el.querySelector('.edit-link')).toBeFalsy();
-        done();
-      });
-    });
+  beforeEach(() => {
+    createStore({ isProjectBoard: true });
+    createComponent();
+  });
 
-    it('shows Edit button if true', (done) => {
-      vm.canEdit = true;
-      Vue.nextTick(() => {
-        expect(vm.$el.querySelector('.edit-link')).toBeTruthy();
-        done();
-      });
-    });
+  afterEach(() => {
+    wrapper.destroy();
+    fakeApollo = null;
+    store = null;
   });
 
-  describe('selected value', () => {
+  describe('when not editing', () => {
     it('defaults to Any Assignee', () => {
       expect(selectedText()).toContain('Any assignee');
     });
 
-    it('shows selected assignee', (done) => {
-      vm.selected = assignee;
-      Vue.nextTick(() => {
-        expect(selectedText()).toContain('first assignee');
-        done();
-      });
+    it('skips the queries and does not render dropdown', () => {
+      expect(usersQueryHandlerSuccess).not.toHaveBeenCalled();
+      expect(findDropdown().isVisible()).toBe(false);
     });
+  });
 
-    describe('clicking dropdown items', () => {
-      let mock;
+  describe('when editing', () => {
+    it('trigger query and renders dropdown with returned users', async () => {
+      findEditButton().vm.$emit('click');
+      await waitForPromises();
+      jest.advanceTimersByTime(ASSIGNEES_DEBOUNCE_DELAY);
+      await nextTick();
+      expect(usersQueryHandlerSuccess).toHaveBeenCalled();
 
-      beforeEach(() => {
-        mock = new MockAdapter(axios);
-        mock.onGet('/-/autocomplete/users.json').reply(200, [assignee, assignee2]);
-      });
+      expect(findDropdown().isVisible()).toBe(true);
+      expect(wrapper.findAll('[data-testid="unselected-user"]')).toHaveLength(3); // 2 users + Any assignee item
+    });
 
-      afterEach(() => {
-        mock.restore();
-      });
+    it('renders selected assignee', async () => {
+      findEditButton().vm.$emit('click');
+      await waitForPromises();
+      jest.advanceTimersByTime(ASSIGNEES_DEBOUNCE_DELAY);
+      await nextTick();
 
-      it('sets assignee', (done) => {
-        vm.$el.querySelector('.edit-link').click();
+      wrapper
+        .findAll('[data-testid="unselected-user"]')
+        .at(1)
+        .vm.$emit('click', new Event('click'));
+
+      await waitForPromises();
+      expect(selectedText()).toContain(mockUser2.username);
+    });
+  });
 
-        jest.runOnlyPendingTimers();
+  describe('canEdit', () => {
+    it('hides Edit button', async () => {
+      wrapper.setProps({ canEdit: false });
+      await nextTick();
 
-        setImmediate(() => {
-          vm.$el.querySelectorAll('li a')[2].click();
+      expect(findEditButton().exists()).toBe(false);
+    });
 
-          setImmediate(() => {
-            expect(activeDropdownItem(0)).toEqual('second assignee');
-            expect(vm.board.assignee).toEqual(assignee2);
-            done();
-          });
-        });
-      });
+    it('shows Edit button if true', () => {
+      expect(findEditButton().exists()).toBe(true);
     });
   });
+
+  it.each`
+    boardType    | mockedResponse            | queryHandler                     | notCalledHandler
+    ${'group'}   | ${groupMembersResponse}   | ${groupUsersQueryHandlerSuccess} | ${usersQueryHandlerSuccess}
+    ${'project'} | ${projectMembersResponse} | ${usersQueryHandlerSuccess}      | ${groupUsersQueryHandlerSuccess}
+  `(
+    'fetches $boardType users',
+    async ({ boardType, mockedResponse, queryHandler, notCalledHandler }) => {
+      createStore({ isProjectBoard: boardType === 'project', isGroupBoard: boardType === 'group' });
+      createComponent({
+        [queryHandler]: jest.fn().mockResolvedValue(mockedResponse),
+      });
+
+      findEditButton().vm.$emit('click');
+      await waitForPromises();
+      jest.advanceTimersByTime(ASSIGNEES_DEBOUNCE_DELAY);
+      await nextTick();
+
+      expect(queryHandler).toHaveBeenCalled();
+      expect(notCalledHandler).not.toHaveBeenCalled();
+    },
+  );
 });
diff --git a/ee/spec/frontend/boards/components/board_scope_spec.js b/ee/spec/frontend/boards/components/board_scope_spec.js
index 8b24c43be25901e1d4010ebef11c516be1a2c549..2d095cede5e3316e3ba38de71aba16a1418c6fc6 100644
--- a/ee/spec/frontend/boards/components/board_scope_spec.js
+++ b/ee/spec/frontend/boards/components/board_scope_spec.js
@@ -1,13 +1,12 @@
-import { createLocalVue, mount } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
 import Vuex from 'vuex';
 import BoardScope from 'ee/boards/components/board_scope.vue';
 import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
 import { TEST_HOST } from 'helpers/test_constants';
 import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
 
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
 
 describe('BoardScope', () => {
   let wrapper;
@@ -25,7 +24,6 @@ describe('BoardScope', () => {
 
   function mountComponent() {
     wrapper = mount(BoardScope, {
-      localVue,
       store,
       propsData: {
         collapseScope: false,
@@ -37,6 +35,9 @@ describe('BoardScope', () => {
         labelsPath: `${TEST_HOST}/labels`,
         labelsWebUrl: `${TEST_HOST}/-/labels`,
       },
+      stubs: {
+        AssigneeSelect: true,
+      },
     });
   }
 
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 94487ec3be1e19b6b46c08f17acb146afc84c12a..a5377bb1749ff7a0b6344c20e4f668e6f792b088 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -3912,9 +3912,6 @@ msgstr ""
 msgid "Any namespace"
 msgstr ""
 
-msgid "Any user"
-msgstr ""
-
 msgid "App ID"
 msgstr ""
 
@@ -5284,6 +5281,24 @@ msgstr ""
 msgid "BoardNewIssue|Select a project"
 msgstr ""
 
+msgid "BoardScope|An error occurred while searching for users, please try again."
+msgstr ""
+
+msgid "BoardScope|Any assignee"
+msgstr ""
+
+msgid "BoardScope|Assignee"
+msgstr ""
+
+msgid "BoardScope|Edit"
+msgstr ""
+
+msgid "BoardScope|No matching results"
+msgstr ""
+
+msgid "BoardScope|Select assignee"
+msgstr ""
+
 msgid "Boards"
 msgstr ""
 
@@ -29525,9 +29540,6 @@ msgstr ""
 msgid "Select type"
 msgstr ""
 
-msgid "Select user"
-msgstr ""
-
 msgid "Selected"
 msgstr ""
 
diff --git a/spec/frontend/sidebar/mock_data.js b/spec/frontend/sidebar/mock_data.js
index 9fab24d75188eae65b8991815bdd5936806c9850..2da007fb549e8a954eed1ad2928f3dc8a9681219 100644
--- a/spec/frontend/sidebar/mock_data.js
+++ b/spec/frontend/sidebar/mock_data.js
@@ -415,7 +415,7 @@ const mockUser1 = {
   status: null,
 };
 
-const mockUser2 = {
+export const mockUser2 = {
   id: 'gid://gitlab/User/4',
   avatarUrl: '/avatar2',
   name: 'rookie',
@@ -452,9 +452,40 @@ export const projectMembersResponse = {
           null,
           null,
           // Remove duplicated entry https://gitlab.com/gitlab-org/gitlab/-/issues/327822
-          mockUser1,
-          mockUser1,
-          mockUser2,
+          { user: mockUser1 },
+          { user: mockUser1 },
+          { user: mockUser2 },
+          {
+            user: {
+              id: 'gid://gitlab/User/2',
+              avatarUrl:
+                'https://www.gravatar.com/avatar/a95e5b71488f4b9d69ce5ff58bfd28d6?s=80\u0026d=identicon',
+              name: 'Jacki Kub',
+              username: 'francina.skiles',
+              webUrl: '/franc',
+              status: {
+                availability: 'BUSY',
+              },
+            },
+          },
+        ],
+      },
+    },
+  },
+};
+
+export const groupMembersResponse = {
+  data: {
+    workspace: {
+      __typename: 'roup',
+      users: {
+        nodes: [
+          // Remove nulls https://gitlab.com/gitlab-org/gitlab/-/issues/329750
+          null,
+          null,
+          // Remove duplicated entry https://gitlab.com/gitlab-org/gitlab/-/issues/327822
+          { user: mockUser1 },
+          { user: mockUser1 },
           {
             user: {
               id: 'gid://gitlab/User/2',