diff --git a/app/assets/javascripts/repository/components/header_area.vue b/app/assets/javascripts/repository/components/header_area.vue
index edede9cd02907c9cdbc3eb4268f5f2c08d1de129..f3c3a7c189eec8c3827cc292d57019d4330d8971 100644
--- a/app/assets/javascripts/repository/components/header_area.vue
+++ b/app/assets/javascripts/repository/components/header_area.vue
@@ -19,6 +19,7 @@ import CodeDropdown from '~/vue_shared/components/code_dropdown/code_dropdown.vu
 import CompactCodeDropdown from '~/repository/components/code_dropdown/compact_code_dropdown.vue';
 import SourceCodeDownloadDropdown from '~/vue_shared/components/download_dropdown/download_dropdown.vue';
 import CloneCodeDropdown from '~/vue_shared/components/code_dropdown/clone_code_dropdown.vue';
+import AddToTree from '~/repository/components/header_area/add_to_tree.vue';
 import FileIcon from '~/vue_shared/components/file_icon.vue';
 
 export default {
@@ -38,6 +39,7 @@ export default {
     CompactCodeDropdown,
     SourceCodeDownloadDropdown,
     CloneCodeDropdown,
+    AddToTree,
     WebIdeLink: () => import('ee_else_ce/vue_shared/components/web_ide_link.vue'),
     LockDirectoryButton: () =>
       import('ee_component/repository/components/lock_directory_button.vue'),
@@ -239,6 +241,25 @@ export default {
 
       <!-- Tree controls -->
       <div v-if="isTreeView" class="tree-controls gl-mb-3 gl-flex gl-flex-wrap gl-gap-3 sm:gl-mb-0">
+        <add-to-tree
+          v-if="!isReadmeView && showCompactCodeDropdown"
+          class="gl-hidden sm:gl-block"
+          :current-path="currentPath"
+          :can-collaborate="canCollaborate"
+          :can-edit-tree="canEditTree"
+          :can-push-code="canPushCode"
+          :can-push-to-branch="canPushToBranch"
+          :original-branch="originalBranch"
+          :selected-branch="selectedBranch"
+          :new-branch-path="newBranchPath"
+          :new-tag-path="newTagPath"
+          :new-blob-path="newBlobPath"
+          :fork-new-blob-path="forkNewBlobPath"
+          :fork-new-directory-path="forkNewDirectoryPath"
+          :fork-upload-blob-path="forkUploadBlobPath"
+          :upload-path="uploadPath"
+          :new-dir-path="newDirPath"
+        />
         <!-- EE: = render_if_exists 'projects/tree/lock_link' -->
         <lock-directory-button v-if="!isRoot" :project-path="projectPath" :path="currentPath" />
         <gl-button
@@ -277,7 +298,27 @@ export default {
         <!-- code + mobile panel -->
         <div v-if="!isReadmeView" class="project-code-holder gl-w-full sm:gl-w-auto">
           <div v-if="showCompactCodeDropdown" class="gl-flex gl-justify-end gl-gap-3">
+            <add-to-tree
+              v-if="!isReadmeView"
+              class="sm:gl-hidden"
+              :current-path="currentPath"
+              :can-collaborate="canCollaborate"
+              :can-edit-tree="canEditTree"
+              :can-push-code="canPushCode"
+              :can-push-to-branch="canPushToBranch"
+              :original-branch="originalBranch"
+              :selected-branch="selectedBranch"
+              :new-branch-path="newBranchPath"
+              :new-tag-path="newTagPath"
+              :new-blob-path="newBlobPath"
+              :fork-new-blob-path="forkNewBlobPath"
+              :fork-new-directory-path="forkNewDirectoryPath"
+              :fork-upload-blob-path="forkUploadBlobPath"
+              :upload-path="uploadPath"
+              :new-dir-path="newDirPath"
+            />
             <compact-code-dropdown
+              class="gl-ml-auto"
               :ssh-url="sshUrl"
               :http-url="httpUrl"
               :kerberos-url="kerberosUrl"
diff --git a/app/assets/javascripts/repository/components/header_area/add_to_tree.vue b/app/assets/javascripts/repository/components/header_area/add_to_tree.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d75f61cd0808ae6299b6670200fa7224e853a541
--- /dev/null
+++ b/app/assets/javascripts/repository/components/header_area/add_to_tree.vue
@@ -0,0 +1,256 @@
+<script>
+import { GlDisclosureDropdown, GlModalDirective } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+import { s__ } from '~/locale';
+import { joinPaths } from '~/lib/utils/url_utility';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
+import permissionsQuery from 'shared_queries/repository/permissions.query.graphql';
+import projectPathQuery from '~/repository/queries/project_path.query.graphql';
+import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
+import NewDirectoryModal from '~/repository/components/new_directory_modal.vue';
+
+export default {
+  components: {
+    GlDisclosureDropdown,
+    UploadBlobModal,
+    NewDirectoryModal,
+  },
+  directives: {
+    GlModal: GlModalDirective,
+  },
+  props: {
+    currentPath: {
+      type: String,
+      required: false,
+      default: '',
+    },
+    canEditTree: {
+      type: Boolean,
+      required: false,
+      default: false,
+    },
+    canCollaborate: {
+      type: Boolean,
+      required: false,
+      default: false,
+    },
+    newBlobPath: {
+      type: String,
+      required: false,
+      default: null,
+    },
+    forkNewBlobPath: {
+      type: String,
+      required: false,
+      default: null,
+    },
+    forkNewDirectoryPath: {
+      type: String,
+      required: false,
+      default: null,
+    },
+    forkUploadBlobPath: {
+      type: String,
+      required: false,
+      default: null,
+    },
+    newBranchPath: {
+      type: String,
+      required: false,
+      default: null,
+    },
+    newTagPath: {
+      type: String,
+      required: false,
+      default: null,
+    },
+    uploadPath: {
+      type: String,
+      required: false,
+      default: '',
+    },
+    newDirPath: {
+      type: String,
+      required: false,
+      default: '',
+    },
+    selectedBranch: {
+      type: String,
+      required: false,
+      default: '',
+    },
+    originalBranch: {
+      type: String,
+      required: false,
+      default: '',
+    },
+    canPushCode: {
+      type: Boolean,
+      required: false,
+      default: false,
+    },
+    canPushToBranch: {
+      type: Boolean,
+      required: false,
+      default: false,
+    },
+  },
+  apollo: {
+    projectPath: {
+      query: projectPathQuery,
+    },
+    userPermissions: {
+      query: permissionsQuery,
+      variables() {
+        return {
+          projectPath: this.projectPath,
+        };
+      },
+      update: (data) => data.project?.userPermissions,
+    },
+  },
+  data() {
+    return {
+      projectPath: '',
+      userPermissions: {},
+    };
+  },
+  computed: {
+    uploadBlobModalId() {
+      return uniqueId('modal-upload-blob');
+    },
+    newDirectoryModalId() {
+      return uniqueId('modal-new-directory');
+    },
+    canCreateMrFromFork() {
+      return this.userPermissions?.forkProject && this.userPermissions?.createMergeRequestIn;
+    },
+    hasPushCodePermission() {
+      return this.userPermissions?.pushCode;
+    },
+    dropdownDirectoryItems() {
+      if (this.canEditTree) {
+        return [
+          {
+            text: s__('Repository|New file'),
+            href: joinPaths(
+              this.newBlobPath,
+              this.currentPath ? encodeURIComponent(this.currentPath) : '',
+            ),
+            extraAttrs: {
+              'data-testid': 'new-file-menu-item',
+            },
+          },
+          {
+            text: s__('Repository|Upload file'),
+            action: () => this.$root.$emit(BV_SHOW_MODAL, this.uploadBlobModalId),
+          },
+          {
+            text: s__('Repository|New directory'),
+            action: () => this.$root.$emit(BV_SHOW_MODAL, this.newDirectoryModalId),
+          },
+        ];
+      }
+
+      if (this.canCreateMrFromFork) {
+        return [
+          {
+            text: s__('Repository|New file'),
+            href: this.forkNewBlobPath,
+            extraAttrs: {
+              'data-method': 'post',
+            },
+          },
+          {
+            text: s__('Repository|Upload file'),
+            href: this.forkUploadBlobPath,
+            extraAttrs: {
+              'data-method': 'post',
+            },
+          },
+          {
+            text: s__('Repository|New directory'),
+            href: this.forkNewDirectoryPath,
+            extraAttrs: {
+              'data-method': 'post',
+            },
+          },
+        ];
+      }
+
+      return [];
+    },
+    dropdownRepositoryItems() {
+      if (!this.hasPushCodePermission) return [];
+      return [
+        {
+          text: s__('Repository|New branch'),
+          href: this.newBranchPath,
+        },
+        {
+          text: s__('Repository|New tag'),
+          href: this.newTagPath,
+        },
+      ];
+    },
+    dropdownItems() {
+      if (!this.canCollaborate && !this.canCreateMrFromFork) return [];
+      return [
+        this.dropdownDirectoryItems?.length && {
+          name: s__('Repository|This directory'),
+          items: this.dropdownDirectoryItems,
+        },
+        this.dropdownRepositoryItems?.length && {
+          name: s__('Repository|This repository'),
+          items: this.dropdownRepositoryItems,
+        },
+      ].filter(Boolean);
+    },
+    renderAddToTreeDropdown() {
+      return this.dropdownItems.length;
+    },
+    showUploadModal() {
+      return this.canEditTree && !this.$apollo.queries.userPermissions.loading;
+    },
+    showNewDirectoryModal() {
+      return this.canEditTree && !this.$apollo.queries.userPermissions.loading;
+    },
+    newDirectoryPath() {
+      return joinPaths(this.newDirPath, this.currentPath);
+    },
+  },
+};
+</script>
+
+<template>
+  <div>
+    <gl-disclosure-dropdown
+      v-if="renderAddToTreeDropdown"
+      :toggle-text="__('Add to tree')"
+      toggle-class="add-to-tree"
+      data-testid="add-to-tree"
+      text-sr-only
+      icon="plus"
+      :items="dropdownItems"
+    />
+    <upload-blob-modal
+      v-if="showUploadModal"
+      :modal-id="uploadBlobModalId"
+      :commit-message="__('Upload New File')"
+      :target-branch="selectedBranch"
+      :original-branch="originalBranch"
+      :can-push-code="canPushCode"
+      :can-push-to-branch="canPushToBranch"
+      :path="uploadPath"
+    />
+    <new-directory-modal
+      v-if="showNewDirectoryModal"
+      :can-push-code="canPushCode"
+      :can-push-to-branch="canPushToBranch"
+      :modal-id="newDirectoryModalId"
+      :target-branch="selectedBranch"
+      :original-branch="originalBranch"
+      :path="newDirectoryPath"
+    />
+  </div>
+</template>
diff --git a/app/assets/javascripts/repository/components/header_area/breadcrumbs.vue b/app/assets/javascripts/repository/components/header_area/breadcrumbs.vue
index 4b7ef9700ef7e470b265387200b54f560cd2011d..37309fe82aa4f18683b7d4289099570b5d328cd2 100644
--- a/app/assets/javascripts/repository/components/header_area/breadcrumbs.vue
+++ b/app/assets/javascripts/repository/components/header_area/breadcrumbs.vue
@@ -300,7 +300,7 @@ export default {
       return this.$route.name === 'blobPath' || this.$route.name === 'blobPathDecoded';
     },
     renderAddToTreeDropdown() {
-      return this.dropdownItems.length;
+      return this.dropdownItems.length && !this.glFeatures.directoryCodeDropdownUpdates;
     },
     newDirectoryPath() {
       return joinPaths(this.newDirPath, this.currentPath);
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index bdc817cefe0001a9940f050bf51dd81ddb3ae4b2..2420ae0b88eb61f88f8c747dae54ca030ceb9ac0 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -48285,6 +48285,27 @@ msgstr ""
 msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
 msgstr ""
 
+msgid "Repository|New branch"
+msgstr ""
+
+msgid "Repository|New directory"
+msgstr ""
+
+msgid "Repository|New file"
+msgstr ""
+
+msgid "Repository|New tag"
+msgstr ""
+
+msgid "Repository|This directory"
+msgstr ""
+
+msgid "Repository|This repository"
+msgstr ""
+
+msgid "Repository|Upload file"
+msgstr ""
+
 msgid "Request"
 msgstr ""
 
diff --git a/spec/features/projects/show/user_sees_collaboration_links_spec.rb b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
index 4d57426bd98c2c5f1a19fb40dedb1559532b5ced..ce4c312c2b39ac6b1455c10d82e89f18a82a123f 100644
--- a/spec/features/projects/show/user_sees_collaboration_links_spec.rb
+++ b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
@@ -39,8 +39,8 @@ def find_new_menu_toggle
       end
 
       # The dropdown above the tree
-      page.within('.repo-breadcrumb') do
-        find_by_testid('add-to-tree').click
+      page.within('.tree-controls') do
+        find('.add-to-tree').click
 
         aggregate_failures 'dropdown links above the repo tree' do
           expect(page).to have_link('New file')
diff --git a/spec/frontend/repository/components/header_area/add_to_tree_spec.js b/spec/frontend/repository/components/header_area/add_to_tree_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..196fe5f5531dfcf66d2af6c25aa4eed1234a6878
--- /dev/null
+++ b/spec/frontend/repository/components/header_area/add_to_tree_spec.js
@@ -0,0 +1,204 @@
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlDisclosureDropdown, GlDisclosureDropdownGroup } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import AddToTree from '~/repository/components/header_area/add_to_tree.vue';
+import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
+import NewDirectoryModal from '~/repository/components/new_directory_modal.vue';
+import waitForPromises from 'helpers/wait_for_promises';
+
+import permissionsQuery from 'shared_queries/repository/permissions.query.graphql';
+import projectPathQuery from '~/repository/queries/project_path.query.graphql';
+
+import createApolloProvider from 'helpers/mock_apollo_helper';
+
+const TEST_PROJECT_PATH = 'test-project/path';
+
+Vue.use(VueApollo);
+
+jest.mock('lodash/uniqueId', () => () => 'fake-id');
+
+describe('Add to tree dropdown and modal components', () => {
+  let wrapper;
+  let permissionsQuerySpy;
+
+  const createPermissionsQueryResponse = ({
+    pushCode = false,
+    forkProject = false,
+    createMergeRequestIn = false,
+  } = {}) => ({
+    data: {
+      project: {
+        id: 1,
+        __typename: '__typename',
+        userPermissions: {
+          __typename: '__typename',
+          pushCode,
+          forkProject,
+          createMergeRequestIn,
+        },
+      },
+    },
+  });
+
+  const factory = ({ currentPath, extraProps = {}, mockRoute = {} } = {}) => {
+    const apolloProvider = createApolloProvider([[permissionsQuery, permissionsQuerySpy]]);
+
+    apolloProvider.clients.defaultClient.cache.writeQuery({
+      query: projectPathQuery,
+      data: {
+        projectPath: TEST_PROJECT_PATH,
+      },
+    });
+
+    wrapper = shallowMount(AddToTree, {
+      apolloProvider,
+      provide: {
+        projectRootPath: TEST_PROJECT_PATH,
+      },
+      propsData: {
+        currentPath,
+        ...extraProps,
+      },
+      stubs: {
+        GlDisclosureDropdown,
+      },
+      mocks: {
+        $route: {
+          name: 'treePath',
+          ...mockRoute,
+        },
+      },
+    });
+  };
+
+  const findDropdown = () => wrapper.findComponent(GlDisclosureDropdown);
+  const findDropdownGroup = () => wrapper.findComponent(GlDisclosureDropdownGroup);
+  const findUploadBlobModal = () => wrapper.findComponent(UploadBlobModal);
+  const findNewDirectoryModal = () => wrapper.findComponent(NewDirectoryModal);
+
+  beforeEach(() => {
+    permissionsQuerySpy = jest.fn().mockResolvedValue(createPermissionsQueryResponse());
+  });
+
+  it('does not render add to tree dropdown when permissions are false', async () => {
+    factory({
+      currentPath: '/',
+      extraProps: {
+        canCollaborate: false,
+      },
+    });
+    await nextTick();
+
+    expect(findDropdown().exists()).toBe(false);
+  });
+
+  it('renders add to tree dropdown when permissions are true', async () => {
+    permissionsQuerySpy.mockResolvedValue(
+      createPermissionsQueryResponse({ forkProject: true, createMergeRequestIn: true }),
+    );
+
+    factory({
+      currentPath: '/',
+      extraProps: {
+        canCollaborate: true,
+        canEditTree: true,
+      },
+    });
+    await nextTick();
+
+    expect(findDropdown().exists()).toBe(true);
+  });
+
+  describe('renders the upload blob modal', () => {
+    beforeEach(() => {
+      factory({
+        currentPath: '/',
+        extraProps: {
+          canEditTree: true,
+        },
+      });
+    });
+
+    it('does not render the modal while loading', () => {
+      expect(findUploadBlobModal().exists()).toBe(false);
+    });
+
+    it('renders the modal with correct props once loaded', async () => {
+      await waitForPromises();
+
+      expect(findUploadBlobModal().exists()).toBe(true);
+      expect(findUploadBlobModal().props()).toStrictEqual({
+        canPushCode: false,
+        canPushToBranch: false,
+        commitMessage: 'Upload New File',
+        emptyRepo: false,
+        modalId: 'fake-id',
+        originalBranch: '',
+        path: '',
+        replacePath: null,
+        targetBranch: '',
+      });
+    });
+  });
+
+  describe('renders the new directory modal', () => {
+    beforeEach(() => {
+      factory({
+        currentPath: 'some_dir',
+        extraProps: {
+          canEditTree: true,
+          newDirPath: 'root/master',
+        },
+      });
+    });
+    it('does not render the modal while loading', () => {
+      expect(findNewDirectoryModal().exists()).toBe(false);
+    });
+
+    it('renders the modal once loaded', async () => {
+      await waitForPromises();
+
+      expect(findNewDirectoryModal().exists()).toBe(true);
+      expect(findNewDirectoryModal().props('path')).toBe('root/master/some_dir');
+    });
+  });
+
+  describe('"this repository" dropdown group', () => {
+    it('renders when user has pushCode permissions', async () => {
+      permissionsQuerySpy.mockResolvedValue(
+        createPermissionsQueryResponse({
+          pushCode: true,
+        }),
+      );
+
+      factory({
+        currentPath: '/',
+        extraProps: {
+          canCollaborate: true,
+        },
+      });
+      await waitForPromises();
+
+      expect(findDropdownGroup().props('group').name).toBe('This repository');
+    });
+
+    it('does not render when user does not have pushCode permissions', async () => {
+      permissionsQuerySpy.mockResolvedValue(
+        createPermissionsQueryResponse({
+          pushCode: false,
+        }),
+      );
+
+      factory({
+        currentPath: '/',
+        extraProps: {
+          canCollaborate: true,
+        },
+      });
+      await waitForPromises();
+
+      expect(findDropdownGroup().exists()).toBe(false);
+    });
+  });
+});
diff --git a/spec/frontend/repository/components/header_area_spec.js b/spec/frontend/repository/components/header_area_spec.js
index a5332095aa0e81a1ba166342954f95b433753fac..73784f25ad9ed296691c95830e0c8ed752485302 100644
--- a/spec/frontend/repository/components/header_area_spec.js
+++ b/spec/frontend/repository/components/header_area_spec.js
@@ -6,6 +6,7 @@ import Breadcrumbs from '~/repository/components/header_area/breadcrumbs.vue';
 import CodeDropdown from '~/vue_shared/components/code_dropdown/code_dropdown.vue';
 import CompactCodeDropdown from '~/repository/components/code_dropdown/compact_code_dropdown.vue';
 import SourceCodeDownloadDropdown from '~/vue_shared/components/download_dropdown/download_dropdown.vue';
+import AddToTree from '~/repository/components/header_area/add_to_tree.vue';
 import FileIcon from '~/vue_shared/components/file_icon.vue';
 import CloneCodeDropdown from '~/vue_shared/components/code_dropdown/clone_code_dropdown.vue';
 import RepositoryOverflowMenu from '~/repository/components/header_area/repository_overflow_menu.vue';
@@ -37,6 +38,7 @@ describe('HeaderArea', () => {
   const findCompactCodeDropdown = () => wrapper.findComponent(CompactCodeDropdown);
   const findSourceCodeDownloadDropdown = () => wrapper.findComponent(SourceCodeDownloadDropdown);
   const findCloneCodeDropdown = () => wrapper.findComponent(CloneCodeDropdown);
+  const findAddToTreeDropdown = () => wrapper.findComponent(AddToTree);
   const findPageHeading = () => wrapper.findByTestId('repository-heading');
   const findFileIcon = () => wrapper.findComponent(FileIcon);
   const findRepositoryOverflowMenu = () => wrapper.findComponent(RepositoryOverflowMenu);
@@ -153,13 +155,28 @@ describe('HeaderArea', () => {
             expect(findCloneCodeDropdown().props('httpUrl')).toBe(headerAppInjected.httpUrl);
           });
         });
+
+        describe('Add to tree dropdown', () => {
+          it('does not render AddToTree component', () => {
+            expect(findAddToTreeDropdown().exists()).toBe(false);
+          });
+        });
       });
     });
   });
 
   describe('when rendered for tree view and directory_code_dropdown_updates flag is true', () => {
-    it('renders CompactCodeDropdown with correct props', () => {
+    beforeEach(() => {
       wrapper = createComponent({}, {}, { glFeatures: { directoryCodeDropdownUpdates: true } });
+    });
+
+    describe('Add to tree dropdown', () => {
+      it('renders AddToTree component', () => {
+        expect(findAddToTreeDropdown().exists()).toBe(true);
+      });
+    });
+
+    it('renders CompactCodeDropdown with correct props', () => {
       expect(findCompactCodeDropdown().exists()).toBe(true);
       expect(findCompactCodeDropdown().props()).toMatchObject({
         sshUrl: headerAppInjected.sshUrl,
@@ -200,6 +217,10 @@ describe('HeaderArea', () => {
       expect(findSourceCodeDownloadDropdown().exists()).toBe(false);
     });
 
+    it('does not render AddToTree component', () => {
+      expect(findAddToTreeDropdown().exists()).toBe(false);
+    });
+
     it('displays correct file name and icon', () => {
       expect(findPageHeading().text()).toContain('index.js');
       expect(findFileIcon().props('fileName')).toBe('index.js');
@@ -223,6 +244,10 @@ describe('HeaderArea', () => {
       expect(findBreadcrumbs().exists()).toBe(false);
     });
 
+    it('does not render AddToTree component', () => {
+      expect(findAddToTreeDropdown().exists()).toBe(false);
+    });
+
     it('does not render CodeDropdown and SourceCodeDownloadDropdown', () => {
       expect(findCodeDropdown().exists()).toBe(false);
       expect(findSourceCodeDownloadDropdown().exists()).toBe(false);
diff --git a/spec/support/shared_examples/features/project_upload_files_shared_examples.rb b/spec/support/shared_examples/features/project_upload_files_shared_examples.rb
index 63d77e9e0a02866eae5371ad63a33e4a72cd1c6b..a6cc14b676fd994ca894f6532956edd76ec8f5b6 100644
--- a/spec/support/shared_examples/features/project_upload_files_shared_examples.rb
+++ b/spec/support/shared_examples/features/project_upload_files_shared_examples.rb
@@ -4,7 +4,7 @@
   it 'uploads and commits a new text file', :js do
     find('.add-to-tree').click
 
-    page.within('.repo-breadcrumb') do
+    page.within('[data-testid="add-to-tree"]') do
       click_button('Upload file')
 
       wait_for_requests
@@ -16,7 +16,7 @@
       attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
     end
 
-    page.within('#modal-upload-blob') do
+    page.within('[data-testid="commit-change-modal"]') do
       fill_in(:commit_message, with: 'New commit message')
       choose(option: true)
       fill_in(:branch_name, with: 'upload_text', visible: true)
@@ -40,7 +40,7 @@
   it 'uploads and commits a new image file', :js do
     find('.add-to-tree').click
 
-    page.within('.repo-breadcrumb') do
+    page.within('[data-testid="add-to-tree"]') do
       click_button('Upload file')
 
       wait_for_requests
@@ -52,7 +52,7 @@
       attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'logo_sample.svg'), make_visible: true)
     end
 
-    page.within('#modal-upload-blob') do
+    page.within('[data-testid="commit-change-modal"]') do
       fill_in(:commit_message, with: 'New commit message')
       choose(option: true)
       fill_in(:branch_name, with: 'upload_image', visible: true)
@@ -71,7 +71,7 @@
   it 'uploads and commits a new pdf file', :js do
     find('.add-to-tree').click
 
-    page.within('.repo-breadcrumb') do
+    page.within('[data-testid="add-to-tree"]') do
       click_button('Upload file')
 
       wait_for_requests
@@ -83,7 +83,7 @@
       attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'sample.pdf'), make_visible: true)
     end
 
-    page.within('#modal-upload-blob') do
+    page.within('[data-testid="commit-change-modal"]') do
       fill_in(:commit_message, with: 'New commit message')
       choose(option: true)
       fill_in(:branch_name, with: 'upload_image', visible: true)
@@ -124,7 +124,7 @@
       attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
     end
 
-    page.within('#modal-upload-blob') do
+    page.within('[data-testid="commit-change-modal"]') do
       fill_in(:commit_message, with: 'New commit message')
       click_button('Commit changes')
     end
@@ -161,7 +161,7 @@
       attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
     end
 
-    page.within('#modal-upload-blob') do
+    page.within('[data-testid="commit-change-modal"]') do
       fill_in(:commit_message, with: 'New commit message')
       click_button('Commit changes')
     end