diff --git a/app/assets/javascripts/emoji/components/category.vue b/app/assets/javascripts/emoji/components/category.vue
index d8607cbc60b8e6c7de110d8d614d28970e4e8e7a..80850475b9656f2a45f024b98c4cbce9da2e76bb 100644
--- a/app/assets/javascripts/emoji/components/category.vue
+++ b/app/assets/javascripts/emoji/components/category.vue
@@ -52,7 +52,7 @@ export default {
         :key="index"
         :emojis="emojiGroup"
         :render-group="renderGroup"
-        :click-emoji="(emoji) => onClick(emoji)"
+        @emoji-click="onClick"
       />
     </template>
     <p v-else>
diff --git a/app/assets/javascripts/emoji/components/emoji_group.vue b/app/assets/javascripts/emoji/components/emoji_group.vue
index bbac6866636d9b51e298b6d22ac49fe27d7eb72d..bb0c3b0a694c2bb157fb78c0218d85883ceb08ab 100644
--- a/app/assets/javascripts/emoji/components/emoji_group.vue
+++ b/app/assets/javascripts/emoji/components/emoji_group.vue
@@ -1,10 +1,10 @@
 <script>
-import { compatFunctionalMixin } from '~/lib/utils/vue3compat/compat_functional_mixin';
+import { GlButton } from '@gitlab/ui';
 
 export default {
-  // Temporary mixin for migration from Vue.js 2 to @vue/compat
-  mixins: [compatFunctionalMixin],
-
+  components: {
+    GlButton,
+  },
   props: {
     emojis: {
       type: Array,
@@ -14,28 +14,33 @@ export default {
       type: Boolean,
       required: true,
     },
-    clickEmoji: {
-      type: Function,
-      required: true,
+  },
+  methods: {
+    clickEmoji(emoji) {
+      this.$emit('emoji-click', emoji);
     },
   },
 };
 </script>
 
-<!-- eslint-disable-next-line vue/no-deprecated-functional-template -->
-<template functional>
+<template>
   <div class="gl-display-flex gl-flex-wrap gl-mb-2">
-    <template v-if="props.renderGroup">
-      <button
-        v-for="emoji in props.emojis"
+    <template v-if="renderGroup">
+      <gl-button
+        v-for="emoji in emojis"
         :key="emoji"
         type="button"
-        class="gl-border-0 gl-bg-transparent gl-px-0 gl-py-2 gl-text-center emoji-picker-emoji"
+        category="tertiary"
+        class="emoji-picker-emoji"
+        :aria-label="emoji"
         data-testid="emoji-button"
-        @click="props.clickEmoji(emoji)"
+        button-text-classes="gl-display-none!"
+        @click="clickEmoji(emoji)"
       >
-        <gl-emoji :data-name="emoji" />
-      </button>
+        <template #emoji>
+          <gl-emoji :data-name="emoji" class="gl-mr-0!" />
+        </template>
+      </gl-button>
     </template>
   </div>
 </template>
diff --git a/app/assets/stylesheets/framework/emojis.scss b/app/assets/stylesheets/framework/emojis.scss
index 92cb509148f17cd29bde77106fa7104e03ef38b0..a06cf84b5b4d96f5b46201e08e9c85fec9b2d657 100644
--- a/app/assets/stylesheets/framework/emojis.scss
+++ b/app/assets/stylesheets/framework/emojis.scss
@@ -41,6 +41,16 @@ gl-emoji {
   &:focus {
     transform: scale(1.3);
   }
+
+  &:focus {
+    @include gl-z-index-2;
+    mix-blend-mode: normal !important;
+  }
+
+  gl-emoji {
+    width: px-to-rem($gl-padding);
+    top: -1px;
+  }
 }
 
 .emoji-picker .gl-dropdown .dropdown-menu {
diff --git a/spec/frontend/emoji/components/emoji_group_spec.js b/spec/frontend/emoji/components/emoji_group_spec.js
index 75397ce25ff43acdfb7cdc5b8b34b05650b5039f..a2a46bedd7b6b4ad91e19308892c77307cb707b7 100644
--- a/spec/frontend/emoji/components/emoji_group_spec.js
+++ b/spec/frontend/emoji/components/emoji_group_spec.js
@@ -1,5 +1,6 @@
 import { shallowMount } from '@vue/test-utils';
 import Vue from 'vue';
+import { GlButton } from '@gitlab/ui';
 import { extendedWrapper } from 'helpers/vue_test_utils_helper';
 import EmojiGroup from '~/emoji/components/emoji_group.vue';
 
@@ -10,6 +11,9 @@ function factory(propsData = {}) {
   wrapper = extendedWrapper(
     shallowMount(EmojiGroup, {
       propsData,
+      stubs: {
+        GlButton,
+      },
     }),
   );
 }
@@ -19,7 +23,6 @@ describe('Emoji group component', () => {
     factory({
       emojis: [],
       renderGroup: false,
-      clickEmoji: jest.fn(),
     });
 
     expect(wrapper.findByTestId('emoji-button').exists()).toBe(false);
@@ -29,24 +32,20 @@ describe('Emoji group component', () => {
     factory({
       emojis: ['thumbsup', 'thumbsdown'],
       renderGroup: true,
-      clickEmoji: jest.fn(),
     });
 
     expect(wrapper.findAllByTestId('emoji-button').exists()).toBe(true);
     expect(wrapper.findAllByTestId('emoji-button').length).toBe(2);
   });
 
-  it('calls clickEmoji', () => {
-    const clickEmoji = jest.fn();
-
+  it('emits emoji-click', () => {
     factory({
       emojis: ['thumbsup', 'thumbsdown'],
       renderGroup: true,
-      clickEmoji,
     });
 
-    wrapper.findByTestId('emoji-button').trigger('click');
+    wrapper.findComponent(GlButton).vm.$emit('click');
 
-    expect(clickEmoji).toHaveBeenCalledWith('thumbsup');
+    expect(wrapper.emitted('emoji-click')).toStrictEqual([['thumbsup']]);
   });
 });