diff --git a/app/assets/stylesheets/framework/images.scss b/app/assets/stylesheets/framework/images.scss
index 1e93bf2b7515b632f26f2c5a5077b685b93d4575..a20920e25033bd9d89c0e49afb6635859e43b44c 100644
--- a/app/assets/stylesheets/framework/images.scss
+++ b/app/assets/stylesheets/framework/images.scss
@@ -39,7 +39,7 @@
 svg {
   fill: currentColor;
 
-  $svg-sizes: 8 10 12 16 18 24 32 48 72;
+  $svg-sizes: 8 10 12 14 16 18 24 32 48 72;
   @each $svg-size in $svg-sizes {
     &.s#{$svg-size} {
       @include svg-size(#{$svg-size}px);
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 19eee4e4abaa2880ae099d23a5f41e139d1549c1..bfcac3f1c3f5adb6e1516ceec68eba277da9ee6f 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -269,6 +269,7 @@ $flash-height: 52px;
 $context-header-height: 60px;
 $breadcrumb-min-height: 48px;
 $project-title-row-height: 24px;
+$gl-line-height: 16px;
 
 /*
 * Common component specific colors
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index a91d44805ee104ffe892c5d935eb0934c11fe6ba..618f23d81b12b68a0eb99f59a22c9851fc806f57 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -4,41 +4,29 @@
  */
 .event-item {
   font-size: $gl-font-size;
-  padding: $gl-padding-top 0 $gl-padding-top 40px;
+  padding: $gl-padding 0 $gl-padding 56px;
   border-bottom: 1px solid $white-normal;
-  color: $gl-text-color;
+  color: $gl-text-color-secondary;
   position: relative;
-
-  &.event-inline {
-    .system-note-image {
-      top: 20px;
-    }
-
-    .user-avatar {
-      top: 14px;
-    }
-
-    .event-title,
-    .event-item-timestamp {
-      line-height: 40px;
-    }
-  }
-
-  a {
-    color: $gl-text-color;
-  }
+  line-height: $gl-line-height;
 
   .system-note-image {
     position: absolute;
     left: 0;
-    top: 14px;
 
     svg {
-      width: 20px;
-      height: 20px;
       fill: $gl-text-color-secondary;
     }
+  }
+
+  .system-note-image-inline {
+    svg {
+      fill: $gl-text-color-secondary;
+    }
+  }
 
+  .system-note-image,
+  .system-note-image-inline {
     &.opened-icon,
     &.created-icon {
       svg {
@@ -53,16 +41,35 @@
     &.accepted-icon svg {
       fill: $blue-300;
     }
+
+    &.commented-on-icon svg {
+      fill: $blue-600;
+    }
+  }
+
+  .event-user-info {
+    margin-bottom: $gl-padding-8;
+
+    .author_name {
+      a {
+        color: $gl-text-color;
+        font-weight: $gl-font-weight-bold;
+      }
+    }
   }
 
   .event-title {
-    @include str-truncated(calc(100% - 174px));
-    font-weight: $gl-font-weight-bold;
-    color: $gl-text-color;
+    .event-type {
+      &::first-letter {
+        text-transform: capitalize;
+      }
+    }
   }
 
   .event-body {
+    margin-top: $gl-padding-8;
     margin-right: 174px;
+    color: $gl-text-color;
 
     .event-note {
       word-wrap: break-word;
@@ -92,7 +99,7 @@
       }
 
       .note-image-attach {
-        margin-top: 4px;
+        margin-top: $gl-padding-4;
         margin-left: 0;
         max-width: 200px;
         float: none;
@@ -107,7 +114,6 @@
       color: $gl-gray-500;
       float: left;
       font-size: $gl-font-size;
-      line-height: 16px;
       margin-right: 5px;
     }
   }
@@ -127,7 +133,9 @@
     }
   }
 
-  &:last-child { border: 0; }
+  &:last-child {
+    border: 0;
+  }
 
   .event_commits {
     li {
@@ -154,7 +162,6 @@
 
   .event-item-timestamp {
     float: right;
-    line-height: 22px;
   }
 }
 
@@ -177,10 +184,8 @@
   .event-item {
     padding-left: 0;
 
-    &.event-inline {
-      .event-title {
-        line-height: 20px;
-      }
+    .event-user-info {
+      margin-bottom: $gl-padding-4;
     }
 
     .event-title {
@@ -194,7 +199,8 @@
     }
 
     .event-body {
-      margin: 0;
+      margin-top: $gl-padding-4;
+      margin-right: 0;
       padding-left: 0;
     }
 
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index f084adaf5d3114a9a30c8c8bbf301f7f8e6e8bfa..1d691d1d8b80ba4d21fb00be4e86c1154aa944d8 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -240,6 +240,12 @@
     left: 0;
   }
 
+  .activities-block {
+    .event-item {
+      padding-left: 40px;
+    }
+  }
+
   @include media-breakpoint-down(xs) {
     .cover-block {
       padding-top: 20px;
@@ -267,6 +273,12 @@
         margin-right: 0;
       }
     }
+
+    .activities-block {
+      .event-item {
+        padding-left: 0;
+      }
+    }
   }
 }
 
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index c94946a04e720bfd197190a3670fbce0712bb819..2adfc04deb83d0b083b1810c3b6a9ad0b1051ffb 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -163,14 +163,10 @@ module EventsHelper
 
   def event_note_title_html(event)
     if event.note_target
-      text = raw("#{event.note_target_type} ") +
-        if event.commit_note?
-          content_tag(:span, event.note_target_reference, class: 'commit-sha')
-        else
-          event.note_target_reference
-        end
-
-      link_to(text, event_note_target_url(event), title: event.target_title, class: 'has-tooltip')
+      capture do
+        concat content_tag(:span, event.note_target_type, class: "event-target-type append-right-4")
+        concat link_to(event.note_target_reference, event_note_target_url(event), title: event.target_title, class: 'has-tooltip event-target-link append-right-4')
+      end
     else
       content_tag(:strong, '(deleted)')
     end
@@ -183,17 +179,9 @@ module EventsHelper
     "--broken encoding"
   end
 
-  def event_row_class(event)
-    if event.body?
-      "event-block"
-    else
-      "event-inline"
-    end
-  end
-
-  def icon_for_event(note)
+  def icon_for_event(note, size: 24)
     icon_name = ICON_NAMES_BY_EVENT_TYPE[note]
-    sprite_icon(icon_name) if icon_name
+    sprite_icon(icon_name, size: size) if icon_name
   end
 
   def icon_for_profile_event(event)
@@ -203,8 +191,24 @@ module EventsHelper
       end
     else
       content_tag :div, class: 'system-note-image user-avatar' do
-        author_avatar(event, size: 32)
+        author_avatar(event, size: 40)
+      end
+    end
+  end
+
+  def inline_event_icon(event)
+    unless current_path?('users#show')
+      content_tag :span, class: "system-note-image-inline d-none d-sm-flex append-right-4 #{event.action_name.parameterize}-icon align-self-center" do
+        icon_for_event(event.action_name, size: 14)
       end
     end
   end
+
+  def event_user_info(event)
+    content_tag(:div, class: "event-user-info") do
+      concat content_tag(:span, link_to_author(event), class: "author_name")
+      concat " ".html_safe
+      concat content_tag(:span, event.author.to_reference, class: "username")
+    end
+  end
 end
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index 78a1d1a0553c2c47b299eb419d6396062c9deeb8..2fcb1d1fd2b33e0acc244a2439d7c9b2286893b1 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -1,5 +1,5 @@
 - if event.visible_to_user?(current_user)
-  .event-item{ class: event_row_class(event) }
+  .event-item
     .event-item-timestamp
       #{time_ago_with_tooltip(event.created_at)}
 
diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml
index 829a3da15580c2132eb7280d157f396fc79d7826..96d6553a2acc97140006c32059894ce53751a51c 100644
--- a/app/views/events/event/_common.html.haml
+++ b/app/views/events/event/_common.html.haml
@@ -1,20 +1,19 @@
 = icon_for_profile_event(event)
 
-.event-title
-  %span.author_name= link_to_author(event)
-  %span{ class: event.action_name }
+= event_user_info(event)
+
+.event-title.d-flex.flex-wrap
+  = inline_event_icon(event)
   - if event.target
-    = event.action_name
-    %strong
-      = link_to [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip', title: event.target_title do
-        = event.target_type.titleize.downcase
-        = event.target.reference_link_text
+    %span.event-type.d-inline-block.append-right-4{ class: event.action_name }
+      = event.action_name
+    %span.event-target-type.append-right-4= event.target_type.titleize.downcase
+    = link_to [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip event-target-link append-right-4', title: event.target_title do
+      = event.target.reference_link_text
+    - unless event.milestone?
+      %span.event-target-title.append-right-4= """.html_safe + event.target.title + "&quot".html_safe
   - else
-    = event_action_name(event)
+    %span.event-type.d-inline-block.append-right-4{ class: event.action_name }
+      = event_action_name(event)
 
   = render "events/event_scope", event: event
-
-- if event.target.respond_to?(:title)
-  .event-body
-    .event-note
-      = event.target.title
diff --git a/app/views/events/event/_created_project.html.haml b/app/views/events/event/_created_project.html.haml
index 6ad7e15713181ea79db69879bb052791889b9ada..2f1566034148dbf86b8a654f3ef6cc31e1e67cae 100644
--- a/app/views/events/event/_created_project.html.haml
+++ b/app/views/events/event/_created_project.html.haml
@@ -1,8 +1,10 @@
 = icon_for_profile_event(event)
 
-.event-title
-  %span.author_name= link_to_author(event)
-  %span{ class: event.action_name }
+= event_user_info(event)
+
+.event-title.d-flex.flex-wrap
+  = inline_event_icon(event)
+  %span.event-type.d-inline-block.append-right-4{ class: event.action_name }
     = event_action_name(event)
 
   - if event.project
diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml
index cdacd998a6987434c11780bbf5b92c5321406a95..fb0d2c3b8b0b64f506ecbc39c1b536580700616d 100644
--- a/app/views/events/event/_note.html.haml
+++ b/app/views/events/event/_note.html.haml
@@ -1,9 +1,13 @@
 = icon_for_profile_event(event)
 
-.event-title
-  %span.author_name= link_to_author(event)
-  = event.action_name
+= event_user_info(event)
+
+.event-title.d-flex.flex-wrap
+  = inline_event_icon(event)
+  %span.event-type.d-inline-block.append-right-4{ class: event.action_name }
+    = event.action_name
   = event_note_title_html(event)
+  %span.event-target-title.append-right-4= """.html_safe + event.target.title + "&quot".html_safe
 
   = render "events/event_scope", event: event
 
diff --git a/app/views/events/event/_private.html.haml b/app/views/events/event/_private.html.haml
index ccd2aacb4eafa929930cc19d7d3cf93213b3a354..d91f30c07cb6b60fc3b8460ac98a77b0927bb45f 100644
--- a/app/views/events/event/_private.html.haml
+++ b/app/views/events/event/_private.html.haml
@@ -1,10 +1,11 @@
-.event-inline.event-item
+.event-item
   .event-item-timestamp
     = time_ago_with_tooltip(event.created_at)
 
-  .system-note-image= sprite_icon('eye-slash', size: 16, css_class: 'icon')
+  .system-note-image= sprite_icon('eye-slash', size: 24, css_class: 'icon')
 
-  .event-title
-    - author_name = capture do
-      %span.author_name= link_to_author(event)
-    = s_('Profiles|%{author_name} made a private contribution').html_safe % { author_name: author_name }
+  = event_user_info(event)
+
+  .event-title.d-flex.flex-wrap
+    = inline_event_icon(event)
+    = s_('Profiles|Made a private contribution')
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index 5f0ee79cd9b1f0b77e08dce0d64e74cff8a0d170..82693ec832e3ce89e5795ef19ce5ed1888872627 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -2,13 +2,15 @@
 
 = icon_for_profile_event(event)
 
-.event-title
-  %span.author_name= link_to_author(event)
-  %span.pushed #{event.action_name} #{event.ref_type}
-  %strong
+= event_user_info(event)
+
+.event-title.d-flex.flex-wrap
+  = inline_event_icon(event)
+  %span.event-type.d-inline-block.append-right-4.pushed #{event.action_name} #{event.ref_type}
+  %span
     - commits_link = project_commits_path(project, event.ref_name)
     - should_link = event.tag? ? project.repository.tag_exists?(event.ref_name) : project.repository.branch_exists?(event.ref_name)
-    = link_to_if should_link, event.ref_name, commits_link, class: 'ref-name'
+    = link_to_if should_link, event.ref_name, commits_link, class: 'ref-name append-right-4'
 
   = render "events/event_scope", event: event
 
diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml
index f8b3754840dabeaa817fa9d030a4d8c4479fb4a5..cf525f2bb2d8b10406a86a3890b898a76e321a64 100644
--- a/app/views/users/_overview.html.haml
+++ b/app/views/users/_overview.html.haml
@@ -11,8 +11,8 @@
 
     - if can?(current_user, :read_cross_project)
       .activities-block
-        .content-block
-          %h5.prepend-top-10
+        .border-bottom.prepend-top-16
+          %h5
             = s_('UserProfile|Recent contributions')
           .overview-content-list{ data: { href: user_path } }
             .center.light.loading
@@ -22,7 +22,7 @@
 
   .col-md-12.col-lg-6
     .projects-block
-      .content-block
+      .border-bottom.prepend-top-16
         %h4
           = s_('UserProfile|Personal projects')
         .overview-content-list{ data: { href: user_projects_path } }
diff --git a/changelogs/unreleased/49403-redesign-activity-feed.yml b/changelogs/unreleased/49403-redesign-activity-feed.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cec53a3ef5a66f7842c1e2b28f84f3e285e22ebb
--- /dev/null
+++ b/changelogs/unreleased/49403-redesign-activity-feed.yml
@@ -0,0 +1,4 @@
+title: Redesign activity feed
+merge_request: 22217
+author:
+type: other
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 1c4c9180c426f753575659f7ce9b4911ab29d969..98417c08dfd0cbd2beb9b7615e482fba3c5e9c34 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -4641,9 +4641,6 @@ msgstr ""
 msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
 msgstr ""
 
-msgid "Profiles|%{author_name} made a private contribution"
-msgstr ""
-
 msgid "Profiles|Account scheduled for removal."
 msgstr ""
 
@@ -4704,6 +4701,9 @@ msgstr ""
 msgid "Profiles|Invalid username"
 msgstr ""
 
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
 msgid "Profiles|Main settings"
 msgstr ""
 
diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb
index aa3ca8923ffda57235a8cbf72f7596a5fc2ae131..a1f93bd3fbddd137a2f321f2813f58673ce542aa 100644
--- a/spec/features/calendar_spec.rb
+++ b/spec/features/calendar_spec.rb
@@ -153,7 +153,7 @@ describe 'Contributions Calendar', :js do
         include_context 'visit user page'
 
         it 'displays calendar activity log' do
-          expect(find('.tab-pane#activity .content_list .event-note')).to have_content issue_title
+          expect(find('.tab-pane#activity .content_list .event-target-title')).to have_content issue_title
         end
       end
     end
diff --git a/spec/features/dashboard/project_member_activity_index_spec.rb b/spec/features/dashboard/project_member_activity_index_spec.rb
index 498775acff3ff4049d52ddb68c0f56190b749e9e..16919fe63adc14ae37c56dd2c468649cadef4cc5 100644
--- a/spec/features/dashboard/project_member_activity_index_spec.rb
+++ b/spec/features/dashboard/project_member_activity_index_spec.rb
@@ -14,14 +14,15 @@ describe 'Project member activity', :js do
     wait_for_requests
   end
 
-  subject { page.find(".event-title").text }
-
   context 'when a user joins the project' do
     before do
       visit_activities_and_wait_with_event(Event::JOINED)
     end
 
-    it { is_expected.to eq("#{user.name} joined project") }
+    it "presents the correct message" do
+      expect(page.find('.event-user-info').text).to eq("#{user.name} #{user.to_reference}")
+      expect(page.find('.event-title').text).to eq("joined project")
+    end
   end
 
   context 'when a user leaves the project' do
@@ -29,7 +30,10 @@ describe 'Project member activity', :js do
       visit_activities_and_wait_with_event(Event::LEFT)
     end
 
-    it { is_expected.to eq("#{user.name} left project") }
+    it "presents the correct message" do
+      expect(page.find('.event-user-info').text).to eq("#{user.name} #{user.to_reference}")
+      expect(page.find('.event-title').text).to eq("left project")
+    end
   end
 
   context 'when a users membership expires for the project' do
@@ -38,8 +42,8 @@ describe 'Project member activity', :js do
     end
 
     it "presents the correct message" do
-      message = "#{user.name} removed due to membership expiration from project"
-      is_expected.to eq(message)
+      expect(page.find('.event-user-info').text).to eq("#{user.name} #{user.to_reference}")
+      expect(page.find('.event-title').text).to eq("removed due to membership expiration from project")
     end
   end
 end
diff --git a/spec/features/milestones/user_creates_milestone_spec.rb b/spec/features/milestones/user_creates_milestone_spec.rb
index 8fd057d587cba2a3e3454a562b1f273fa2e1568b..5de0c381cdfb903e9dc315714859f4c1ce9a169a 100644
--- a/spec/features/milestones/user_creates_milestone_spec.rb
+++ b/spec/features/milestones/user_creates_milestone_spec.rb
@@ -24,6 +24,6 @@ describe "User creates milestone", :js do
 
     visit(activity_project_path(project))
 
-    expect(page).to have_content("#{user.name} opened milestone")
+    expect(page).to have_content("#{user.name} #{user.to_reference} opened milestone")
   end
 end
diff --git a/spec/features/milestones/user_deletes_milestone_spec.rb b/spec/features/milestones/user_deletes_milestone_spec.rb
index a8c296b4cd2eaa0b02fa0bbdbd79fc9866f03fa0..f68ed1cde071a2127952a423fffb2f642463521a 100644
--- a/spec/features/milestones/user_deletes_milestone_spec.rb
+++ b/spec/features/milestones/user_deletes_milestone_spec.rb
@@ -23,7 +23,7 @@ describe "User deletes milestone", :js do
 
       visit(activity_project_path(project))
 
-      expect(page).to have_content("#{user.name} destroyed milestone")
+      expect(page).to have_content("#{user.name} #{user.to_reference} destroyed milestone")
     end
   end
 
diff --git a/spec/features/projects/activity/user_sees_activity_spec.rb b/spec/features/projects/activity/user_sees_activity_spec.rb
index ebaa137772d0b51b146d140f0e508e0eb0dca9d7..bb4b2abc3c72d08a01bf57112643ae2c65d1eb32 100644
--- a/spec/features/projects/activity/user_sees_activity_spec.rb
+++ b/spec/features/projects/activity/user_sees_activity_spec.rb
@@ -19,13 +19,13 @@ describe 'Projects > Activity > User sees activity' do
   it 'shows the last push in the activity page', :js do
     visit activity_project_path(project)
 
-    expect(page).to have_content "#{user.name} pushed new branch fix"
+    expect(page).to have_content "#{user.name} #{user.to_reference} pushed new branch fix"
   end
 
   it 'allows to filter event with the "event_filter=issue" URL param', :js do
     visit activity_project_path(project, event_filter: 'issue')
 
-    expect(page).not_to have_content "#{user.name} pushed new branch fix"
-    expect(page).to have_content "#{user.name} opened issue #{issue.to_reference}"
+    expect(page).not_to have_content "#{user.name} #{user.to_reference} pushed new branch fix"
+    expect(page).to have_content "#{user.name} #{user.to_reference} opened issue #{issue.to_reference}"
   end
 end
diff --git a/spec/features/projects/activity/user_sees_private_activity_spec.rb b/spec/features/projects/activity/user_sees_private_activity_spec.rb
index d7dc0a6712a913827cc92b6b619660ee61c8f4ae..61ec2ce9d29dc6e0f0639fcca146f2894ab647c3 100644
--- a/spec/features/projects/activity/user_sees_private_activity_spec.rb
+++ b/spec/features/projects/activity/user_sees_private_activity_spec.rb
@@ -5,7 +5,7 @@ describe 'Project > Activity > User sees private activity', :js do
   let(:author) { create(:user) }
   let(:user) { create(:user) }
   let(:issue) { create(:issue, :confidential, project: project, author: author) }
-  let(:message) { "#{author.name} opened issue #{issue.to_reference}" }
+  let(:message) { "#{author.name} #{author.to_reference} opened issue #{issue.to_reference}" }
 
   before do
     project.add_developer(author)