diff --git a/app/views/admin/topics/_topic.html.haml b/app/views/admin/topics/_topic.html.haml
index ae9fe9675c1aa482e5c65886e2e5882baf3210ff..89a334d73b72a054135e9753799560e05ae45192 100644
--- a/app/views/admin/topics/_topic.html.haml
+++ b/app/views/admin/topics/_topic.html.haml
@@ -1,7 +1,7 @@
 - topic = local_assigns.fetch(:topic)
 - title = topic.title || topic.name
 
-%li.topic-row.gl-py-3.gl-items-center{ class: '!gl-flex' }
+%li.topic-row.gl-py-3.gl-items-center{ class: '!gl-flex !gl-px-5' }
   = render Pajamas::AvatarComponent.new(topic, size: 32, alt: '')
 
   .gl-min-w-0.gl-grow.gl-ml-3
diff --git a/app/views/admin/topics/index.html.haml b/app/views/admin/topics/index.html.haml
index dec30c8e465a774bc83f785255c61d0d1765b02f..7033f3c5b338cbb3776b91e80002599cd95ae598 100644
--- a/app/views/admin/topics/index.html.haml
+++ b/app/views/admin/topics/index.html.haml
@@ -1,23 +1,28 @@
 - page_title _("Topics")
 - add_page_specific_style 'page_bundles/search'
+- search = params[:search]
+- show_empty_search = @topics.empty? && search
+- show_empty_state = @topics.empty? && !search
 
-= render ::Layouts::PageHeadingComponent.new(_('Topics'), options: { data: { event_tracking_load: 'true', event_tracking: 'view_admin_topics_pageload' } }) do |c|
-  - c.with_actions do
-    .js-merge-topics{ data: { path: merge_admin_topics_path } }
-    = render Pajamas::ButtonComponent.new(href: new_admin_topic_path, variant: 'confirm') do
-      = _('New topic')
+- if show_empty_state
+  = render 'shared/empty_states/topics', button_text: _('New topic'), button_path: new_admin_topic_path
+- else
+  = render ::Layouts::PageHeadingComponent.new(_('Topics'), options: { data: { event_tracking_load: 'true', event_tracking: 'view_admin_topics_pageload' } }) do |c|
+    - c.with_actions do
+      .js-merge-topics{ data: { path: merge_admin_topics_path } }
+      = render Pajamas::ButtonComponent.new(href: new_admin_topic_path, variant: 'confirm') do
+        = _('New topic')
 
-.gl-flex.gl-min-w-0.gl-grow.row-content-block
-  = form_tag admin_topics_path, method: :get, class: 'gl-w-full' do |f|
-    - search = params.fetch(:search, nil)
-    .search-field-holder
-      = search_field_tag :search, search, class: "form-control gl-form-input search-text-input js-search-input", autofocus: true, spellcheck: false, placeholder: _('Search by name')
-      = sprite_icon('search', css_class: 'search-icon')
+  .gl-flex.gl-min-w-0.gl-grow.row-content-block
+    = form_tag admin_topics_path, method: :get, class: 'gl-w-full' do |f|
+      - search = params.fetch(:search, nil)
+      .search-field-holder
+        = search_field_tag :search, search, class: "form-control gl-form-input search-text-input js-search-input", autofocus: true, spellcheck: false, placeholder: _('Search by name')
+        = sprite_icon('search', css_class: 'search-icon')
 
-%ul.content-list
-  = render partial: 'topic', collection: @topics
-
-= paginate_collection @topics
-
-- if @topics.empty?
-  = render 'shared/empty_states/topics'
+  - if show_empty_search
+    = render ::Layouts::EmptyResultComponent.new(type: :search)
+  - else
+    %ul.content-list
+      = render partial: 'topic', collection: @topics
+    = paginate_collection @topics
diff --git a/app/views/explore/projects/topics.html.haml b/app/views/explore/projects/topics.html.haml
index 08cd122c6aa519453e2a8de995487aa996bca6b8..05253c1b4eeb1c011568a6307faa0ef35eb3e065 100644
--- a/app/views/explore/projects/topics.html.haml
+++ b/app/views/explore/projects/topics.html.haml
@@ -1,9 +1,13 @@
 - breadcrumb_title _("Topics")
 - page_title    _("Explore topics")
 - header_title  _("Topics"), topics_explore_projects_path
+- search = params[:search]
+- show_empty_state = @topics.empty? && !search
 
 = render_dashboard_ultimate_trial(current_user)
 
-= render 'explore/topics/head'
-
-= render partial: 'shared/topics/list'
+- if show_empty_state
+  = render 'shared/empty_states/topics'
+- else
+  = render 'explore/topics/head'
+  = render partial: 'shared/topics/list'
diff --git a/app/views/explore/topics/_head.html.haml b/app/views/explore/topics/_head.html.haml
index 2ec0b8427086752897defe6da9603d803f73ca80..0291bcb8668d89bcc7c78e82d3d885103c57808c 100644
--- a/app/views/explore/topics/_head.html.haml
+++ b/app/views/explore/topics/_head.html.haml
@@ -1,6 +1,4 @@
-.page-title-holder.gl-flex.gl-items-center
-  %h1.page-title.gl-text-size-h-display= page_title
+= render ::Layouts::PageHeadingComponent.new(page_title)
 
-.top-area.gl-p-4
-  .nav-controls
-    = render 'shared/topics/search_form'
+.gl-flex.gl-min-w-0.gl-grow.row-content-block
+  = render 'shared/topics/search_form'
diff --git a/app/views/shared/empty_states/_topics.html.haml b/app/views/shared/empty_states/_topics.html.haml
index 04f859bb60384968e3f355c9b665eeb485dc5f7c..53791687792ec746136fa6198c0fc42ab9df2102 100644
--- a/app/views/shared/empty_states/_topics.html.haml
+++ b/app/views/shared/empty_states/_topics.html.haml
@@ -1,5 +1,10 @@
+- primary_button_text = local_assigns.fetch(:button_text, nil)
+- primary_button_link = local_assigns.fetch(:button_path, nil)
+
 = render Pajamas::EmptyStateComponent.new(svg_path: 'illustrations/empty-state/empty-labels-md.svg',
-  title: _('There are no topics to show'))  do |c|
+  title: _('There are no topics to show'),
+  primary_button_text: primary_button_text,
+  primary_button_link: primary_button_link)  do |c|
 
   - c.with_description do
     = _('Add topics to projects to help users find them.')
diff --git a/app/views/shared/topics/_list.html.haml b/app/views/shared/topics/_list.html.haml
index ddf47261d4243da210d7f0d4ca632b85eda29b8c..4015fc0f2c59f647572b73b801e9de3dc46a1c06 100644
--- a/app/views/shared/topics/_list.html.haml
+++ b/app/views/shared/topics/_list.html.haml
@@ -1,9 +1,9 @@
 - remote = local_assigns.fetch(:remote, false)
+- search = params[:search]
+- show_empty_search = @topics.empty? && search
 
-- if @topics.empty?
-  = render 'shared/empty_states/topics'
+- if show_empty_search
+  = render ::Layouts::EmptyResultComponent.new(type: :search)
 - else
-  .row.gl-mt-3
-    = render partial: 'shared/topics/topic', collection: @topics
-
+  = render partial: 'shared/topics/topic', collection: @topics
   = paginate_collection @topics, remote: remote
diff --git a/app/views/shared/topics/_search_form.html.haml b/app/views/shared/topics/_search_form.html.haml
index 2806b2865ddfad737a638b314eb8dec6a81943df..ac32099b1010216e715d36da4f117894e55b7c98 100644
--- a/app/views/shared/topics/_search_form.html.haml
+++ b/app/views/shared/topics/_search_form.html.haml
@@ -1,7 +1,7 @@
-= form_tag page_filter_path, method: :get, class: "topic-filter-form js-topic-filter-form", id: 'topic-filter-form' do |f|
+= form_tag page_filter_path, method: :get, class: "topic-filter-form js-topic-filter-form gl-grow", id: 'topic-filter-form' do |f|
   = search_field_tag :search, params[:search],
     placeholder: _('Filter by name'),
-    class: 'topic-filter-form-field form-control input-short',
+    class: 'topic-filter-form-field form-control',
     spellcheck: false,
     id: 'topic-filter-form-field',
     autofocus: local_assigns[:autofocus]
diff --git a/app/views/shared/topics/_topic.html.haml b/app/views/shared/topics/_topic.html.haml
index c0473ddb61d29a02fc2da66e7b2f27f9ad68a155..4ab5b9afe55c753c9f96cde409fd74dd94307e0b 100644
--- a/app/views/shared/topics/_topic.html.haml
+++ b/app/views/shared/topics/_topic.html.haml
@@ -1,7 +1,7 @@
 - max_topic_title_length = 30
 - detail_page_link = topic_explore_projects_cleaned_path(topic_name: topic.name)
 
-.col-lg-3.col-md-4.col-sm-12
+.gl-mt-5.gl-grid{ class: 'sm:gl-grid-cols-2 md:gl-grid-cols-3 ml:gl-grid-cols-3' }
   = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' },
                                       body_options: { class: 'gl-flex gl-items-center' }) do |c|
     - c.with_body do