diff --git a/e2e/support/helpers/e2e-dashboard-helpers.ts b/e2e/support/helpers/e2e-dashboard-helpers.ts
index 8e1885dc86a1d08cbad2c0c6373683f178e61da8..582964ffc8325f183a2c82e2f6acc6188e4b8ac5 100644
--- a/e2e/support/helpers/e2e-dashboard-helpers.ts
+++ b/e2e/support/helpers/e2e-dashboard-helpers.ts
@@ -6,7 +6,7 @@ import type {
 } from "metabase-types/api";
 
 import { visitDashboard } from "./e2e-misc-helpers";
-import { menu, popover, sidebar } from "./e2e-ui-elements-helpers";
+import { menu, popover, sidebar, sidesheet } from "./e2e-ui-elements-helpers";
 
 // Metabase utility functions for commonly-used patterns
 export function selectDashboardFilter(
@@ -260,9 +260,12 @@ export function resizeDashboardCard({
   });
 }
 
-export function toggleDashboardInfoSidebar() {
+export function openDashboardInfoSidebar() {
   dashboardHeader().icon("info").click();
 }
+export function closeDashboardInfoSidebar() {
+  sidesheet().findByLabelText("Close").click();
+}
 
 export function openDashboardMenu() {
   dashboardHeader().findByLabelText("Move, trash, and more…").click();
diff --git a/e2e/test/scenarios/admin-2/api-keys.cy.spec.ts b/e2e/test/scenarios/admin-2/api-keys.cy.spec.ts
index e678b56509796514f7cc61dc905acc289c8dbaf1..69fac0029fa37c7cb46ec7eb6da4c75fe54313ad 100644
--- a/e2e/test/scenarios/admin-2/api-keys.cy.spec.ts
+++ b/e2e/test/scenarios/admin-2/api-keys.cy.spec.ts
@@ -214,9 +214,10 @@ describe("scenarios > admin > settings > API keys", () => {
             visitDashboard(dashboardId);
             cy.findByTestId("dashboard-header").findByText("Test Dashboard");
             cy.findByTestId("dashboard-header").icon("info").click();
-            cy.findByTestId("sidebar-right").findByText(
-              "Test API Key One created this.",
-            );
+            sidesheet().within(() => {
+              cy.findByRole("tab", { name: "History" }).click();
+              cy.findByText("Test API Key One created this.");
+            });
           });
         },
       );
@@ -256,7 +257,8 @@ describe("scenarios > admin > settings > API keys", () => {
               "Edited Dashboard Name",
             );
             cy.findByTestId("dashboard-header").icon("info").click();
-            cy.findByTestId("sidebar-right").within(() => {
+            sidesheet().within(() => {
+              cy.findByRole("tab", { name: "History" }).click();
               cy.findByText("You created this.");
               cy.findByText(
                 'Test API Key One renamed this Dashboard from "Orders in a dashboard" to "Edited Dashboard Name".',
diff --git a/e2e/test/scenarios/admin/performance/helpers/e2e-strategy-form-helpers.ts b/e2e/test/scenarios/admin/performance/helpers/e2e-strategy-form-helpers.ts
index 813291bd5a0d791bae75e5c471a152582b25aa33..2570c11f6121847555d52feb586a46ec141bebb8 100644
--- a/e2e/test/scenarios/admin/performance/helpers/e2e-strategy-form-helpers.ts
+++ b/e2e/test/scenarios/admin/performance/helpers/e2e-strategy-form-helpers.ts
@@ -178,16 +178,6 @@ export const selectCacheStrategy = ({
   }
 
   saveCacheStrategyForm({ strategyType: strategy.type, model: item?.model });
-
-  if (item?.model === "question") {
-    cy.findByLabelText("Close").click();
-  }
-
-  // Once dashboard sidesheets is merged, we can change this to use the same
-  // approach that we use for questions.
-  if (item?.model === "dashboard") {
-    cy.findByLabelText("More info").click();
-  }
 };
 
 export const disableCaching = (
diff --git a/e2e/test/scenarios/collections/revision-history.cy.spec.js b/e2e/test/scenarios/collections/revision-history.cy.spec.js
index 076329b1744d434a9805b093f1728da6b71849d4..5e10477ff5996d743c301e23d03b7d3527170e00 100644
--- a/e2e/test/scenarios/collections/revision-history.cy.spec.js
+++ b/e2e/test/scenarios/collections/revision-history.cy.spec.js
@@ -9,9 +9,9 @@ import {
   openQuestionsSidebar,
   questionInfoButton,
   restore,
-  rightSidebar,
   saveDashboard,
   sidebar,
+  sidesheet,
   visitDashboard,
   visitQuestion,
 } from "e2e/support/helpers";
@@ -94,7 +94,8 @@ describe("revision history", () => {
               cy.wait(100);
 
               openRevisionHistory();
-              rightSidebar().within(() => {
+              sidesheet().within(() => {
+                cy.findByRole("tab", { name: "History" }).click();
                 cy.findByText(/added a card/)
                   .siblings("button")
                   .should("not.exist");
@@ -206,9 +207,10 @@ function openRevisionHistory() {
   cy.get("main header").within(() => {
     cy.icon("info").click();
   });
+  cy.findByRole("tab", { name: "History" }).click();
   cy.wait("@revisionHistory");
 
-  rightSidebar().within(() => {
+  sidesheet().within(() => {
     cy.findByText("History");
     cy.findByTestId("dashboard-history-list").should("be.visible");
   });
diff --git a/e2e/test/scenarios/dashboard-filters/dashboard-filters-auto-apply.cy.spec.js b/e2e/test/scenarios/dashboard-filters/dashboard-filters-auto-apply.cy.spec.js
index d2fb9357b8bd50f6ad5ecc4928b1d61955e844cd..ad97648a01ac801f5868cdc0d862867426c9743f 100644
--- a/e2e/test/scenarios/dashboard-filters/dashboard-filters-auto-apply.cy.spec.js
+++ b/e2e/test/scenarios/dashboard-filters/dashboard-filters-auto-apply.cy.spec.js
@@ -1,5 +1,6 @@
 import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
 import {
+  closeDashboardInfoSidebar,
   dashboardParametersContainer,
   describeWithSnowplow,
   editDashboard,
@@ -8,14 +9,14 @@ import {
   expectNoBadSnowplowEvents,
   filterWidget,
   getDashboardCard,
+  openDashboardInfoSidebar,
   popover,
   resetSnowplow,
   restore,
-  rightSidebar,
   saveDashboard,
   setFilter,
   sidebar,
-  toggleDashboardInfoSidebar,
+  sidesheet,
   undoToast,
   visitDashboard,
   visitEmbeddedPage,
@@ -93,12 +94,13 @@ describe(
         cy.log(
           "parameter values should be preserved when disabling auto applying filters",
         );
-        toggleDashboardInfoSidebar();
-        rightSidebar().within(() => {
+        openDashboardInfoSidebar();
+        sidesheet().within(() => {
           cy.findByText(filterToggleLabel).click();
           cy.wait("@updateDashboard");
           cy.findByLabelText(filterToggleLabel).should("not.be.checked");
         });
+        closeDashboardInfoSidebar();
         filterWidget().findByText("Gadget").should("be.visible");
         getDashboardCard().findByText("Rows 1-4 of 53").should("be.visible");
 
@@ -126,11 +128,15 @@ describe(
         });
         filterWidget().findByText("Widget").should("be.visible");
         dashboardParametersContainer().button("Apply").should("be.visible");
-        rightSidebar().within(() => {
+
+        openDashboardInfoSidebar();
+        sidesheet().within(() => {
           cy.findByText(filterToggleLabel).click();
           cy.wait("@updateDashboard");
           cy.findByLabelText(filterToggleLabel).should("be.checked");
         });
+        closeDashboardInfoSidebar();
+
         filterWidget().findByText("Widget").should("be.visible");
         getDashboardCard().findByText("Rows 1-4 of 54").should("be.visible");
         cy.get("@cardQuery.all").should("have.length", 4);
@@ -143,11 +149,15 @@ describe(
           cy.findByText("Gadget").click();
           cy.button("Update filter").click();
         });
-        rightSidebar().within(() => {
+
+        openDashboardInfoSidebar();
+        sidesheet().within(() => {
           cy.findByText(filterToggleLabel).click();
           cy.wait("@updateDashboard");
           cy.findByLabelText(filterToggleLabel).should("not.be.checked");
         });
+        closeDashboardInfoSidebar();
+
         filterWidget().findByText("2 selections").should("be.visible");
         cy.get("@cardQuery.all").should("have.length", 5);
 
@@ -230,19 +240,20 @@ describe(
 
       it("should handle toggling auto applying filters on and off", () => {
         openDashboard();
-        toggleDashboardInfoSidebar();
+        openDashboardInfoSidebar();
 
         getDashboardCard().findByText("Rows 1-4 of 53").should("be.visible");
 
         cy.log(
           "parameter with default value should still be applied after turning auto-apply filter off",
         );
-        rightSidebar().within(() => {
+        sidesheet().within(() => {
           cy.findByLabelText(filterToggleLabel).should("be.checked");
           cy.findByText(filterToggleLabel).click();
           cy.wait("@updateDashboard");
           cy.findByLabelText(filterToggleLabel).should("not.be.checked");
         });
+        closeDashboardInfoSidebar();
 
         getDashboardCard().findByText("Rows 1-4 of 53").should("be.visible");
 
@@ -260,7 +271,8 @@ describe(
         cy.log(
           "should not use the default parameter after turning auto-apply filter on again since the parameter was manually updated",
         );
-        rightSidebar().within(() => {
+        openDashboardInfoSidebar();
+        sidesheet().within(() => {
           cy.findByLabelText(filterToggleLabel).should("not.be.checked");
           cy.findAllByText(filterToggleLabel).click();
           cy.wait("@updateDashboard");
@@ -282,10 +294,8 @@ describe(
           cy.wait("@updateDashboard");
         });
 
-        toggleDashboardInfoSidebar();
-        rightSidebar()
-          .findByLabelText(filterToggleLabel)
-          .should("not.be.checked");
+        openDashboardInfoSidebar();
+        sidesheet().findByLabelText(filterToggleLabel).should("not.be.checked");
         // Gadget
         const filterDefaultValue = FILTER_WITH_DEFAULT_VALUE.default[0];
         filterWidget().findByText(filterDefaultValue).should("be.visible");
@@ -317,10 +327,9 @@ describe(
           cy.wait("@updateDashboard");
         });
 
-        toggleDashboardInfoSidebar();
-        rightSidebar()
-          .findByLabelText(filterToggleLabel)
-          .should("not.be.checked");
+        openDashboardInfoSidebar();
+        sidesheet().findByLabelText(filterToggleLabel).should("not.be.checked");
+        closeDashboardInfoSidebar();
         filterWidget().findByText("Gadget").should("be.visible");
         getDashboardCard().findByText("Rows 1-4 of 53").should("be.visible");
       });
@@ -396,8 +405,8 @@ describe(
         openDashboard();
         cy.wait("@cardQuery");
 
-        toggleDashboardInfoSidebar();
-        rightSidebar().findByLabelText(filterToggleLabel).should("be.disabled");
+        openDashboardInfoSidebar();
+        sidesheet().findByLabelText(filterToggleLabel).should("be.disabled");
       });
 
       it.skip("should not display a toast even when a dashboard takes longer than 15s to load", () => {
@@ -557,8 +566,8 @@ describe(
           // so to make sure callback in `setTimeout` is called, we need to advance the clock using cy.tick().
           cy.tick();
 
-          toggleDashboardInfoSidebar();
-          rightSidebar()
+          openDashboardInfoSidebar();
+          sidesheet()
             .findByLabelText(filterToggleLabel)
             .should("not.be.checked");
           filterWidget().findByText("Gadget").should("be.visible");
@@ -616,8 +625,8 @@ describeWithSnowplow("scenarios > dashboards > filters > auto apply", () => {
     openDashboard();
     cy.wait("@cardQuery");
 
-    toggleDashboardInfoSidebar();
-    rightSidebar().within(() => {
+    openDashboardInfoSidebar();
+    sidesheet().within(() => {
       expectGoodSnowplowEvents(
         NUMBERS_OF_GOOD_SNOWPLOW_EVENTS_BEFORE_DISABLING_AUTO_APPLY_FILTERS,
       );
@@ -635,8 +644,8 @@ describeWithSnowplow("scenarios > dashboards > filters > auto apply", () => {
     openDashboard();
     cy.wait("@cardQuery");
 
-    toggleDashboardInfoSidebar();
-    rightSidebar().within(() => {
+    openDashboardInfoSidebar();
+    sidesheet().within(() => {
       expectGoodSnowplowEvents(
         NUMBERS_OF_GOOD_SNOWPLOW_EVENTS_BEFORE_DISABLING_AUTO_APPLY_FILTERS,
       );
diff --git a/e2e/test/scenarios/dashboard/dashboard-management.cy.spec.js b/e2e/test/scenarios/dashboard/dashboard-management.cy.spec.js
index d4b0061f647f6b8d31f78f119c18051c36bae76f..3fd958db3b4d0da6c63cfdfa4c1c58a953bbdcd1 100644
--- a/e2e/test/scenarios/dashboard/dashboard-management.cy.spec.js
+++ b/e2e/test/scenarios/dashboard/dashboard-management.cy.spec.js
@@ -4,17 +4,18 @@ import { USERS } from "e2e/support/cypress_data";
 import { ORDERS_DASHBOARD_ID } from "e2e/support/cypress_sample_instance_data";
 import {
   appBar,
+  closeDashboardInfoSidebar,
   collectionOnTheGoModal,
   entityPickerModal,
   getDashboardCard,
   modal,
   navigationSidebar,
+  openDashboardInfoSidebar,
   openDashboardMenu,
   openNavigationSidebar,
   popover,
   restore,
-  rightSidebar,
-  toggleDashboardInfoSidebar,
+  sidesheet,
   undoToast,
   visitDashboard,
 } from "e2e/support/helpers";
@@ -71,12 +72,13 @@ describe("managing dashboard from the dashboard's edit menu", () => {
               assertOnRequest("updateDashboard");
               assertOnRequest("getDashboard");
 
-              toggleDashboardInfoSidebar();
+              openDashboardInfoSidebar();
 
-              rightSidebar()
+              sidesheet()
                 .findByPlaceholderText("Add description")
                 .type("Foo")
                 .blur();
+              closeDashboardInfoSidebar();
 
               assertOnRequest("updateDashboard");
               assertOnRequest("getDashboard");
diff --git a/e2e/test/scenarios/dashboard/dashboard-reproductions.cy.spec.js b/e2e/test/scenarios/dashboard/dashboard-reproductions.cy.spec.js
index 613aa2b2dad647a6c5c2b374667b8427d351a371..38ed2ae30639cf9c6b6e411ece3f2cbc65016b7f 100644
--- a/e2e/test/scenarios/dashboard/dashboard-reproductions.cy.spec.js
+++ b/e2e/test/scenarios/dashboard/dashboard-reproductions.cy.spec.js
@@ -11,6 +11,7 @@ import {
   addTextBox,
   appBar,
   cartesianChartCircle,
+  closeDashboardInfoSidebar,
   createDashboard,
   createDashboardWithTabs,
   dashboardGrid,
@@ -27,18 +28,18 @@ import {
   main,
   modal,
   navigationSidebar,
+  openDashboardInfoSidebar,
   openQuestionsSidebar,
   popover,
   queryBuilderHeader,
   removeDashboardCard,
   restore,
-  rightSidebar,
   saveDashboard,
   setFilter,
   setTokenFeatures,
   showDashboardCardActions,
   sidebar,
-  toggleDashboardInfoSidebar,
+  sidesheet,
   undo,
   undoToast,
   updateDashboardCards,
@@ -329,58 +330,82 @@ describe("issue 16559", () => {
     "should always show the most recent revision (metabase#16559)",
     { tags: "@flaky" },
     () => {
-      toggleDashboardInfoSidebar();
-
-      cy.log("Dashboard creation");
-      cy.findByTestId("dashboard-history-list")
-        .findAllByRole("listitem")
-        .eq(0)
-        .findByText("You created this.")
-        .should("be.visible");
+      openDashboardInfoSidebar();
+      sidesheet().within(() => {
+        cy.findByRole("tab", { name: "History" }).click();
+        cy.log("Dashboard creation");
+        cy.findByTestId("dashboard-history-list")
+          .findAllByRole("listitem")
+          .eq(0)
+          .findByText("You created this.")
+          .should("be.visible");
+      });
+      closeDashboardInfoSidebar();
 
       cy.log("Edit dashboard");
       editDashboard();
       openQuestionsSidebar();
       sidebar().findByText("Orders, Count").click();
       cy.button("Save").click();
-      toggleDashboardInfoSidebar();
-      cy.findByTestId("dashboard-history-list")
-        .findAllByRole("listitem")
-        .eq(0)
-        .findByText("You added a card.")
-        .should("be.visible");
+
+      openDashboardInfoSidebar();
+      sidesheet().within(() => {
+        cy.findByRole("tab", { name: "History" }).click();
+        cy.findByTestId("dashboard-history-list")
+          .findAllByRole("listitem")
+          .eq(0)
+          .findByText("You added a card.")
+          .should("be.visible");
+      });
+      closeDashboardInfoSidebar();
 
       cy.log("Change dashboard name");
       cy.findByTestId("dashboard-name-heading")
         .click()
         .type(" modified")
         .blur();
-      cy.findByTestId("dashboard-history-list")
-        .findAllByRole("listitem")
-        .eq(0)
-        .findByText(
-          'You renamed this Dashboard from "16559 Dashboard" to "16559 Dashboard modified".',
-        )
-        .should("be.visible");
-
-      cy.log("Add description");
-      cy.findByPlaceholderText("Add description")
-        .click()
-        .type("16559 description")
-        .blur();
-      cy.findByTestId("dashboard-history-list")
-        .findAllByRole("listitem")
-        .eq(0)
-        .findByText("You added a description.")
-        .should("be.visible");
-
-      cy.log("Toggle auto-apply filters");
-      rightSidebar().findByText("Auto-apply filters").click();
-      cy.findByTestId("dashboard-history-list")
-        .findAllByRole("listitem")
-        .eq(0)
-        .findByText("You set auto apply filters to false.")
-        .should("be.visible");
+
+      openDashboardInfoSidebar();
+      sidesheet().within(() => {
+        cy.findByRole("tab", { name: "History" }).click();
+
+        cy.findByTestId("dashboard-history-list")
+          .findAllByRole("listitem")
+          .eq(0)
+          .findByText(
+            'You renamed this Dashboard from "16559 Dashboard" to "16559 Dashboard modified".',
+          )
+          .should("be.visible");
+
+        cy.log("Add description");
+        cy.findByRole("tab", { name: "Overview" }).click();
+
+        cy.findByPlaceholderText("Add description")
+          .click()
+          .type("16559 description")
+          .blur();
+
+        cy.findByRole("tab", { name: "History" }).click();
+
+        cy.findByTestId("dashboard-history-list")
+          .findAllByRole("listitem")
+          .eq(0)
+          .findByText("You added a description.")
+          .should("be.visible");
+
+        cy.log("Toggle auto-apply filters");
+
+        cy.findByRole("tab", { name: "Overview" }).click();
+        cy.findByText("Auto-apply filters").click();
+        cy.findByRole("tab", { name: "History" }).click();
+
+        cy.findByTestId("dashboard-history-list")
+          .findAllByRole("listitem")
+          .eq(0)
+          .findByText("You set auto apply filters to false.")
+          .should("be.visible");
+      });
+      closeDashboardInfoSidebar();
 
       cy.log("Move dashboard to another collection");
       dashboardHeader().icon("ellipsis").click();
@@ -389,11 +414,16 @@ describe("issue 16559", () => {
         cy.findByText("First collection").click();
         cy.button("Move").click();
       });
-      cy.findByTestId("dashboard-history-list")
-        .findAllByRole("listitem")
-        .eq(0)
-        .findByText("You moved this Dashboard to First collection.")
-        .should("be.visible");
+
+      openDashboardInfoSidebar();
+      sidesheet().within(() => {
+        cy.findByRole("tab", { name: "History" }).click();
+        cy.findByTestId("dashboard-history-list")
+          .findAllByRole("listitem")
+          .eq(0)
+          .findByText("You moved this Dashboard to First collection.")
+          .should("be.visible");
+      });
     },
   );
 });
diff --git a/e2e/test/scenarios/dashboard/dashboard.cy.spec.js b/e2e/test/scenarios/dashboard/dashboard.cy.spec.js
index 609c83e592417bc22de5dc13d3c2e16dd806d698..6107bfc6e352c3b66e72e7138f7d9250ba9e9421 100644
--- a/e2e/test/scenarios/dashboard/dashboard.cy.spec.js
+++ b/e2e/test/scenarios/dashboard/dashboard.cy.spec.js
@@ -13,6 +13,7 @@ import {
   appBar,
   assertDashboardFixedWidth,
   assertDashboardFullWidth,
+  closeDashboardInfoSidebar,
   closeNavigationSidebar,
   collectionOnTheGoModal,
   commandPalette,
@@ -32,6 +33,7 @@ import {
   getDashboardCards,
   getTextCardDetails,
   modal,
+  openDashboardInfoSidebar,
   openDashboardMenu,
   openProductsTable,
   openQuestionsSidebar,
@@ -41,14 +43,13 @@ import {
   removeDashboardCard,
   resetSnowplow,
   restore,
-  rightSidebar,
   saveDashboard,
   selectDashboardFilter,
   setFilter,
   setTokenFeatures,
   showDashboardCardActions,
   sidebar,
-  toggleDashboardInfoSidebar,
+  sidesheet,
   updateDashboardCards,
   visitDashboard,
 } from "e2e/support/helpers";
@@ -403,7 +404,7 @@ describe("scenarios > dashboard", () => {
       });
     });
 
-    context("title and description", () => {
+    describe("title and description", () => {
       beforeEach(() => {
         cy.intercept("GET", "/api/dashboard/*").as("getDashboard");
         cy.intercept(
@@ -422,9 +423,9 @@ describe("scenarios > dashboard", () => {
         cy.wait("@updateDashboard");
         cy.wait("@getDashboard");
 
-        toggleDashboardInfoSidebar();
+        openDashboardInfoSidebar();
 
-        rightSidebar()
+        sidesheet()
           .findByPlaceholderText("Add description")
           .type(newDescription)
           .blur();
@@ -439,8 +440,9 @@ describe("scenarios > dashboard", () => {
         cy.wait("@getDashboard");
 
         dashboardHeader().findByDisplayValue(newTitle);
-        toggleDashboardInfoSidebar();
-        sidebar().findByText(newDescription);
+        openDashboardInfoSidebar();
+        sidesheet().findByText(newDescription);
+        closeDashboardInfoSidebar();
 
         cy.log("should not call unnecessary API requests (metabase#31721)");
         cy.get("@updateDashboardSpy").should("have.callCount", 2);
@@ -451,8 +453,11 @@ describe("scenarios > dashboard", () => {
         cy.get("@updateDashboardSpy").should("have.callCount", 2);
 
         cy.log("Should revert the description change if escaped");
-        sidebar().findByText(newDescription).type("Baz{esc}");
-        sidebar().findByText(newDescription);
+        openDashboardInfoSidebar();
+        sidesheet().within(() => {
+          cy.findByText(newDescription).type("Baz{esc}");
+          cy.findByText(newDescription);
+        });
         cy.get("@updateDashboardSpy").should("have.callCount", 2);
       });
 
@@ -478,7 +483,7 @@ describe("scenarios > dashboard", () => {
           .findByText(/^Edited a few seconds ago/)
           .click();
 
-        rightSidebar()
+        sidesheet()
           .findByPlaceholderText("Add description")
           .type(newDescription)
           .blur();
@@ -487,6 +492,7 @@ describe("scenarios > dashboard", () => {
         // This might be a bug! We're applying the description while still in the edit mode!
         // OTOH, the title is preserved only on save.
         cy.wait("@updateDashboard");
+        closeDashboardInfoSidebar();
 
         saveDashboard();
         cy.wait("@updateDashboard");
@@ -494,19 +500,19 @@ describe("scenarios > dashboard", () => {
       });
 
       it("should not have markdown content overflow the description area (metabase#31326)", () => {
-        toggleDashboardInfoSidebar();
+        openDashboardInfoSidebar();
 
         const testMarkdownContent =
           "# Heading 1{enter}{enter}**bold** https://www.metabase.com/community_posts/how-to-measure-the-success-of-new-product-features-and-why-it-is-important{enter}{enter}![alt](/app/assets/img/welcome-modal-2.png){enter}{enter}This is my description. ";
 
-        rightSidebar()
+        sidesheet()
           .findByPlaceholderText("Add description")
           .type(testMarkdownContent, { delay: 0 })
           .blur();
 
         cy.wait("@updateDashboard");
 
-        rightSidebar().within(() => {
+        sidesheet().within(() => {
           cy.log("Markdown content should not be bigger than its container");
           cy.findByTestId("editable-text").then($markdown => {
             const el = $markdown[0];
@@ -1266,10 +1272,8 @@ describeEE("scenarios > dashboard > caching", () => {
 
     openSidebarCacheStrategyForm("dashboard");
 
-    rightSidebar().within(() => {
-      cy.findByRole("heading", { name: /Caching settings/ }).should(
-        "be.visible",
-      );
+    sidesheet().within(() => {
+      cy.findByText(/Caching settings/).should("be.visible");
       durationRadioButton().click();
       cy.findByLabelText("Cache results for this many hours").type("48");
       cy.findByRole("button", { name: /Save/ }).click();
@@ -1293,20 +1297,18 @@ describeEE("scenarios > dashboard > caching", () => {
 
     openSidebarCacheStrategyForm("dashboard");
 
-    rightSidebar().within(() => {
-      cy.findByRole("heading", { name: /Caching settings/ }).should(
-        "be.visible",
-      );
+    sidesheet().within(() => {
+      cy.findByText(/Caching settings/).should("be.visible");
       cy.findByRole("button", {
         name: /Clear cache for this dashboard/,
       }).click();
     });
 
-    modal().within(() => {
+    cy.findByTestId("confirm-modal").within(() => {
       cy.findByRole("button", { name: /Clear cache/ }).click();
     });
     cy.wait("@invalidateCache");
-    rightSidebar().within(() => {
+    sidesheet().within(() => {
       cy.findByText("Cache cleared").should("be.visible");
     });
   });
diff --git a/enterprise/frontend/src/metabase-enterprise/caching/components/DashboardStrategySidebar.styled.tsx b/enterprise/frontend/src/metabase-enterprise/caching/components/DashboardStrategySidebar.styled.tsx
deleted file mode 100644
index 59b10af52db504c3befa2569a166ffc069acfa54..0000000000000000000000000000000000000000
--- a/enterprise/frontend/src/metabase-enterprise/caching/components/DashboardStrategySidebar.styled.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import styled from "@emotion/styled";
-
-import {
-  FormBox,
-  StyledFormButtonsGroup,
-} from "metabase/admin/performance/components/StrategyForm.styled";
-import { Group } from "metabase/ui";
-
-export const DashboardStrategySidebarBody = styled(Group)`
-  display: flex;
-  flex-flow: column nowrap;
-  height: 100%;
-  ${StyledFormButtonsGroup} {
-    border-top: 1px solid var(--mb-color-border);
-    position: sticky;
-    bottom: 0;
-  }
-  ${FormBox} {
-    border-bottom: 0 !important;
-  }
-`;
diff --git a/enterprise/frontend/src/metabase-enterprise/caching/components/DashboardStrategySidebar.tsx b/enterprise/frontend/src/metabase-enterprise/caching/components/DashboardStrategySidebar.tsx
deleted file mode 100644
index e4150df74cbed3ac9378fa897bbdf593cac69cb0..0000000000000000000000000000000000000000
--- a/enterprise/frontend/src/metabase-enterprise/caching/components/DashboardStrategySidebar.tsx
+++ /dev/null
@@ -1,126 +0,0 @@
-import { useCallback, useMemo } from "react";
-import type { InjectedRouter, Route } from "react-router";
-import { withRouter } from "react-router";
-import _ from "underscore";
-
-import { StrategyForm } from "metabase/admin/performance/components/StrategyForm";
-import { useCacheConfigs } from "metabase/admin/performance/hooks/useCacheConfigs";
-import { useConfirmIfFormIsDirty } from "metabase/admin/performance/hooks/useConfirmIfFormIsDirty";
-import { useSaveStrategy } from "metabase/admin/performance/hooks/useSaveStrategy";
-import { DelayedLoadingAndErrorWrapper } from "metabase/components/LoadingAndErrorWrapper/DelayedLoadingAndErrorWrapper";
-import type { DashboardSidebarPageProps } from "metabase/dashboard/components/DashboardInfoSidebar";
-import { color } from "metabase/lib/colors";
-import { Button, Flex, Icon, Title } from "metabase/ui";
-import type { CacheStrategy, CacheableModel } from "metabase-types/api";
-
-import { DashboardStrategySidebarBody } from "./DashboardStrategySidebar.styled";
-
-const configurableModels: CacheableModel[] = ["dashboard"];
-
-const DashboardStrategySidebar_Base = ({
-  dashboard,
-  setPage,
-  router,
-  route,
-}: DashboardSidebarPageProps & {
-  router: InjectedRouter;
-  route: Route;
-}) => {
-  if (typeof dashboard.id === "string") {
-    throw new Error("This dashboard has an invalid id");
-  }
-  const dashboardId: number = dashboard.id;
-  const { configs, setConfigs, loading, error } = useCacheConfigs({
-    configurableModels,
-    id: dashboardId,
-  });
-
-  const { savedStrategy, filteredConfigs } = useMemo(() => {
-    const targetConfig = _.findWhere(configs, { model_id: dashboardId });
-    const savedStrategy = targetConfig?.strategy;
-    const filteredConfigs = _.compact([targetConfig]);
-    return { savedStrategy, filteredConfigs };
-  }, [configs, dashboardId]);
-
-  const saveStrategy = useSaveStrategy(
-    dashboardId,
-    filteredConfigs,
-    setConfigs,
-    "dashboard",
-  );
-  const saveAndCloseSidebar = useCallback(
-    async (values: CacheStrategy) => {
-      await saveStrategy(values);
-      setPage("default");
-    },
-    [saveStrategy, setPage],
-  );
-
-  const closeSidebar = useCallback(async () => {
-    setPage("default");
-  }, [setPage]);
-
-  const {
-    askBeforeDiscardingChanges,
-    confirmationModal,
-    isStrategyFormDirty,
-    setIsStrategyFormDirty,
-  } = useConfirmIfFormIsDirty(router, route);
-
-  const goBack = () => setPage("default");
-
-  const headingId = "dashboard-sidebar-caching-settings-heading";
-
-  return (
-    <DashboardStrategySidebarBody
-      align="flex-start"
-      spacing="md"
-      aria-labelledby={headingId}
-    >
-      <Flex align="center">
-        <BackButton
-          onClick={() => {
-            isStrategyFormDirty ? askBeforeDiscardingChanges(goBack) : goBack();
-          }}
-        />
-        <Title order={2} id={headingId}>
-          Caching settings
-        </Title>
-      </Flex>
-      <DelayedLoadingAndErrorWrapper
-        loadingMessages={[]}
-        loading={loading}
-        error={error}
-      >
-        <StrategyForm
-          targetId={dashboardId}
-          targetModel="dashboard"
-          targetName={dashboard.name}
-          isInSidebar
-          setIsDirty={setIsStrategyFormDirty}
-          saveStrategy={saveAndCloseSidebar}
-          savedStrategy={savedStrategy}
-          shouldAllowInvalidation
-          shouldShowName={false}
-          onReset={closeSidebar}
-        />
-      </DelayedLoadingAndErrorWrapper>
-      {confirmationModal}
-    </DashboardStrategySidebarBody>
-  );
-};
-
-export const DashboardStrategySidebar = withRouter(
-  DashboardStrategySidebar_Base,
-);
-
-const BackButton = ({ onClick }: { onClick: () => void }) => (
-  <Button
-    lh={0}
-    style={{ marginInlineStart: "1rem" }}
-    variant="subtle"
-    onClick={onClick}
-  >
-    <Icon name="chevronleft" color={color("text-dark")} />
-  </Button>
-);
diff --git a/enterprise/frontend/src/metabase-enterprise/caching/components/SidebarCacheForm.tsx b/enterprise/frontend/src/metabase-enterprise/caching/components/SidebarCacheForm.tsx
index 36c4d9ae1386f6b0240b191b923c98ab972c2652..dfbaee8aba6870bfd1118c549d0770bdb268f670 100644
--- a/enterprise/frontend/src/metabase-enterprise/caching/components/SidebarCacheForm.tsx
+++ b/enterprise/frontend/src/metabase-enterprise/caching/components/SidebarCacheForm.tsx
@@ -61,7 +61,9 @@ const SidebarCacheForm_Base = ({
       onBack={() =>
         isStrategyFormDirty ? askBeforeDiscardingChanges(onBack) : onBack()
       }
-      onClose={onClose}
+      onClose={() => {
+        isStrategyFormDirty ? askBeforeDiscardingChanges(onClose) : onClose();
+      }}
     >
       <Stack
         align="space-between"
diff --git a/enterprise/frontend/src/metabase-enterprise/caching/index.tsx b/enterprise/frontend/src/metabase-enterprise/caching/index.tsx
index 30de2d38fd1c61f3c1e524cd50c8b4074bbc4cad..e96725b0367b07d9739fd36f40c2778b6c84252b 100644
--- a/enterprise/frontend/src/metabase-enterprise/caching/index.tsx
+++ b/enterprise/frontend/src/metabase-enterprise/caching/index.tsx
@@ -2,7 +2,6 @@ import { PLUGIN_CACHING } from "metabase/plugins";
 import { hasPremiumFeature } from "metabase-enterprise/settings";
 
 import { DashboardAndQuestionCachingTab } from "./components/DashboardAndQuestionCachingTab";
-import { DashboardStrategySidebar } from "./components/DashboardStrategySidebar";
 import { GranularControlsExplanation } from "./components/GranularControlsExplanation";
 import { InvalidateNowButton } from "./components/InvalidateNowButton";
 import { SidebarCacheForm } from "./components/SidebarCacheForm";
@@ -22,7 +21,6 @@ if (hasPremiumFeature("cache_granular_controls")) {
   PLUGIN_CACHING.canOverrideRootStrategy = true;
   PLUGIN_CACHING.GranularControlsExplanation = GranularControlsExplanation;
   PLUGIN_CACHING.InvalidateNowButton = InvalidateNowButton;
-  PLUGIN_CACHING.DashboardStrategySidebar = DashboardStrategySidebar;
   PLUGIN_CACHING.SidebarCacheSection = SidebarCacheSection;
   PLUGIN_CACHING.SidebarCacheForm = SidebarCacheForm;
   PLUGIN_CACHING.strategies = {
diff --git a/frontend/src/metabase/common/components/Sidesheet/Sidesheet.tsx b/frontend/src/metabase/common/components/Sidesheet/Sidesheet.tsx
index 001bc5436dc6bd27ce87f732ae1124e76290463c..cfc43a9483624610fdd7d80d474bfa5ac2f7329d 100644
--- a/frontend/src/metabase/common/components/Sidesheet/Sidesheet.tsx
+++ b/frontend/src/metabase/common/components/Sidesheet/Sidesheet.tsx
@@ -5,19 +5,19 @@ import { Modal, Stack } from "metabase/ui";
 
 import Styles from "./sidesheet.module.css";
 
-type Size = "xs" | "sm" | "md" | "lg" | "xl" | "auto";
+export type SidesheetSize = "xs" | "sm" | "md" | "lg" | "xl" | "auto";
 
 interface SidesheetProps {
   title?: React.ReactNode;
   isOpen: boolean;
   onClose: () => void;
-  size?: Size;
+  size?: SidesheetSize;
   children: React.ReactNode;
   /** use this if you want to enable interior scrolling of tab panels */
   removeBodyPadding?: boolean;
 }
 
-const sizes: Record<Size, string> = {
+const sizes: Record<SidesheetSize, string> = {
   xs: "20rem",
   sm: "30rem",
   md: "40rem",
diff --git a/frontend/src/metabase/common/components/Sidesheet/SidesheetSubPage.tsx b/frontend/src/metabase/common/components/Sidesheet/SidesheetSubPage.tsx
index 9be8a9cadd7ec21c4492a1a7e64c9dcf44633d66..09ea1724dc5c90c50414e1738b48a62ee0d9ccea 100644
--- a/frontend/src/metabase/common/components/Sidesheet/SidesheetSubPage.tsx
+++ b/frontend/src/metabase/common/components/Sidesheet/SidesheetSubPage.tsx
@@ -2,7 +2,7 @@ import type React from "react";
 
 import { Button, Flex, Icon, Title } from "metabase/ui";
 
-import { Sidesheet } from "./Sidesheet";
+import { Sidesheet, type SidesheetSize } from "./Sidesheet";
 
 interface SidesheetSubPageTitleProps {
   title: React.ReactNode;
@@ -15,6 +15,7 @@ interface SidesheetSubPageProps {
   onClose: () => void;
   onBack: () => void;
   children: React.ReactNode;
+  size?: SidesheetSize;
 }
 
 export const SidesheetSubPageTitle = ({
@@ -37,11 +38,13 @@ export const SidesheetSubPage = ({
   onBack,
   children,
   isOpen,
+  size,
 }: SidesheetSubPageProps) => (
   <Sidesheet
     isOpen={isOpen}
     title={<SidesheetSubPageTitle title={title} onClick={onBack} />}
     onClose={onClose}
+    size={size}
   >
     {children}
   </Sidesheet>
diff --git a/frontend/src/metabase/core/components/EditableText/EditableText.tsx b/frontend/src/metabase/core/components/EditableText/EditableText.tsx
index efdea791c6e54f92b08dc715040b393650d3ecb2..6c6860fe2d971a55642e6e5542738590fd75183a 100644
--- a/frontend/src/metabase/core/components/EditableText/EditableText.tsx
+++ b/frontend/src/metabase/core/components/EditableText/EditableText.tsx
@@ -101,6 +101,7 @@ const EditableText = forwardRef(function EditableText(
   const handleKeyDown = useCallback(
     (event: KeyboardEvent<HTMLTextAreaElement>) => {
       if (event.key === "Escape") {
+        event.stopPropagation(); // don't close modal
         setInputValue(submitValue);
         submitOnBlur.current = false;
         event.currentTarget.blur();
diff --git a/frontend/src/metabase/dashboard/components/DashboardHeader/DashboardHeaderView.tsx b/frontend/src/metabase/dashboard/components/DashboardHeader/DashboardHeaderView.tsx
index fb5f9f9c49d55bbd1491b372aea075ecdee0df0f..c16bf2213af9a04108951ed2e2809c86b8bf3bb9 100644
--- a/frontend/src/metabase/dashboard/components/DashboardHeader/DashboardHeaderView.tsx
+++ b/frontend/src/metabase/dashboard/components/DashboardHeader/DashboardHeaderView.tsx
@@ -18,6 +18,7 @@ import {
   getCanResetFilters,
   getIsEditing,
   getIsHeaderVisible,
+  getIsShowDashboardInfoSidebar,
   getIsSidebarOpen,
 } from "metabase/dashboard/selectors";
 import type {
@@ -85,6 +86,8 @@ export function DashboardHeaderView({
 
   const canResetFilters = useSelector(getCanResetFilters);
   const isSidebarOpen = useSelector(getIsSidebarOpen);
+  const isInfoSidebarOpen = useSelector(getIsShowDashboardInfoSidebar);
+
   const isDashboardHeaderVisible = useSelector(getIsHeaderVisible);
   const isAnalyticsDashboard = isInstanceAnalyticsCollection(collection);
 
@@ -163,7 +166,7 @@ export function DashboardHeaderView({
       )}
       <HeaderContainer
         isFixedWidth={dashboard?.width === "fixed"}
-        isSidebarOpen={isSidebarOpen}
+        offsetSidebar={isSidebarOpen && !isInfoSidebarOpen}
       >
         {isDashboardHeaderVisible && (
           <HeaderRow
diff --git a/frontend/src/metabase/dashboard/components/DashboardHeaderView.styled.tsx b/frontend/src/metabase/dashboard/components/DashboardHeaderView.styled.tsx
index dbd7fef4e3545309f95d50aec9e951786be79309..d8b779005c64e243482b67578e66858258d6ce32 100644
--- a/frontend/src/metabase/dashboard/components/DashboardHeaderView.styled.tsx
+++ b/frontend/src/metabase/dashboard/components/DashboardHeaderView.styled.tsx
@@ -40,12 +40,12 @@ export const HeaderFixedWidthContainer = styled(
 `;
 
 export const HeaderContainer = styled.div<{
-  isSidebarOpen: boolean;
+  offsetSidebar: boolean;
   isFixedWidth: boolean;
 }>`
   ${props =>
     props.isFixedWidth &&
-    props.isSidebarOpen &&
+    props.offsetSidebar &&
     css`
       margin-right: ${SIDEBAR_WIDTH}px;
     `}
diff --git a/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.module.css b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.module.css
new file mode 100644
index 0000000000000000000000000000000000000000..70613d52e255e14ce983454bafd680171ffefea6
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.module.css
@@ -0,0 +1,5 @@
+.EditableTextContainer {
+  max-height: 19rem;
+  overflow: auto;
+  line-height: 1.38rem; /* magic number to keep line-height from changing in edit mode */
+}
diff --git a/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.styled.tsx b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.styled.tsx
deleted file mode 100644
index 7401b9159368863d3ff70d106b4ef1ab1cc2b94d..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.styled.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import { css } from "@emotion/react";
-import styled from "@emotion/styled";
-
-import EditableText from "metabase/core/components/EditableText";
-import FormField from "metabase/core/components/FormField/FormField";
-import { breakpointMaxSmall } from "metabase/styled-components/theme";
-
-import { SIDEBAR_WIDTH } from "../Sidebar";
-
-export const DashboardInfoSidebarRoot = styled.aside`
-  width: ${SIDEBAR_WIDTH}px;
-  min-width: ${SIDEBAR_WIDTH}px;
-  background: var(--mb-color-bg-white);
-  border-left: 1px solid var(--mb-color-border);
-  align-self: stretch;
-  box-sizing: border-box;
-  display: flex;
-  flex-direction: column;
-
-  ${breakpointMaxSmall} {
-    position: absolute;
-    right: 0;
-    z-index: 2;
-    height: auto;
-    border-bottom: 1px solid var(--mb-color-border);
-  }
-`;
-
-export const HistoryHeader = styled.h3`
-  margin-bottom: 1rem;
-`;
-
-export const ContentSection = styled.div`
-  padding: 2rem 0;
-  border-bottom: 1px solid var(--mb-color-border);
-
-  &:first-of-type {
-    padding-top: 1.5rem;
-  }
-
-  &:last-of-type {
-    border-bottom: none;
-  }
-
-  ${EditableText.Root} {
-    font-size: 1rem;
-    line-height: 1.4rem;
-    margin-left: -0.3rem;
-
-    h1 {
-      line-height: 1em;
-    }
-  }
-
-  ${FormField.Root}:last-child {
-    margin-bottom: 0;
-  }
-`;
-
-export const DescriptionHeader = styled.h3`
-  margin-bottom: 0.5rem;
-`;
-
-export const EditableDescription = styled(EditableText)<{ hasError?: boolean }>`
-  ${props =>
-    props.hasError &&
-    css`
-      border-color: var(--mb-color-error);
-
-      &:hover {
-        border-color: var(--mb-color-error);
-      }
-    `}
-`;
diff --git a/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.tsx b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.tsx
index 13fa27b33cc47c612053119835cc79fe90bd6775..fec2025b3ccd7d0e604047db0429baf646d3a919 100644
--- a/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.tsx
+++ b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.tsx
@@ -1,11 +1,19 @@
-import type { Dispatch, FocusEvent, SetStateAction } from "react";
+import type { FocusEvent, SetStateAction } from "react";
 import { useCallback, useState } from "react";
+import { useMount } from "react-use";
 import { t } from "ttag";
 
 import ErrorBoundary from "metabase/ErrorBoundary";
+import {
+  Sidesheet,
+  SidesheetCard,
+  SidesheetTabPanelContainer,
+} from "metabase/common/components/Sidesheet";
+import SidesheetS from "metabase/common/components/Sidesheet/sidesheet.module.css";
 import { Timeline } from "metabase/common/components/Timeline";
 import { getTimelineEvents } from "metabase/common/components/Timeline/utils";
 import { useRevisionListQuery } from "metabase/common/hooks";
+import EditableText from "metabase/core/components/EditableText";
 import {
   revertToRevision,
   toggleAutoApplyFilters,
@@ -17,16 +25,15 @@ import { useUniqueId } from "metabase/hooks/use-unique-id";
 import { useDispatch, useSelector } from "metabase/lib/redux";
 import { PLUGIN_CACHING } from "metabase/plugins";
 import { getUser } from "metabase/selectors/user";
-import { Stack, Switch, Text } from "metabase/ui";
-import type { Dashboard } from "metabase-types/api";
+import { Stack, Switch, Tabs, Text } from "metabase/ui";
+import type {
+  CacheableDashboard,
+  Dashboard,
+  Revision,
+  User,
+} from "metabase-types/api";
 
-import {
-  ContentSection,
-  DashboardInfoSidebarRoot,
-  DescriptionHeader,
-  EditableDescription,
-  HistoryHeader,
-} from "./DashboardInfoSidebar.styled";
+import DashboardInfoSidebarS from "./DashboardInfoSidebar.module.css";
 
 interface DashboardInfoSidebarProps {
   dashboard: Dashboard;
@@ -34,49 +41,29 @@ interface DashboardInfoSidebarProps {
     attribute: Key,
     value: Dashboard[Key],
   ) => void;
+  onClose: () => void;
+}
+
+enum Tab {
+  Overview = "overview",
+  History = "history",
 }
 
 export function DashboardInfoSidebar({
   dashboard,
   setDashboardAttribute,
+  onClose,
 }: DashboardInfoSidebarProps) {
+  const [isOpen, setIsOpen] = useState(false);
   const [page, setPage] = useState<"default" | "caching">("default");
 
-  return (
-    <DashboardInfoSidebarRoot
-      style={{ padding: page === "default" ? "0 2rem 0.5rem" : "1rem 0 0 0" }}
-      data-testid="sidebar-right"
-    >
-      <ErrorBoundary>
-        {page === "default" && (
-          <DashboardInfoSidebarBody
-            dashboard={dashboard}
-            setDashboardAttribute={setDashboardAttribute}
-            setPage={setPage}
-          />
-        )}
-        {page === "caching" && (
-          <PLUGIN_CACHING.DashboardStrategySidebar
-            dashboard={dashboard}
-            setPage={setPage}
-          />
-        )}
-      </ErrorBoundary>
-    </DashboardInfoSidebarRoot>
-  );
-}
-
-export type DashboardSidebarPageProps = {
-  dashboard: Dashboard;
-  setPage: Dispatch<SetStateAction<"default" | "caching">>;
-  setDashboardAttribute: DashboardInfoSidebarProps["setDashboardAttribute"];
-};
+  useMount(() => {
+    // this component is not rendered until it is "open"
+    // but we want to set isOpen after it mounts to get
+    // pretty animations
+    setIsOpen(true);
+  });
 
-const DashboardInfoSidebarBody = ({
-  dashboard,
-  setDashboardAttribute,
-  setPage,
-}: DashboardSidebarPageProps) => {
   const [descriptionError, setDescriptionError] = useState<string | null>(null);
 
   const { data: revisions } = useRevisionListQuery({
@@ -107,6 +94,91 @@ const DashboardInfoSidebarBody = ({
     [],
   );
 
+  const canWrite = dashboard.can_write && !dashboard.archived;
+  const showCaching = canWrite && PLUGIN_CACHING.isGranularCachingEnabled();
+
+  if (page === "caching") {
+    return (
+      <PLUGIN_CACHING.SidebarCacheForm
+        item={dashboard as CacheableDashboard}
+        model="dashboard"
+        onBack={() => setPage("default")}
+        onClose={onClose}
+        pt="md"
+      />
+    );
+  }
+
+  return (
+    <div data-testid="sidebar-right">
+      <ErrorBoundary>
+        <Sidesheet
+          isOpen={isOpen}
+          title={t`Info`}
+          onClose={onClose}
+          removeBodyPadding
+          size="md"
+        >
+          <Tabs
+            defaultValue={Tab.Overview}
+            className={SidesheetS.FlexScrollContainer}
+          >
+            <Tabs.List mx="lg">
+              <Tabs.Tab value={Tab.Overview}>{t`Overview`}</Tabs.Tab>
+              <Tabs.Tab value={Tab.History}>{t`History`}</Tabs.Tab>
+            </Tabs.List>
+            <SidesheetTabPanelContainer>
+              <Tabs.Panel value={Tab.Overview}>
+                <OverviewTab
+                  dashboard={dashboard}
+                  handleDescriptionChange={handleDescriptionChange}
+                  handleDescriptionBlur={handleDescriptionBlur}
+                  descriptionError={descriptionError}
+                  setDescriptionError={setDescriptionError}
+                  canWrite={canWrite}
+                  setPage={setPage}
+                  showCaching={showCaching}
+                />
+              </Tabs.Panel>
+              <Tabs.Panel value={Tab.History}>
+                <HistoryTab
+                  canWrite={canWrite}
+                  revisions={revisions}
+                  currentUser={currentUser}
+                />
+              </Tabs.Panel>
+            </SidesheetTabPanelContainer>
+          </Tabs>
+        </Sidesheet>
+      </ErrorBoundary>
+    </div>
+  );
+}
+
+const OverviewTab = ({
+  dashboard,
+  handleDescriptionChange,
+  handleDescriptionBlur,
+  descriptionError,
+  setDescriptionError,
+  canWrite,
+  setPage,
+  showCaching,
+}: {
+  dashboard: Dashboard;
+  handleDescriptionChange: (description: string) => void;
+  handleDescriptionBlur: (event: FocusEvent<HTMLTextAreaElement>) => void;
+  descriptionError: string | null;
+  setDescriptionError: (error: string | null) => void;
+  canWrite: boolean;
+  setPage: (
+    page: "default" | "caching" | SetStateAction<"default" | "caching">,
+  ) => void;
+  showCaching: boolean;
+}) => {
+  const isCacheable = isDashboardCacheable(dashboard);
+  const autoApplyFilterToggleId = useUniqueId();
+  const dispatch = useDispatch();
   const handleToggleAutoApplyFilters = useCallback(
     (isAutoApplyingFilters: boolean) => {
       dispatch(toggleAutoApplyFilters(isAutoApplyingFilters));
@@ -114,70 +186,75 @@ const DashboardInfoSidebarBody = ({
     [dispatch],
   );
 
-  const autoApplyFilterToggleId = useUniqueId();
-  const canWrite = dashboard.can_write && !dashboard.archived;
-  const isCacheable = isDashboardCacheable(dashboard);
-
-  const showCaching = canWrite && PLUGIN_CACHING.isGranularCachingEnabled();
-
   return (
-    <>
-      <ContentSection>
-        <DescriptionHeader>{t`About`}</DescriptionHeader>
-        <EditableDescription
-          initialValue={dashboard.description}
-          isDisabled={!canWrite}
-          onChange={handleDescriptionChange}
-          onFocus={() => setDescriptionError("")}
-          onBlur={handleDescriptionBlur}
-          isOptional
-          isMultiline
-          isMarkdown
-          hasError={!!descriptionError}
-          placeholder={t`Add description`}
-          key={`dashboard-description-${dashboard.description}`}
-          style={{ fontSize: ".875rem" }}
-        />
+    <Stack spacing="lg">
+      <SidesheetCard title={t`Description`} pb="md">
+        <div className={DashboardInfoSidebarS.EditableTextContainer}>
+          <EditableText
+            initialValue={dashboard.description}
+            isDisabled={!canWrite}
+            onChange={handleDescriptionChange}
+            onFocus={() => setDescriptionError("")}
+            onBlur={handleDescriptionBlur}
+            isOptional
+            isMultiline
+            isMarkdown
+            placeholder={t`Add description`}
+          />
+        </div>
         {!!descriptionError && (
           <Text color="error" size="xs" mt="xs">
             {descriptionError}
           </Text>
         )}
-      </ContentSection>
+      </SidesheetCard>
 
       {!dashboard.archived && (
-        <ContentSection>
-          <Stack spacing="md">
-            <Switch
-              disabled={!canWrite}
-              label={t`Auto-apply filters`}
-              labelPosition="left"
-              variant="stretch"
-              size="sm"
-              id={autoApplyFilterToggleId}
-              checked={dashboard.auto_apply_filters}
-              onChange={e => handleToggleAutoApplyFilters(e.target.checked)}
-            />
-            {showCaching && isCacheable && (
-              <PLUGIN_CACHING.SidebarCacheSection
-                model="dashboard"
-                item={dashboard}
-                setPage={setPage}
-              />
-            )}
-          </Stack>
-        </ContentSection>
+        <SidesheetCard>
+          <Switch
+            disabled={!canWrite}
+            label={t`Auto-apply filters`}
+            labelPosition="left"
+            variant="stretch"
+            size="sm"
+            id={autoApplyFilterToggleId}
+            checked={dashboard.auto_apply_filters}
+            onChange={e => handleToggleAutoApplyFilters(e.target.checked)}
+          />
+        </SidesheetCard>
       )}
 
-      <ContentSection>
-        <HistoryHeader>{t`History`}</HistoryHeader>
-        <Timeline
-          events={getTimelineEvents({ revisions, currentUser })}
-          data-testid="dashboard-history-list"
-          revert={revision => dispatch(revertToRevision(revision))}
-          canWrite={canWrite}
-        />
-      </ContentSection>
-    </>
+      {showCaching && isCacheable && (
+        <SidesheetCard title={t`Caching`} pb="md">
+          <PLUGIN_CACHING.SidebarCacheSection
+            model="dashboard"
+            item={dashboard}
+            setPage={setPage}
+          />
+        </SidesheetCard>
+      )}
+    </Stack>
+  );
+};
+
+const HistoryTab = ({
+  canWrite,
+  revisions,
+  currentUser,
+}: {
+  canWrite: boolean;
+  revisions?: Revision[];
+  currentUser: User | null;
+}) => {
+  const dispatch = useDispatch();
+  return (
+    <SidesheetCard>
+      <Timeline
+        events={getTimelineEvents({ revisions, currentUser })}
+        data-testid="dashboard-history-list"
+        revert={revision => dispatch(revertToRevision(revision))}
+        canWrite={canWrite}
+      />
+    </SidesheetCard>
   );
 };
diff --git a/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.unit.spec.tsx b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/tests/common.unit.spec.ts
similarity index 52%
rename from frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.unit.spec.tsx
rename to frontend/src/metabase/dashboard/components/DashboardInfoSidebar/tests/common.unit.spec.ts
index 816a2574b2258ff57c5770fa50fe79740255578a..bd7e54d6fa46539bfcfd405c1d75fb906ac53695 100644
--- a/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/DashboardInfoSidebar.unit.spec.tsx
+++ b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/tests/common.unit.spec.ts
@@ -1,32 +1,9 @@
 import userEvent from "@testing-library/user-event";
 
-import { setupRevisionsEndpoints } from "__support__/server-mocks/revision";
-import { renderWithProviders, screen } from "__support__/ui";
-import type { Dashboard } from "metabase-types/api";
+import { screen } from "__support__/ui";
 import { createMockDashboard } from "metabase-types/api/mocks";
 
-import { DashboardInfoSidebar } from "./DashboardInfoSidebar";
-
-interface SetupOpts {
-  dashboard?: Dashboard;
-}
-
-function setup({ dashboard = createMockDashboard() }: SetupOpts = {}) {
-  const setDashboardAttribute = jest.fn();
-
-  setupRevisionsEndpoints([]);
-
-  renderWithProviders(
-    <DashboardInfoSidebar
-      dashboard={dashboard}
-      setDashboardAttribute={setDashboardAttribute}
-    />,
-  );
-
-  return {
-    setDashboardAttribute,
-  };
-}
+import { setup } from "./setup";
 
 jest.mock("metabase/dashboard/constants", () => ({
   ...jest.requireActual("metabase/dashboard/constants"),
@@ -37,11 +14,44 @@ describe("DashboardInfoSidebar", () => {
   it("should render the component", () => {
     setup();
 
-    expect(screen.getByText("About")).toBeInTheDocument();
+    expect(screen.getByText("Info")).toBeInTheDocument();
+    expect(screen.getByTestId("sidesheet")).toBeInTheDocument();
+  });
+
+  it("should render overview tab", () => {
+    setup();
+    expect(screen.getByRole("tab", { name: "Overview" })).toBeInTheDocument();
+  });
+
+  it("should render history tab", () => {
+    setup();
+    expect(screen.getByRole("tab", { name: "History" })).toBeInTheDocument();
+  });
+
+  it("should show description when clicking on overview tab", async () => {
+    await setup();
+    await userEvent.click(screen.getByRole("tab", { name: "History" }));
+    await userEvent.click(screen.getByRole("tab", { name: "Overview" }));
+
+    expect(screen.getByText("Description")).toBeInTheDocument();
+  });
+
+  it("should show history when clicking on history tab", async () => {
+    await setup();
+    await userEvent.click(screen.getByRole("tab", { name: "History" }));
+
+    expect(screen.getByTestId("dashboard-history-list")).toBeInTheDocument();
+  });
+
+  it("should close when clicking the close button", async () => {
+    const { onClose } = await setup();
+    await userEvent.click(screen.getByRole("button", { name: "Close" }));
+
+    expect(onClose).toHaveBeenCalledTimes(1);
   });
 
   it("should allow to set description", async () => {
-    const { setDashboardAttribute } = setup();
+    const { setDashboardAttribute } = await setup();
 
     await userEvent.click(screen.getByTestId("editable-text"));
     await userEvent.type(
@@ -58,7 +68,7 @@ describe("DashboardInfoSidebar", () => {
 
   it("should validate description length", async () => {
     const expectedErrorMessage = "Must be 20 characters or less";
-    const { setDashboardAttribute } = setup();
+    const { setDashboardAttribute } = await setup();
 
     await userEvent.click(screen.getByTestId("editable-text"));
     await userEvent.type(
@@ -79,7 +89,7 @@ describe("DashboardInfoSidebar", () => {
   });
 
   it("should allow to clear description", async () => {
-    const { setDashboardAttribute } = setup({
+    const { setDashboardAttribute } = await setup({
       dashboard: createMockDashboard({ description: "some description" }),
     });
 
@@ -89,4 +99,14 @@ describe("DashboardInfoSidebar", () => {
 
     expect(setDashboardAttribute).toHaveBeenCalledWith("description", "");
   });
+
+  it("should show dashboard auto-apply filter toggle", async () => {
+    await setup();
+    expect(screen.getByText("Auto-apply filters")).toBeInTheDocument();
+  });
+
+  it("should not render caching section in OSS", async () => {
+    await setup();
+    expect(screen.queryByText("Caching")).not.toBeInTheDocument();
+  });
 });
diff --git a/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/tests/enterprise.unit.spec.ts b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/tests/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8f9d5650225176d5afa3c1ccfc5d88317a0b877a
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/tests/enterprise.unit.spec.ts
@@ -0,0 +1,18 @@
+import { screen } from "__support__/ui";
+
+import { setupEnterprise } from "./setup";
+
+describe("DashboardInfoSidebar > enterprise", () => {
+  it("should render the component", async () => {
+    await setupEnterprise();
+
+    expect(screen.getByText("Info")).toBeInTheDocument();
+    expect(screen.getByTestId("sidesheet")).toBeInTheDocument();
+  });
+
+  it("should not render caching section without caching feature", async () => {
+    await setupEnterprise({}, { cache_granular_controls: false });
+
+    expect(screen.queryByText("Caching")).not.toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/tests/premium.unit.spec.ts b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/tests/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..959b17e035e4420969d17b11d4c98e58ae15f4ed
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/tests/premium.unit.spec.ts
@@ -0,0 +1,33 @@
+import userEvent from "@testing-library/user-event";
+
+import { screen } from "__support__/ui";
+
+import { setupEnterprise } from "./setup";
+
+const tokenFeatures = {
+  cache_granular_controls: true,
+};
+
+describe("DashboardInfoSidebar > premium enterprise", () => {
+  it("should render the component", async () => {
+    await setupEnterprise({}, tokenFeatures);
+
+    expect(screen.getByText("Info")).toBeInTheDocument();
+    expect(screen.getByTestId("sidesheet")).toBeInTheDocument();
+  });
+
+  it("should render caching section with caching feature", async () => {
+    await setupEnterprise({}, tokenFeatures);
+
+    expect(await screen.findByText("Caching")).toBeInTheDocument();
+    expect(await screen.findByText("Caching policy")).toBeInTheDocument();
+  });
+
+  it("should show cache form when clicking on caching section", async () => {
+    await setupEnterprise({}, tokenFeatures);
+
+    await userEvent.click(await screen.findByText("Use default"));
+
+    expect(await screen.findByText("Caching settings")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/tests/setup.tsx b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..16a79a2d323df1fb6d12213f8716249134ab6a40
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/DashboardInfoSidebar/tests/setup.tsx
@@ -0,0 +1,91 @@
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import {
+  setupDashboardEndpoints,
+  setupPerformanceEndpoints,
+  setupRevisionsEndpoints,
+  setupUsersEndpoints,
+} from "__support__/server-mocks";
+import { mockSettings } from "__support__/settings";
+import { createMockEntitiesState } from "__support__/store";
+import { renderWithProviders, waitForLoaderToBeRemoved } from "__support__/ui";
+import type { Dashboard, Settings, TokenFeatures } from "metabase-types/api";
+import {
+  createMockDashboard,
+  createMockSettings,
+  createMockTokenFeatures,
+  createMockUser,
+} from "metabase-types/api/mocks";
+import { createSampleDatabase } from "metabase-types/api/mocks/presets";
+import { createMockState } from "metabase-types/store/mocks";
+
+import { DashboardInfoSidebar } from "../DashboardInfoSidebar";
+
+export interface SetupOpts {
+  dashboard?: Dashboard;
+  settings?: Settings;
+  hasEnterprisePlugins?: boolean;
+}
+
+export async function setup({
+  dashboard = createMockDashboard(),
+  settings = createMockSettings(),
+  hasEnterprisePlugins,
+}: SetupOpts = {}) {
+  const setDashboardAttribute = jest.fn();
+  const onClose = jest.fn();
+
+  const currentUser = createMockUser();
+  setupDashboardEndpoints(dashboard);
+  setupUsersEndpoints([currentUser]);
+  setupRevisionsEndpoints([]);
+  setupPerformanceEndpoints([]);
+
+  const state = createMockState({
+    currentUser,
+    settings: mockSettings({
+      ...settings,
+      "token-features": createMockTokenFeatures(
+        settings["token-features"] || {},
+      ),
+    }),
+    entities: createMockEntitiesState({
+      databases: [createSampleDatabase()],
+      dashboards: [dashboard],
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(
+    <DashboardInfoSidebar
+      dashboard={dashboard}
+      setDashboardAttribute={setDashboardAttribute}
+      onClose={onClose}
+    />,
+    { storeInitialState: state },
+  );
+  await waitForLoaderToBeRemoved();
+
+  return {
+    setDashboardAttribute,
+    onClose,
+  };
+}
+
+export const setupEnterprise = (
+  opts: SetupOpts = {},
+  tokenFeatures: Partial<TokenFeatures> = {},
+) => {
+  return setup({
+    ...opts,
+    settings: createMockSettings({
+      ...opts.settings,
+      "token-features": createMockTokenFeatures({
+        ...tokenFeatures,
+      }),
+    }),
+    hasEnterprisePlugins: true,
+  });
+};
diff --git a/frontend/src/metabase/dashboard/components/DashboardSidebars.tsx b/frontend/src/metabase/dashboard/components/DashboardSidebars.tsx
index 13573c618d528718298a40586592572537da18da..7b114927c512905025d52699a933ad01fde7dd63 100644
--- a/frontend/src/metabase/dashboard/components/DashboardSidebars.tsx
+++ b/frontend/src/metabase/dashboard/components/DashboardSidebars.tsx
@@ -214,6 +214,7 @@ export function DashboardSidebars({
         <DashboardInfoSidebar
           dashboard={dashboard}
           setDashboardAttribute={setDashboardAttribute}
+          onClose={closeSidebar}
         />
       );
     default:
diff --git a/frontend/src/metabase/plugins/index.ts b/frontend/src/metabase/plugins/index.ts
index 10e0d15ea16a8feecb88867eb9359f17e0003fd2..5fedbd87c5194b3ec719798c7e71c0de4b14fec1 100644
--- a/frontend/src/metabase/plugins/index.ts
+++ b/frontend/src/metabase/plugins/index.ts
@@ -405,7 +405,6 @@ export const PLUGIN_CACHING = {
   isGranularCachingEnabled: () => false,
   StrategyFormLauncherPanel: PluginPlaceholder as any,
   GranularControlsExplanation: PluginPlaceholder as any,
-  DashboardStrategySidebar: PluginPlaceholder as any,
   SidebarCacheSection:
     PluginPlaceholder as ComponentType<SidebarCacheSectionProps>,
   SidebarCacheForm: PluginPlaceholder as ComponentType<
diff --git a/frontend/test/__support__/server-mocks/index.ts b/frontend/test/__support__/server-mocks/index.ts
index effd00dea93f5742f859b26afb4c775245060f61..8e3c67d55037006dd5e148565bb8d31ca00c15bc 100644
--- a/frontend/test/__support__/server-mocks/index.ts
+++ b/frontend/test/__support__/server-mocks/index.ts
@@ -18,6 +18,7 @@ export * from "./metabot";
 export * from "./model-indexes";
 export * from "./native-query-snippet";
 export * from "./revision";
+export * from "./performance";
 export * from "./permissions";
 export * from "./public";
 export * from "./pulse";