diff --git a/frontend/src/metabase-types/api/dashboard.ts b/frontend/src/metabase-types/api/dashboard.ts
index d24ad00101d80f72900d7aa9624a3b2d820f3320..dadf526e04e7a5f0b934e644602b1b3523d85b59 100644
--- a/frontend/src/metabase-types/api/dashboard.ts
+++ b/frontend/src/metabase-types/api/dashboard.ts
@@ -4,7 +4,9 @@ import type {
   ParameterId,
   Parameter,
 } from "metabase-types/types/Parameter";
+
 import type { CardId, SavedCard } from "metabase-types/types/Card";
+import type { WritebackAction } from "./writeback";
 
 import type { Dataset } from "./dataset";
 
@@ -41,6 +43,7 @@ export type DashboardOrderedCard = BaseDashboardOrderedCard & {
   card: SavedCard;
   parameter_mappings?: DashboardParameterMapping[] | null;
   series?: SavedCard[];
+  action?: WritebackAction;
 };
 
 export type DashboardParameterMapping = {
diff --git a/frontend/src/metabase-types/api/data-app.ts b/frontend/src/metabase-types/api/data-app.ts
index 24e816ff1aadf35fd547a4c7a388af773f3d8e01..1ecd4ed434bf419984ddd6719111414afb64f86a 100644
--- a/frontend/src/metabase-types/api/data-app.ts
+++ b/frontend/src/metabase-types/api/data-app.ts
@@ -6,7 +6,8 @@ import {
   DashboardParameterMapping,
 } from "./dashboard";
 import { WritebackAction } from "./writeback";
-import { FormType } from "./writeback-form-settings";
+import { ActionDisplayType } from "./writeback-form-settings";
+import { Card } from "./card";
 
 export type DataAppId = number;
 export type DataAppPage = Dashboard;
@@ -45,7 +46,6 @@ export type ActionParametersMapping = Pick<
 
 export interface ActionDashboardCard
   extends Omit<BaseDashboardOrderedCard, "parameter_mappings"> {
-  action_id: number | null;
   action?: WritebackAction;
   card_id?: number; // model card id for the associated action
 
@@ -54,6 +54,6 @@ export interface ActionDashboardCard
     [key: string]: unknown;
     "button.label"?: string;
     click_behavior?: ClickBehavior;
-    actionDisplayType?: FormType;
+    actionDisplayType?: ActionDisplayType;
   };
 }
diff --git a/frontend/src/metabase-types/api/mocks/data-app.ts b/frontend/src/metabase-types/api/mocks/data-app.ts
index 526a6441b1c99866dbd7db361934c64b1302fda8..e6c990334a0fe304a4d1be275b56fd252bdebeb5 100644
--- a/frontend/src/metabase-types/api/mocks/data-app.ts
+++ b/frontend/src/metabase-types/api/mocks/data-app.ts
@@ -30,7 +30,6 @@ export const createMockDashboardActionButton = ({
   ...opts
 }: Partial<ActionDashboardCard> = {}): ActionDashboardCard => ({
   id: 1,
-  action_id: null,
   parameter_mappings: null,
   visualization_settings: merge(
     {
diff --git a/frontend/src/metabase-types/api/mocks/writeback.ts b/frontend/src/metabase-types/api/mocks/writeback.ts
index 3e259832b65190a133bb725d6f0173d0b7d8e448..2465062c35f9bdc53250a54d699febb01f4c6df0 100644
--- a/frontend/src/metabase-types/api/mocks/writeback.ts
+++ b/frontend/src/metabase-types/api/mocks/writeback.ts
@@ -2,6 +2,7 @@ import {
   Card,
   QueryAction,
   WritebackAction,
+  WritebackQueryAction,
   QueryActionCard,
 } from "metabase-types/api";
 import { createMockCard } from "./card";
@@ -25,7 +26,7 @@ export const createMockQueryAction = ({
   ...opts
 }: Partial<WritebackAction & QueryAction> = {}): WritebackAction => {
   return {
-    id: 1,
+    action_id: 1,
     type: "query",
     card_id: card.id,
     card,
@@ -37,3 +38,30 @@ export const createMockQueryAction = ({
     ...opts,
   };
 };
+
+export const createMockImplictQueryAction = (
+  options: Partial<WritebackQueryAction>,
+): WritebackQueryAction => ({
+  card_id: 1,
+  name: "",
+  description: "",
+  "updated-at": new Date().toISOString(),
+  "created-at": new Date().toISOString(),
+  slug: "",
+  parameters: [
+    {
+      id: "id",
+      target: ["variable", ["template-tag", "id"]],
+      type: "type/Integer",
+    },
+    {
+      id: "name",
+      target: ["variable", ["template-tag", "name"]],
+      type: "type/Text",
+    },
+  ] as WritebackAction["parameters"],
+  type: "implicit",
+  visualization_settings: undefined,
+  card: createMockQueryActionCard(),
+  ...options,
+});
diff --git a/frontend/src/metabase-types/api/writeback-form-settings.ts b/frontend/src/metabase-types/api/writeback-form-settings.ts
index e8bd542a017047b6e50d67c169b8b6a43cc7c053..4651d498d29b6e5812273f9087a3d0eb334675b1 100644
--- a/frontend/src/metabase-types/api/writeback-form-settings.ts
+++ b/frontend/src/metabase-types/api/writeback-form-settings.ts
@@ -1,6 +1,6 @@
 import type { ParameterId } from "./parameters";
 
-export type FormType = "inline" | "modal";
+export type ActionDisplayType = "form" | "button";
 export type FieldType = "string" | "number" | "date" | "category";
 
 export type DateInputType = "date" | "datetime" | "monthyear" | "quarteryear";
@@ -38,7 +38,7 @@ export interface FieldSettings {
 export type FieldSettingsMap = Record<ParameterId, FieldSettings>;
 export interface ActionFormSettings {
   name?: string;
-  type: FormType;
+  type: ActionDisplayType;
   description?: string;
   fields: FieldSettingsMap;
   submitButtonLabel?: string;
diff --git a/frontend/src/metabase-types/api/writeback.ts b/frontend/src/metabase-types/api/writeback.ts
index cda2f510edaf8150db42d1266970fad8f92b1d98..30c6bc144009cd61ee2f3c63e56b4e21a12897cd 100644
--- a/frontend/src/metabase-types/api/writeback.ts
+++ b/frontend/src/metabase-types/api/writeback.ts
@@ -8,7 +8,8 @@ export interface WritebackParameter extends Parameter {
 export type WritebackActionType = "http" | "query" | "implicit";
 
 export interface WritebackActionBase {
-  id: number;
+  id?: number;
+  action_id?: number;
   model_id?: number;
   slug?: string;
   name: string;
diff --git a/frontend/src/metabase/components/EmptyState.jsx b/frontend/src/metabase/components/EmptyState.jsx
index a97d558482b3dcb8aa741b4ea929ba483e4852bf..95a7c23949dab12fb71040d5d08cf73ee8aa967a 100644
--- a/frontend/src/metabase/components/EmptyState.jsx
+++ b/frontend/src/metabase/components/EmptyState.jsx
@@ -48,9 +48,10 @@ const EmptyState = ({
   link,
   illustrationElement,
   onActionClick,
+  className,
   ...rest
 }) => (
-  <div>
+  <div className={className}>
     <EmptyStateHeader>
       {illustrationElement && (
         <EmptyStateIllustration>{illustrationElement}</EmptyStateIllustration>
diff --git a/frontend/src/metabase/containers/ActionPicker/ActionPicker.styled.tsx b/frontend/src/metabase/containers/ActionPicker/ActionPicker.styled.tsx
index 5cf4ba6d3e4e031223f7aaab65bd5b6778fc57c5..24ab073f0845ed181a489d55649d29fcee219d0a 100644
--- a/frontend/src/metabase/containers/ActionPicker/ActionPicker.styled.tsx
+++ b/frontend/src/metabase/containers/ActionPicker/ActionPicker.styled.tsx
@@ -1,34 +1,42 @@
 import _ from "underscore";
 import styled from "@emotion/styled";
 
-import { color } from "metabase/lib/colors";
+import { color, lighten } from "metabase/lib/colors";
+import { space } from "metabase/styled-components/theme";
 
-import { SidebarItem } from "metabase/dashboard/components/ClickBehaviorSidebar/SidebarItem";
+import UnstyledEmptyState from "metabase/components/EmptyState";
 
-export const ActionSidebarItem = styled(SidebarItem.Selectable)<{
-  hasDescription?: boolean;
-}>`
-  align-items: ${props => (props.hasDescription ? "flex-start" : "center")};
-  margin-top: 2px;
+export const ModelActionList = styled.div`
+  margin-bottom: ${space(2)};
+  &:not(:last-child) {
+    border-bottom: 1px solid ${color("border")};
+  }
 `;
 
-export const ActionSidebarItemIcon = styled(SidebarItem.Icon)<{
-  isSelected?: boolean;
-}>`
-  .Icon {
-    color: ${props =>
-      props.isSelected ? color("text-white") : color("brand")};
-  }
+export const ModelTitle = styled.h4`
+  color: ${color("text-dark")};
+  margin-bottom: ${space(2)};
+  display: flex;
+  align-items: center;
 `;
 
-export const ActionDescription = styled.span<{ isSelected?: boolean }>`
-  width: 95%;
-  margin-top: 2px;
+export const ActionItem = styled.li`
+  padding-left: ${space(3)};
+  margin-bottom: ${space(2)};
+  color: ${color("brand")};
+  cursor: pointer;
+  font-weight: bold;
+  &:hover: {
+    color: ${lighten("brand", 0.1)};
+  }
+`;
 
-  color: ${props =>
-    props.isSelected ? color("text-white") : color("text-medium")};
+export const EmptyState = styled(UnstyledEmptyState)`
+  margin-bottom: ${space(2)};
 `;
 
-export const ClickMappingsContainer = styled.div`
-  margin-top: 1rem;
+export const EmptyModelStateContainer = styled.div`
+  padding-bottom: ${space(2)};
+  color: ${color("text-medium")};
+  text-align: center;
 `;
diff --git a/frontend/src/metabase/containers/ActionPicker/ActionPicker.tsx b/frontend/src/metabase/containers/ActionPicker/ActionPicker.tsx
index a7c28796f4c277b60806d3acd929ac0eff787880..78f7702b0e1153be1fdf24b240ece90439b9acc6 100644
--- a/frontend/src/metabase/containers/ActionPicker/ActionPicker.tsx
+++ b/frontend/src/metabase/containers/ActionPicker/ActionPicker.tsx
@@ -1,86 +1,99 @@
-import React, { useState } from "react";
+import React from "react";
 import { t } from "ttag";
+import _ from "underscore";
 
-import Button from "metabase/core/components/Button";
-import EmptyState from "metabase/components/EmptyState";
+import Icon from "metabase/components/Icon";
 
 import Actions from "metabase/entities/actions";
-import type { WritebackAction } from "metabase-types/api";
+import Questions from "metabase/entities/questions";
+
+import type { Card, WritebackAction } from "metabase-types/api";
 import type { State } from "metabase-types/store";
 
-import ModelPicker from "../ModelPicker";
-import ActionOptionItem from "./ActionOptionItem";
+import Link from "metabase/core/components/Link";
+import Button from "metabase/core/components/Button";
+import {
+  ModelTitle,
+  ActionItem,
+  ModelActionList,
+  EmptyState,
+  EmptyModelStateContainer,
+} from "./ActionPicker.styled";
 
 export default function ActionPicker({
-  value,
-  onChange,
+  modelIds,
+  onClick,
 }: {
-  value: WritebackAction | undefined;
-  onChange: (value: WritebackAction) => void;
+  modelIds: number[];
+  onClick: (action: WritebackAction) => void;
 }) {
-  const [modelId, setModelId] = useState<number | undefined>(value?.model_id);
-
   return (
     <div className="scroll-y">
-      {!modelId ? (
-        <ModelPicker value={modelId} onChange={setModelId} />
-      ) : (
-        <>
-          <Button
-            icon="arrow_left"
-            borderless
-            onClick={() => setModelId(undefined)}
-          >
-            {t`Select Model`}
-          </Button>
-
-          <ConnectedModelActionPicker
-            modelId={modelId}
-            value={value}
-            onChange={onChange}
-          />
-        </>
+      {modelIds.map(modelId => (
+        <ConnectedModelActionPicker
+          key={modelId}
+          modelId={modelId}
+          onClick={onClick}
+        />
+      ))}
+      {!modelIds.length && (
+        <EmptyState
+          message={t`No models found`}
+          action={t`Create new model`}
+          link={"/model/new"}
+        />
       )}
     </div>
   );
 }
 
 function ModelActionPicker({
-  value,
-  onChange,
+  onClick,
+  model,
   actions,
 }: {
-  value: WritebackAction | undefined;
-  onChange: (newValue: WritebackAction) => void;
+  onClick: (newValue: WritebackAction) => void;
+  model: Card;
   actions: WritebackAction[];
 }) {
-  if (!actions?.length) {
-    return (
-      <EmptyState
-        message={t`There are no actions for this model`}
-        action={t`Create new action`}
-        link={"/action/create"}
-      />
-    );
-  }
-
   return (
-    <ul>
-      {actions?.map(action => (
-        <ActionOptionItem
-          name={action.name}
-          description={action.description}
-          isSelected={action.id === value?.id}
-          key={action.slug}
-          onClick={() => onChange(action)}
-        />
-      ))}
-    </ul>
+    <ModelActionList>
+      <ModelTitle>
+        <Icon name="model" size={16} className="mr2" />
+        {model.name}
+      </ModelTitle>
+      {actions?.length ? (
+        <ul>
+          {actions?.map(action => (
+            <ActionItem onClick={() => onClick(action)} key={action.id}>
+              {action.name}
+            </ActionItem>
+          ))}
+        </ul>
+      ) : (
+        <EmptyModelStateContainer>
+          <div>{t`There are no actions for this model`}</div>
+          <Button
+            as={Link}
+            to={`/action/create?model-id=${model.id}`}
+            borderless
+          >
+            {t`Create new action`}
+          </Button>
+        </EmptyModelStateContainer>
+      )}
+    </ModelActionList>
   );
 }
 
-const ConnectedModelActionPicker = Actions.loadList({
-  query: (state: State, props: { modelId?: number | null }) => ({
-    "model-id": props?.modelId,
+const ConnectedModelActionPicker = _.compose(
+  Questions.load({
+    id: (state: State, props: { modelId?: number | null }) => props?.modelId,
+    entityAlias: "model",
+  }),
+  Actions.loadList({
+    query: (state: State, props: { modelId?: number | null }) => ({
+      "model-id": props?.modelId,
+    }),
   }),
-})(ModelActionPicker);
+)(ModelActionPicker);
diff --git a/frontend/src/metabase/dashboard/actions/cards.js b/frontend/src/metabase/dashboard/actions/cards.js
index de2f843e45cb7d58d31f3b90008c25128b327536..cae93fa5644e8860bf2f8deeb8e165581042849b 100644
--- a/frontend/src/metabase/dashboard/actions/cards.js
+++ b/frontend/src/metabase/dashboard/actions/cards.js
@@ -1,4 +1,5 @@
 import _ from "underscore";
+import { t } from "ttag";
 
 import { createAction } from "metabase/lib/redux";
 
@@ -85,22 +86,74 @@ export const addTextDashCardToDashboard = function ({ dashId }) {
   });
 };
 
-export const addActionDashCardToDashboard = ({ dashId }) => {
-  const virtualActionsCard = {
-    ...createCard(),
-    display: "action",
-    archived: false,
-  };
-  const dashcardOverrides = {
-    card: virtualActionsCard,
-    size_x: 2,
-    size_y: 1,
-    visualization_settings: {
-      virtual_card: virtualActionsCard,
-    },
+const esitmateCardSize = (displayType, action) => {
+  const BASE_HEIGHT = 3;
+  const HEIGHT_PER_FIELD = 1.5;
+
+  if (displayType === "button") {
+    return { size_x: 2, size_y: 1 };
+  }
+
+  return {
+    size_x: 6,
+    size_y: Math.round(
+      BASE_HEIGHT + action.parameters.length * HEIGHT_PER_FIELD,
+    ),
   };
-  return addDashCardToDashboard({
-    dashId: dashId,
-    dashcardOverrides: dashcardOverrides,
-  });
 };
+
+export const addActionToDashboard =
+  async ({ dashId, action, displayType }) =>
+  dispatch => {
+    const virtualActionsCard = {
+      ...createCard(),
+      display: "action",
+      archived: false,
+    };
+
+    const dashcardOverrides = {
+      action,
+      card_id: action.model_id,
+      card: virtualActionsCard,
+      ...esitmateCardSize(displayType, action),
+      visualization_settings: {
+        actionDisplayType: displayType ?? "button",
+        virtual_card: virtualActionsCard,
+        "button.label": action.name ?? action.id,
+        action_slug: action.slug,
+      },
+    };
+    dispatch(
+      addDashCardToDashboard({
+        dashId: dashId,
+        dashcardOverrides: dashcardOverrides,
+      }),
+    );
+  };
+
+export const addLinkToDashboard =
+  async ({ dashId, clickBehavior }) =>
+  dispatch => {
+    const virtualActionsCard = {
+      ...createCard(),
+      display: "action",
+      archived: false,
+    };
+    const dashcardOverrides = {
+      card: virtualActionsCard,
+      size_x: 2,
+      size_y: 1,
+      visualization_settings: {
+        virtual_card: virtualActionsCard,
+        "button.label": t`Link`,
+        click_behavior: clickBehavior,
+        actionDisplayType: "button",
+      },
+    };
+    dispatch(
+      addDashCardToDashboard({
+        dashId: dashId,
+        dashcardOverrides: dashcardOverrides,
+      }),
+    );
+  };
diff --git a/frontend/src/metabase/dashboard/actions/save.js b/frontend/src/metabase/dashboard/actions/save.js
index f176e62fa547519409a6e907df6eb87e2412924a..0ad697f79f5c2eecfdab694131882ad86f032b35 100644
--- a/frontend/src/metabase/dashboard/actions/save.js
+++ b/frontend/src/metabase/dashboard/actions/save.js
@@ -77,7 +77,6 @@ export const saveDashboardAndCards = createThunkAction(
               // mark isAdded because addcard doesn't record the position
               return {
                 ...result,
-                action_id: dc.action_id,
                 col: dc.col,
                 row: dc.row,
                 size_x: dc.size_x,
diff --git a/frontend/src/metabase/dashboard/actions/ui.js b/frontend/src/metabase/dashboard/actions/ui.js
index 5536b270720b1f17f744622496a029ba4407a991..65328ff3bcd49fe33778a8eedcd0a0f3494441a2 100644
--- a/frontend/src/metabase/dashboard/actions/ui.js
+++ b/frontend/src/metabase/dashboard/actions/ui.js
@@ -1,5 +1,6 @@
 import { createAction } from "metabase/lib/redux";
 import { SIDEBAR_NAME } from "metabase/dashboard/constants";
+import { getSidebar } from "../selectors";
 
 export const SET_SIDEBAR = "metabase/dashboard/SET_SIDEBAR";
 export const setSidebar = createAction(SET_SIDEBAR);
@@ -20,6 +21,15 @@ export const showClickBehaviorSidebar = dashcardId => dispatch => {
   }
 };
 
+export const toggleSidebar = name => (dispatch, getState) => {
+  const currentSidebarName = getSidebar(getState()).name;
+  if (currentSidebarName === name) {
+    dispatch(closeSidebar());
+  } else {
+    dispatch(setSidebar({ name }));
+  }
+};
+
 export const openAddQuestionSidebar = () => dispatch => {
   dispatch(
     setSidebar({
diff --git a/frontend/src/metabase/dashboard/components/AddActionSidebar/AddActionSidebar.styled.tsx b/frontend/src/metabase/dashboard/components/AddActionSidebar/AddActionSidebar.styled.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..be7fcd176b6daa14b690e9df8cbfef6f39be411a
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/AddActionSidebar/AddActionSidebar.styled.tsx
@@ -0,0 +1,43 @@
+import styled from "@emotion/styled";
+import { color } from "metabase/lib/colors";
+import { space } from "metabase/styled-components/theme";
+
+export const Heading = styled.h4`
+  color: ${color("text-dark")};
+  font-size: 1.125rem;
+`;
+
+export const SidebarContent = styled.div`
+  padding: 1rem 2rem;
+`;
+
+export const BorderedSidebarContent = styled(SidebarContent)`
+  border-bottom: 1px solid ${color("border")};
+`;
+
+export const ClickBehaviorPickerText = styled.div`
+  color: ${color("text-medium")};
+  margin-bottom: ${space(2)};
+  margin-left: ${space(2)};
+`;
+
+export const BackButtonContainer = styled.div`
+  display: flex;
+  align-items: center;
+  cursor: pointer;
+  font-weight: bold;
+
+  color: ${color("text-medium")};
+
+  &:hover {
+    color: ${color("brand")};
+  }
+`;
+
+export const BackButtonIconContainer = styled.div`
+  padding: 4px 6px;
+  margin-right: 8px;
+
+  border: 1px solid ${color("border")};
+  border-radius: 4px;
+`;
diff --git a/frontend/src/metabase/dashboard/components/AddActionSidebar/AddActionSidebar.tsx b/frontend/src/metabase/dashboard/components/AddActionSidebar/AddActionSidebar.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..366eb72807f7c0b2a478a45f461dc1f72cc23d29
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/AddActionSidebar/AddActionSidebar.tsx
@@ -0,0 +1,121 @@
+import React, { useState } from "react";
+import _ from "underscore";
+import { t } from "ttag";
+import { connect } from "react-redux";
+
+import type {
+  ActionDisplayType,
+  Dashboard,
+  WritebackAction,
+  Card,
+  CustomDestinationClickBehavior,
+} from "metabase-types/api";
+import type { State } from "metabase-types/store";
+
+import Search from "metabase/entities/search";
+
+import Sidebar from "metabase/dashboard/components/Sidebar";
+import ActionPicker from "metabase/containers/ActionPicker";
+import {
+  addActionToDashboard,
+  addLinkToDashboard,
+  closeSidebar,
+} from "metabase/dashboard/actions";
+
+import { ButtonOptions } from "./ButtonOptions";
+import {
+  Heading,
+  SidebarContent,
+  BorderedSidebarContent,
+} from "./AddActionSidebar.styled";
+
+const mapDispatchToProps = {
+  addAction: addActionToDashboard,
+  addLink: addLinkToDashboard,
+  closeSidebar,
+};
+
+interface ActionSidebarProps {
+  dashboard: Dashboard;
+  addAction: ({
+    dashId,
+    action,
+    displayType,
+  }: {
+    dashId: number;
+    action: WritebackAction;
+    displayType: ActionDisplayType;
+  }) => void;
+  addLink: ({
+    dashId,
+    clickBehavior,
+  }: {
+    dashId: number;
+    clickBehavior: CustomDestinationClickBehavior;
+  }) => void;
+  closeSidebar: () => void;
+  models: Card[];
+  displayType: ActionDisplayType;
+}
+
+function AddActionSidebarFn({
+  dashboard,
+  addAction,
+  addLink,
+  closeSidebar,
+  models,
+  displayType,
+}: ActionSidebarProps) {
+  const handleActionSelected = async (action: WritebackAction) => {
+    await addAction({ dashId: dashboard.id, action, displayType });
+  };
+  const modelIds = models?.map(model => model.id) ?? [];
+  const showButtonOptions = displayType === "button";
+  const showActionPicker = displayType === "form";
+
+  return (
+    <Sidebar>
+      <BorderedSidebarContent>
+        <Heading>
+          {t`Add a ${
+            displayType === "button" ? t`button` : t`form`
+          } to the page`}
+        </Heading>
+      </BorderedSidebarContent>
+
+      {showActionPicker && (
+        <SidebarContent>
+          <ActionPicker modelIds={modelIds} onClick={handleActionSelected} />
+        </SidebarContent>
+      )}
+
+      {showButtonOptions && (
+        <ButtonOptions
+          addLink={addLink}
+          closeSidebar={closeSidebar}
+          dashboard={dashboard}
+          ActionPicker={
+            <SidebarContent>
+              <ActionPicker
+                modelIds={modelIds}
+                onClick={handleActionSelected}
+              />
+            </SidebarContent>
+          }
+        />
+      )}
+    </Sidebar>
+  );
+}
+
+export const AddActionSidebar = _.compose(
+  Search.loadList({
+    query: (_state: State, props: any) => ({
+      models: ["dataset"],
+      collection: props.dashboard.collection_id,
+    }),
+    loadingAndErrorWrapper: false,
+    listName: "models",
+  }),
+  connect(null, mapDispatchToProps),
+)(AddActionSidebarFn);
diff --git a/frontend/src/metabase/dashboard/components/AddActionSidebar/ButtonOptions.tsx b/frontend/src/metabase/dashboard/components/AddActionSidebar/ButtonOptions.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..c5b8912db14c59ddb4fb406034e246d55faca8b2
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/AddActionSidebar/ButtonOptions.tsx
@@ -0,0 +1,129 @@
+import React, { useState } from "react";
+import { t } from "ttag";
+
+import type {
+  Dashboard,
+  CustomDestinationClickBehavior,
+  DashboardOrderedCard,
+} from "metabase-types/api";
+import { clickBehaviorIsValid } from "metabase/lib/click-behavior";
+
+import { BehaviorOption } from "metabase/dashboard/components/ClickBehaviorSidebar/TypeSelector/TypeSelector";
+import LinkOptions from "metabase/dashboard/components/ClickBehaviorSidebar/LinkOptions";
+import Icon from "metabase/components/Icon";
+
+import {
+  ClickBehaviorPickerText,
+  SidebarContent,
+  BackButtonIconContainer,
+  BackButtonContainer,
+  BorderedSidebarContent,
+} from "./AddActionSidebar.styled";
+
+type ButtonType = "action" | "link" | null;
+
+// this type depends on no properties being null, but many of the components that use it expect nulls while
+// the object is buing constructed :(
+const emptyClickBehavior: any = {
+  type: "link",
+  linkType: null,
+  targetId: null,
+};
+
+export const ButtonOptions = ({
+  addLink,
+  closeSidebar,
+  dashboard,
+  ActionPicker,
+}: {
+  addLink: ({
+    dashId,
+    clickBehavior,
+  }: {
+    dashId: number;
+    clickBehavior: CustomDestinationClickBehavior;
+  }) => void;
+  closeSidebar: () => void;
+  dashboard: Dashboard;
+  ActionPicker: React.ReactNode;
+}) => {
+  const [buttonType, setButtonType] = useState<ButtonType>(null);
+  const [linkClickBehavior, setLinkClickBehavior] =
+    useState<CustomDestinationClickBehavior>(emptyClickBehavior);
+
+  const showLinkPicker = buttonType === "link";
+  const showActionPicker = buttonType === "action";
+
+  const handleClickBehaviorChange = (
+    newClickBehavior: CustomDestinationClickBehavior,
+  ) => {
+    if (newClickBehavior.type !== "link") {
+      return;
+    }
+    if (clickBehaviorIsValid(newClickBehavior)) {
+      addLink({ dashId: dashboard.id, clickBehavior: newClickBehavior });
+      closeSidebar();
+      return;
+    }
+    setLinkClickBehavior(newClickBehavior);
+  };
+
+  return (
+    <>
+      <ButtonTypePicker value={buttonType} onChange={setButtonType} />
+
+      {showLinkPicker && (
+        <LinkOptions
+          clickBehavior={linkClickBehavior}
+          dashcard={{ card: { display: "action" } } as DashboardOrderedCard} // necessary for LinkOptions to work
+          parameters={[]}
+          updateSettings={handleClickBehaviorChange as any}
+        />
+      )}
+      {showActionPicker && ActionPicker}
+    </>
+  );
+};
+
+const ButtonTypePicker = ({
+  value,
+  onChange,
+}: {
+  value: ButtonType;
+  onChange: (type: ButtonType) => void;
+}) => {
+  if (value) {
+    return (
+      <BorderedSidebarContent>
+        <BackButtonContainer onClick={() => onChange(null)}>
+          <BackButtonIconContainer>
+            <Icon name="chevronleft" size={16} />
+          </BackButtonIconContainer>
+          <div>{t`Change button type`}</div>
+        </BackButtonContainer>
+      </BorderedSidebarContent>
+    );
+  }
+
+  return (
+    <SidebarContent>
+      <ClickBehaviorPickerText>
+        {t`What type of button do you want to add?`}
+      </ClickBehaviorPickerText>
+      <BehaviorOption
+        option={t`Perform action`}
+        selected={false}
+        icon="play"
+        hasNextStep
+        onClick={() => onChange("action")}
+      />
+      <BehaviorOption
+        option={t`Go to a custom destination`}
+        selected={false}
+        icon="link"
+        hasNextStep
+        onClick={() => onChange("link")}
+      />
+    </SidebarContent>
+  );
+};
diff --git a/frontend/src/metabase/dashboard/components/AddActionSidebar/index.ts b/frontend/src/metabase/dashboard/components/AddActionSidebar/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..82ec75ef22b9f69c5726d2a3b9e9f3db6fab4c47
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/AddActionSidebar/index.ts
@@ -0,0 +1 @@
+export * from "./AddActionSidebar";
diff --git a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/ActionOptions.styled.tsx b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/ActionOptions.styled.tsx
index d8b033260e31c68e1c1a4f7a564d928ecb97d454..f6fb47d085c1f7089d77361655c2d90313c0f4f4 100644
--- a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/ActionOptions.styled.tsx
+++ b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/ActionOptions.styled.tsx
@@ -1,34 +1,6 @@
 import _ from "underscore";
 import styled from "@emotion/styled";
 
-import { color } from "metabase/lib/colors";
-
-import { SidebarItem } from "../SidebarItem";
-
-export const ActionSidebarItem = styled(SidebarItem.Selectable)<{
-  hasDescription?: boolean;
-}>`
-  align-items: ${props => (props.hasDescription ? "flex-start" : "center")};
-  margin-top: 2px;
-`;
-
-export const ActionSidebarItemIcon = styled(SidebarItem.Icon)<{
-  isSelected?: boolean;
-}>`
-  .Icon {
-    color: ${props =>
-      props.isSelected ? color("text-white") : color("brand")};
-  }
-`;
-
-export const ActionDescription = styled.span<{ isSelected?: boolean }>`
-  width: 95%;
-  margin-top: 2px;
-
-  color: ${props =>
-    props.isSelected ? color("text-white") : color("text-medium")};
-`;
-
 export const ClickMappingsContainer = styled.div`
   margin-top: 1rem;
 `;
diff --git a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/ActionOptions.tsx b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/ActionOptions.tsx
index 1b28a5f9b4f7b9c356a40ecd04747fd3f5ff2333..904f725b8fb942bcc3a614e1cb59eeee687c6aa5 100644
--- a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/ActionOptions.tsx
+++ b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/ActionOptions.tsx
@@ -1,9 +1,7 @@
 import React, { useCallback } from "react";
-import { t } from "ttag";
 import { connect } from "react-redux";
 
 import { updateButtonActionMapping } from "metabase/dashboard/actions";
-import { updateSettings } from "metabase/visualizations/lib/settings";
 
 import ActionPicker from "metabase/containers/ActionPicker";
 
@@ -15,13 +13,10 @@ import type {
 import type { State } from "metabase-types/store";
 import type { UiParameter } from "metabase/parameters/types";
 
-import { Heading, SidebarContent } from "../ClickBehaviorSidebar.styled";
+import { SidebarContent } from "../ClickBehaviorSidebar.styled";
 
 import ActionClickMappings from "./ActionClickMappings";
-import {
-  ClickMappingsContainer,
-  ActionPickerWrapper,
-} from "./ActionOptions.styled";
+import { ClickMappingsContainer } from "./ActionOptions.styled";
 
 import { ensureParamsHaveNames } from "./utils";
 
@@ -55,26 +50,6 @@ function ActionOptions({
 }: ActionOptionsProps) {
   const selectedAction = dashcard.action;
 
-  const handleActionSelected = useCallback(
-    (action: WritebackAction) => {
-      onUpdateButtonActionMapping(dashcard.id, {
-        card_id: action.model_id,
-        action,
-        visualization_settings: updateSettings(
-          {
-            "button.label": action.name,
-            action_slug: action.slug, // :-( so hacky
-          },
-          dashcard.visualization_settings,
-        ),
-        // Clean mappings from previous action
-        // as they're most likely going to be irrelevant
-        parameter_mappings: null,
-      });
-    },
-    [dashcard, onUpdateButtonActionMapping],
-  );
-
   const handleParameterMappingChange = useCallback(
     (parameter_mappings: ActionParametersMapping[] | null) => {
       onUpdateButtonActionMapping(dashcard.id, {
@@ -84,36 +59,23 @@ function ActionOptions({
     [dashcard, onUpdateButtonActionMapping],
   );
 
-  return (
-    <ActionPickerWrapper>
-      <ActionPicker value={selectedAction} onChange={handleActionSelected} />
-
-      {!!selectedAction && (
-        <ClickMappingsContainer>
-          <ActionClickMappings
-            action={{
-              ...selectedAction,
-              parameters: ensureParamsHaveNames(selectedAction.parameters),
-            }}
-            dashcard={dashcard}
-            parameters={parameters}
-            onChange={handleParameterMappingChange}
-          />
-        </ClickMappingsContainer>
-      )}
-    </ActionPickerWrapper>
-  );
-}
+  if (!selectedAction) {
+    return null;
+  }
 
-function ActionOptionsContainer(props: ActionOptionsProps) {
   return (
     <SidebarContent>
-      <Heading className="text-medium">{t`Pick an action`}</Heading>
-      <ActionOptions
-        dashcard={props.dashcard}
-        parameters={props.parameters}
-        onUpdateButtonActionMapping={props.onUpdateButtonActionMapping}
-      />
+      <ClickMappingsContainer>
+        <ActionClickMappings
+          action={{
+            ...selectedAction,
+            parameters: ensureParamsHaveNames(selectedAction?.parameters ?? []),
+          }}
+          dashcard={dashcard}
+          parameters={parameters}
+          onChange={handleParameterMappingChange}
+        />
+      </ClickMappingsContainer>
     </SidebarContent>
   );
 }
@@ -126,4 +88,4 @@ export default connect<
 >(
   null,
   mapDispatchToProps,
-)(ActionOptionsContainer);
+)(ActionOptions);
diff --git a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/utils.ts b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/utils.ts
index 1f0660e19bf8f8180966f0759b39382e6f2a592e..a49dd8ebdd9f1b1be11cecb63b81d6796821b74e 100644
--- a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/utils.ts
+++ b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/utils.ts
@@ -1,4 +1,5 @@
 import _ from "underscore";
+import { humanize } from "metabase/lib/formatting";
 
 import type {
   ActionDashboardCard,
@@ -78,6 +79,6 @@ export function ensureParamsHaveNames(
 ): WritebackParameter[] {
   return parameters.map(parameter => ({
     ...parameter,
-    name: parameter.name ?? parameter.id,
+    name: parameter.name ?? humanize(parameter.id),
   }));
 }
diff --git a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/utils.unit.spec.ts b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/utils.unit.spec.ts
index 1e05ae7c712ebd83bfc1cd116a9004918c59c5c5..083aa06fa14bd752839885427b4879c1948db04d 100644
--- a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/utils.unit.spec.ts
+++ b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ActionOptions/utils.unit.spec.ts
@@ -63,7 +63,6 @@ describe("turnDashCardParameterMappingsIntoClickBehaviorMappings", () => {
     const action = createMockQueryAction({ parameters: actionParameters });
     const dashCard = createMockDashboardActionButton({
       action,
-      action_id: action.id,
       parameter_mappings: dashCardParameterMappings,
     });
     return { action, dashCard };
diff --git a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ClickBehaviorSidebarMainView/ClickBehaviorSidebarMainView.tsx b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ClickBehaviorSidebarMainView/ClickBehaviorSidebarMainView.tsx
index 0967a49a8fecd03a6e22389514a84ed03ebc59af..fbea0fcd1e717e03fd28f83ea21940f0fd4f58e6 100644
--- a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ClickBehaviorSidebarMainView/ClickBehaviorSidebarMainView.tsx
+++ b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/ClickBehaviorSidebarMainView/ClickBehaviorSidebarMainView.tsx
@@ -33,6 +33,14 @@ function ClickBehaviorOptions({
   parameters,
   updateSettings,
 }: ClickBehaviorOptionsProps) {
+  if (dashcard.action) {
+    return (
+      <ActionOptions
+        dashcard={dashcard as ActionDashboardCard}
+        parameters={parameters}
+      />
+    );
+  }
   if (clickBehavior.type === "link") {
     return (
       <LinkOptions
@@ -53,12 +61,7 @@ function ClickBehaviorOptions({
       />
     );
   }
-  return (
-    <ActionOptions
-      dashcard={dashcard as unknown as ActionDashboardCard}
-      parameters={parameters}
-    />
-  );
+  return null;
 }
 
 interface ClickBehaviorSidebarMainViewProps {
@@ -88,21 +91,23 @@ function ClickBehaviorSidebarMainView({
 
   return (
     <>
-      <SidebarContentBordered>
-        <SidebarItem.Selectable
-          onClick={handleShowTypeSelector}
-          isSelected
-          padded={false}
-        >
-          <SelectedClickBehaviorItemIcon
-            name={currentOption?.icon || "unknown"}
-          />
-          <SidebarItem.Content>
-            <SidebarItem.Name>{clickBehaviorOptionName}</SidebarItem.Name>
-            <SidebarItem.CloseIcon />
-          </SidebarItem.Content>
-        </SidebarItem.Selectable>
-      </SidebarContentBordered>
+      {!dashcard.action && (
+        <SidebarContentBordered>
+          <SidebarItem.Selectable
+            onClick={handleShowTypeSelector}
+            isSelected
+            padded={false}
+          >
+            <SelectedClickBehaviorItemIcon
+              name={currentOption?.icon || "unknown"}
+            />
+            <SidebarItem.Content>
+              <SidebarItem.Name>{clickBehaviorOptionName}</SidebarItem.Name>
+              <SidebarItem.CloseIcon />
+            </SidebarItem.Content>
+          </SidebarItem.Selectable>
+        </SidebarContentBordered>
+      )}
 
       <ClickBehaviorOptions
         clickBehavior={clickBehavior}
diff --git a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/TypeSelector/TypeSelector.tsx b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/TypeSelector/TypeSelector.tsx
index d1e4cc9b671c555e8e7f9cae133b0c2983cd70ad..888c4b4ab32125310d7e198277ed8c240772b098 100644
--- a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/TypeSelector/TypeSelector.tsx
+++ b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/TypeSelector/TypeSelector.tsx
@@ -22,7 +22,7 @@ interface BehaviorOptionProps {
   onClick: () => void;
 }
 
-const BehaviorOption = ({
+export const BehaviorOption = ({
   option,
   icon,
   onClick,
diff --git a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/utils.ts b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/utils.ts
index 67c656d0effe6f400060796652e4b94aae4042be..27dd4af4ca85d1c2dac9ab76d27abd71fc0f72ef 100644
--- a/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/utils.ts
+++ b/frontend/src/metabase/dashboard/components/ClickBehaviorSidebar/utils.ts
@@ -19,7 +19,6 @@ export const clickBehaviorOptions: ClickBehaviorOption[] = [
   { value: "menu", icon: "popover" },
   { value: "link", icon: "link" },
   { value: "crossfilter", icon: "filter" },
-  { value: "action", icon: "play" },
 ];
 
 export function getClickBehaviorOptionName(
diff --git a/frontend/src/metabase/dashboard/components/Dashboard/Dashboard.jsx b/frontend/src/metabase/dashboard/components/Dashboard/Dashboard.jsx
index e6e3c6f59e0cf7b22ae525ac0e4a250e6139978e..a3cd469ec0328b600bd2e754a002adeb0ea71f2d 100644
--- a/frontend/src/metabase/dashboard/components/Dashboard/Dashboard.jsx
+++ b/frontend/src/metabase/dashboard/components/Dashboard/Dashboard.jsx
@@ -87,8 +87,6 @@ class Dashboard extends Component {
       props: PropTypes.object,
     }).isRequired,
     closeSidebar: PropTypes.func.isRequired,
-    openAddQuestionSidebar: PropTypes.func.isRequired,
-    showAddQuestionSidebar: PropTypes.bool.isRequired,
     embedOptions: PropTypes.object,
   };
 
@@ -192,14 +190,6 @@ class Dashboard extends Component {
     });
   };
 
-  onToggleAddQuestionSidebar = () => {
-    if (this.props.showAddQuestionSidebar) {
-      this.props.closeSidebar();
-    } else {
-      this.props.openAddQuestionSidebar();
-    }
-  };
-
   onCancel = () => {
     this.props.setSharing(false);
   };
@@ -220,7 +210,6 @@ class Dashboard extends Component {
       parameters,
       parameterValues,
       isNavbarOpen,
-      showAddQuestionSidebar,
       editingParameter,
       setParameterValue,
       setParameterIndex,
@@ -282,9 +271,6 @@ class Dashboard extends Component {
                   addParameter={addParameter}
                   parametersWidget={parametersWidget}
                   onSharingClick={this.onSharingClick}
-                  onToggleAddQuestionSidebar={this.onToggleAddQuestionSidebar}
-                  showAddQuestionSidebar={showAddQuestionSidebar}
-                  isDataApp={dashboard.is_app_page}
                 />
 
                 {shouldRenderParametersWidgetInEditMode && (
@@ -336,7 +322,6 @@ class Dashboard extends Component {
               <DashboardSidebars
                 {...this.props}
                 onCancel={this.onCancel}
-                showAddQuestionSidebar={showAddQuestionSidebar}
                 setDashboardAttribute={this.setDashboardAttribute}
               />
             </DashboardBody>
diff --git a/frontend/src/metabase/dashboard/components/DashboardSidebars.jsx b/frontend/src/metabase/dashboard/components/DashboardSidebars.jsx
index c89b1dd62cf522e45206f60bcbb24fbf21a9c9ba..19e6f1cc541a57542dd267f92007171c3cb90eac 100644
--- a/frontend/src/metabase/dashboard/components/DashboardSidebars.jsx
+++ b/frontend/src/metabase/dashboard/components/DashboardSidebars.jsx
@@ -10,6 +10,7 @@ import * as MetabaseAnalytics from "metabase/lib/analytics";
 import ClickBehaviorSidebar from "./ClickBehaviorSidebar";
 import DashboardInfoSidebar from "./DashboardInfoSidebar";
 import { AddCardSidebar } from "./add-card-sidebar/AddCardSidebar";
+import { AddActionSidebar } from "./AddActionSidebar";
 
 DashboardSidebars.propTypes = {
   dashboard: PropTypes.object,
@@ -19,7 +20,6 @@ DashboardSidebars.propTypes = {
   addCardToDashboard: PropTypes.func.isRequired,
   editingParameter: PropTypes.object,
   isEditingParameter: PropTypes.bool.isRequired,
-  showAddQuestionSidebar: PropTypes.bool.isRequired,
   clickBehaviorSidebarDashcard: PropTypes.object, // only defined when click-behavior sidebar is open
   onReplaceAllDashCardVisualizationSettings: PropTypes.func.isRequired,
   onUpdateDashCardVisualizationSettings: PropTypes.func.isRequired,
@@ -51,20 +51,15 @@ export function DashboardSidebars({
   removeParameter,
   addCardToDashboard,
   editingParameter,
-  isEditingParameter,
-  showAddQuestionSidebar,
   clickBehaviorSidebarDashcard,
   onReplaceAllDashCardVisualizationSettings,
   onUpdateDashCardVisualizationSettings,
   onUpdateDashCardColumnSettings,
-  setEditingParameter,
   setParameter,
   setParameterName,
   setParameterDefaultValue,
   dashcardData,
   setParameterFilteringParameters,
-  isSharing,
-  isEditing,
   isFullscreen,
   onCancel,
   params,
@@ -96,6 +91,16 @@ export function DashboardSidebars({
           onSelect={handleAddCard}
         />
       );
+    case SIDEBAR_NAME.addActionForm:
+    case SIDEBAR_NAME.addActionButton:
+      return (
+        <AddActionSidebar
+          dashboard={dashboard}
+          displayType={
+            sidebar.name === SIDEBAR_NAME.addActionForm ? "form" : "button"
+          }
+        />
+      );
     case SIDEBAR_NAME.clickBehavior:
       return (
         <ClickBehaviorSidebar
diff --git a/frontend/src/metabase/dashboard/constants.js b/frontend/src/metabase/dashboard/constants.js
index 6703c46daf49e1641a93501e93e722cd4b5ce969..e3f05ec65070f50603ef33b491bd81ac13d6bf60 100644
--- a/frontend/src/metabase/dashboard/constants.js
+++ b/frontend/src/metabase/dashboard/constants.js
@@ -1,5 +1,7 @@
 export const SIDEBAR_NAME = {
   addQuestion: "addQuestion",
+  addActionButton: "addActionButton",
+  addActionForm: "addActionForm",
   clickBehavior: "clickBehavior",
   editParameter: "editParameter",
   sharing: "sharing",
diff --git a/frontend/src/metabase/dashboard/containers/DashboardApp.jsx b/frontend/src/metabase/dashboard/containers/DashboardApp.jsx
index c9f012b7e89614c066e46725fde2b09d03c9c9bb..130d57e99d46522ac3c1ea8e4f74dc5aa0a4f372 100644
--- a/frontend/src/metabase/dashboard/containers/DashboardApp.jsx
+++ b/frontend/src/metabase/dashboard/containers/DashboardApp.jsx
@@ -51,7 +51,6 @@ import {
   getClickBehaviorSidebarDashcard,
   getIsAddParameterPopoverOpen,
   getSidebar,
-  getShowAddQuestionSidebar,
   getFavicon,
   getDocumentTitle,
   getIsRunning,
@@ -95,7 +94,6 @@ const mapStateToProps = (state, props) => {
     clickBehaviorSidebarDashcard: getClickBehaviorSidebarDashcard(state),
     isAddParameterPopoverOpen: getIsAddParameterPopoverOpen(state),
     sidebar: getSidebar(state),
-    showAddQuestionSidebar: getShowAddQuestionSidebar(state),
     pageFavicon: getFavicon(state),
     documentTitle: getDocumentTitle(state),
     isRunning: getIsRunning(state),
diff --git a/frontend/src/metabase/dashboard/containers/DashboardHeader.jsx b/frontend/src/metabase/dashboard/containers/DashboardHeader.jsx
index 5c7337d69a175320ae68405c89c24cffb0c4d8d0..c1a727e68be253ec7749f93f6c90a2c592885529 100644
--- a/frontend/src/metabase/dashboard/containers/DashboardHeader.jsx
+++ b/frontend/src/metabase/dashboard/containers/DashboardHeader.jsx
@@ -25,6 +25,7 @@ import {
   getIsBookmarked,
   getIsShowDashboardInfoSidebar,
 } from "metabase/dashboard/selectors";
+import { toggleSidebar } from "../actions";
 
 import Header from "../components/DashboardHeader";
 import { SIDEBAR_NAME } from "../constants";
@@ -50,6 +51,7 @@ const mapDispatchToProps = {
   deleteBookmark: ({ id }) =>
     Bookmark.actions.delete({ id, type: "dashboard" }),
   onChangeLocation: push,
+  toggleSidebar,
 };
 
 class DashboardHeader extends Component {
@@ -92,6 +94,8 @@ class DashboardHeader extends Component {
 
     onChangeLocation: PropTypes.func.isRequired,
 
+    toggleSidebar: PropTypes.func.isRequired,
+    sidebar: PropTypes.string.isRequired,
     setSidebar: PropTypes.func.isRequired,
     closeSidebar: PropTypes.func.isRequired,
   };
@@ -189,12 +193,12 @@ class DashboardHeader extends Component {
       isFullscreen,
       isEditable,
       location,
-      onToggleAddQuestionSidebar,
-      showAddQuestionSidebar,
       onFullscreenChange,
       createBookmark,
       deleteBookmark,
+      sidebar,
       setSidebar,
+      toggleSidebar,
       isShowingDashboardInfoSidebar,
       closeSidebar,
     } = this.props;
@@ -210,16 +214,18 @@ class DashboardHeader extends Component {
     }
 
     if (isEditing) {
-      const addQuestionButtonHint = showAddQuestionSidebar
-        ? t`Close sidebar`
-        : t`Add questions`;
+      const activeSidebarName = sidebar.name;
+      const addQuestionButtonHint =
+        activeSidebarName === SIDEBAR_NAME.addQuestion
+          ? t`Close sidebar`
+          : t`Add questions`;
 
       buttons.push(
         <Tooltip tooltip={addQuestionButtonHint}>
           <DashboardHeaderButton
             icon="add"
-            isActive={showAddQuestionSidebar}
-            onClick={onToggleAddQuestionSidebar}
+            isActive={activeSidebarName === SIDEBAR_NAME.addQuestion}
+            onClick={() => toggleSidebar(SIDEBAR_NAME.addQuestion)}
             data-metabase-event="Dashboard;Add Card Sidebar"
           />
         </Tooltip>,
@@ -241,23 +247,6 @@ class DashboardHeader extends Component {
         </Tooltip>,
       );
 
-      if (isAdmin && dashboard.is_app_page) {
-        buttons.push(
-          <Tooltip key="add-action" tooltip={t`Add action`}>
-            <a
-              data-metabase-event="Dashboard;Add Action"
-              key="add-action"
-              className="text-brand-hover cursor-pointer"
-              onClick={() => this.onAddAction()}
-            >
-              <DashboardHeaderButton>
-                <Icon name="play" size={18} />
-              </DashboardHeaderButton>
-            </a>
-          </Tooltip>,
-        );
-      }
-
       const {
         isAddParameterPopoverOpen,
         showAddParameterPopover,
@@ -293,6 +282,32 @@ class DashboardHeader extends Component {
         </span>,
       );
 
+      if (isAdmin && dashboard.is_app_page) {
+        buttons.push(
+          <>
+            <DashboardHeaderActionDivider />
+            <Tooltip key="add-action-form" tooltip={t`Add action form`}>
+              <DashboardHeaderButton
+                isActive={activeSidebarName === SIDEBAR_NAME.addActionForm}
+                onClick={() => toggleSidebar(SIDEBAR_NAME.addActionForm)}
+                data-metabase-event="Dashboard;Add Card Sidebar"
+              >
+                <Icon name="list" size={18} />
+              </DashboardHeaderButton>
+            </Tooltip>
+            <Tooltip key="add-action-button" tooltip={t`Add action button`}>
+              <DashboardHeaderButton
+                isActive={activeSidebarName === SIDEBAR_NAME.addActionButton}
+                onClick={() => toggleSidebar(SIDEBAR_NAME.addActionButton)}
+                data-metabase-event="Dashboard;Add Card Sidebar"
+              >
+                <Icon name="click" size={18} />
+              </DashboardHeaderButton>
+            </Tooltip>
+          </>,
+        );
+      }
+
       extraButtons.push({
         title: t`Revision history`,
         icon: "history",
diff --git a/frontend/src/metabase/entities/actions/actions.ts b/frontend/src/metabase/entities/actions/actions.ts
index 584f31136be987ca5cd411cff59f1abb41a538eb..6eef3a6165fc371a2da78e801b242e28f0275d5d 100644
--- a/frontend/src/metabase/entities/actions/actions.ts
+++ b/frontend/src/metabase/entities/actions/actions.ts
@@ -1,10 +1,6 @@
 import { createEntity } from "metabase/lib/entities";
 
-import type {
-  ActionFormSettings,
-  ModelAction,
-  WritebackAction,
-} from "metabase-types/api";
+import type { ActionFormSettings, WritebackAction } from "metabase-types/api";
 import type { Dispatch } from "metabase-types/store";
 
 import { ActionsApi, CardApi, ModelActionsApi } from "metabase/services";
@@ -122,9 +118,9 @@ const Actions = createEntity({
     list: async (params: any) => {
       const actions = await ActionsApi.list(params);
 
-      return actions.map((action: ModelAction | WritebackAction) => ({
+      return actions.map((action: WritebackAction) => ({
         ...action,
-        id: action.id ?? `implicit-${action.slug}`,
+        id: action.id ?? `implicit-${action.slug}-${action.model_id}`,
         name: action.name ?? action.slug,
       }));
     },
diff --git a/frontend/src/metabase/lib/click-behavior.js b/frontend/src/metabase/lib/click-behavior.js
index ec5dabb0ddc5ce3077e279a70e11b7c33305732f..b53ca8252a2ea344190154d00304713b315746b8 100644
--- a/frontend/src/metabase/lib/click-behavior.js
+++ b/frontend/src/metabase/lib/click-behavior.js
@@ -274,7 +274,7 @@ export function hasActionsMenu(dashcard) {
 }
 
 export function isTableDisplay(dashcard) {
-  return dashcard.card.display === "table";
+  return dashcard?.card?.display === "table";
 }
 
 export function formatSourceForTarget(
diff --git a/frontend/src/metabase/models/components/ModelDetailPage/ModelActionDetails/ModelActionDetails.tsx b/frontend/src/metabase/models/components/ModelDetailPage/ModelActionDetails/ModelActionDetails.tsx
index 3a2b6661441074ef37cb22098b75f6aba2bf19bb..30381f9b4f9a0fe771e63a1034cffef362b2e392 100644
--- a/frontend/src/metabase/models/components/ModelDetailPage/ModelActionDetails/ModelActionDetails.tsx
+++ b/frontend/src/metabase/models/components/ModelDetailPage/ModelActionDetails/ModelActionDetails.tsx
@@ -46,11 +46,7 @@ function ModelActionDetails({
         <Button onClick={handleCreateImplicitActions} icon="add">
           {t`Enable implicit actions`}
         </Button>
-        <Button
-          as={Link}
-          to="/action/create"
-          icon="add"
-        >{t`Create a new action`}</Button>
+        <AddActionButton modelId={modelId} />
       </EmptyStateContainer>
     );
   }
@@ -64,6 +60,7 @@ function ModelActionDetails({
           {t`Enable implicit actions`}
         </Button>
       )}
+      <AddActionButton modelId={modelId} />
       <ul>
         {actions.map(action => (
           <li key={action.id}>
@@ -83,6 +80,14 @@ function ModelActionDetails({
   );
 }
 
+const AddActionButton = ({ modelId }: { modelId: number }) => (
+  <Button
+    as={Link}
+    to={`/action/create?model-id=${modelId}`}
+    icon="add"
+  >{t`Create a new action`}</Button>
+);
+
 export default Actions.loadList(
   {
     query: (state: State, props: { modelId?: number | null }) => ({
diff --git a/frontend/src/metabase/models/components/ModelDetailPage/ModelDetailPage.styled.tsx b/frontend/src/metabase/models/components/ModelDetailPage/ModelDetailPage.styled.tsx
index 6cea9850586be0025f37a5da99703f2bc6159512..997affd9bd499f01c6e196fe89502f9b9ac5d453 100644
--- a/frontend/src/metabase/models/components/ModelDetailPage/ModelDetailPage.styled.tsx
+++ b/frontend/src/metabase/models/components/ModelDetailPage/ModelDetailPage.styled.tsx
@@ -60,7 +60,7 @@ export const EmptyStateContainer = styled.div`
   align-items: center;
   gap: 1rem;
 
-  margin-top: 3rem;
+  margin: 3rem 0;
 `;
 
 export const EmptyStateTitle = styled.span`
diff --git a/frontend/src/metabase/modes/components/drill/ActionClickDrill/ActionClickDrill.unit.spec.ts b/frontend/src/metabase/modes/components/drill/ActionClickDrill/ActionClickDrill.unit.spec.ts
index ff3d5d346d4334e449b153914e801eea2435fb14..ce184d58d62626eecf7c76bf94d89cda81f81768 100644
--- a/frontend/src/metabase/modes/components/drill/ActionClickDrill/ActionClickDrill.unit.spec.ts
+++ b/frontend/src/metabase/modes/components/drill/ActionClickDrill/ActionClickDrill.unit.spec.ts
@@ -188,7 +188,6 @@ describe("ActionClickDrill", () => {
     const action = createMockQueryAction();
     const dashcard = createMockDashboardActionButton({
       action,
-      action_id: action.id,
     });
     const dashboard = createMockDashboard({
       ordered_cards: [dashcard as unknown as DashboardOrderedCard],
@@ -269,7 +268,6 @@ describe("ActionClickDrill", () => {
 
   it("does nothing for buttons without linked action", () => {
     const dashcard = createMockDashboardActionButton({
-      action_id: null,
       parameter_mappings: [PARAMETER_MAPPING],
     });
     const dashboard = createMockDashboard({
diff --git a/frontend/src/metabase/writeback/components/ActionCreator/ActionCreator.tsx b/frontend/src/metabase/writeback/components/ActionCreator/ActionCreator.tsx
index b2763d9aca8aa0c1560427d1cafe7485ee9432a5..5b56e747252ab691b7e2bb2bbf5e58d104c7a010 100644
--- a/frontend/src/metabase/writeback/components/ActionCreator/ActionCreator.tsx
+++ b/frontend/src/metabase/writeback/components/ActionCreator/ActionCreator.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from "react";
+import React, { useState, useMemo, useEffect } from "react";
 import { t } from "ttag";
 import _ from "underscore";
 import { connect } from "react-redux";
@@ -7,6 +7,7 @@ import { push } from "react-router-redux";
 import Actions from "metabase/entities/actions";
 import { getMetadata } from "metabase/selectors/metadata";
 import { createQuestionFromAction } from "metabase/writeback/selectors";
+
 import type {
   WritebackQueryAction,
   ActionFormSettings,
@@ -66,9 +67,16 @@ function ActionCreatorComponent({
 
   useEffect(() => {
     setQuestion(passedQuestion ?? newQuestion(metadata));
+
     // we do not want to update this any time the props or metadata change, only if action id changes
   }, [actionId]); // eslint-disable-line react-hooks/exhaustive-deps
 
+  const defaultModelId: number | undefined = useMemo(() => {
+    const params = new URLSearchParams(window.location.search);
+    const modelId = params.get("model-id");
+    return modelId ? Number(modelId) : undefined;
+  }, []);
+
   if (!question || !metadata) {
     return null;
   }
@@ -115,7 +123,7 @@ function ActionCreatorComponent({
               id: (question.card() as SavedCard).id,
               name: question.displayName(),
               description: question.description(),
-              collection_id: question.collectionId(),
+              model_id: defaultModelId,
               formSettings,
               question,
             }}
diff --git a/frontend/src/metabase/writeback/components/ActionCreator/FormCreator/utils.ts b/frontend/src/metabase/writeback/components/ActionCreator/FormCreator/utils.ts
index 4a7b5ef31ed38c4ff67da170368c297c8928cbb8..4063313700cc393f8b40f9374336b9dd1b3936f1 100644
--- a/frontend/src/metabase/writeback/components/ActionCreator/FormCreator/utils.ts
+++ b/frontend/src/metabase/writeback/components/ActionCreator/FormCreator/utils.ts
@@ -16,7 +16,7 @@ export const getDefaultFormSettings = (
   overrides: Partial<ActionFormSettings> = {},
 ): ActionFormSettings => ({
   name: "",
-  type: "modal",
+  type: "button",
   description: "",
   fields: {},
   confirmMessage: "",
diff --git a/frontend/src/metabase/writeback/components/ActionViz/Action.tsx b/frontend/src/metabase/writeback/components/ActionViz/Action.tsx
index fd6c39c6f28e4d54f8b297915443237d71782eb9..b5970746efc387fc4f2837249db8abe548090301 100644
--- a/frontend/src/metabase/writeback/components/ActionViz/Action.tsx
+++ b/frontend/src/metabase/writeback/components/ActionViz/Action.tsx
@@ -45,7 +45,7 @@ function ActionComponent({
   const dashcardSettings = dashcard.visualization_settings;
   const actionSettings = dashcard.action?.visualization_settings;
   const actionDisplayType =
-    dashcardSettings?.actionDisplayType ?? actionSettings?.type ?? "modal";
+    dashcardSettings?.actionDisplayType ?? actionSettings?.type ?? "button";
 
   const dashcardParamValues = useMemo(
     () => getDashcardParamValues(dashcard, parameterValues),
@@ -63,7 +63,7 @@ function ActionComponent({
   }, [dashcard, dashcardParamValues]);
 
   const shouldDisplayButton =
-    actionDisplayType !== "inline" || !missingParameters.length;
+    actionDisplayType !== "form" || !missingParameters.length;
 
   const onSubmit = useCallback(
     (parameterMap: ParametersForActionExecution) =>
diff --git a/frontend/src/metabase/writeback/components/ActionViz/ActionViz.tsx b/frontend/src/metabase/writeback/components/ActionViz/ActionViz.tsx
index 605813cbe4435c2127290c606298387081e58ef1..60072ed4819ed22a345f3f8d616dd60317f5a452 100644
--- a/frontend/src/metabase/writeback/components/ActionViz/ActionViz.tsx
+++ b/frontend/src/metabase/writeback/components/ActionViz/ActionViz.tsx
@@ -29,8 +29,8 @@ export default Object.assign(Action, {
       widget: "radio",
       props: {
         options: [
-          { name: t`Inline`, value: "inline" },
-          { name: t`Modal`, value: "modal" },
+          { name: t`Form`, value: "form" },
+          { name: t`Button`, value: "button" },
         ],
       },
     },
diff --git a/frontend/src/metabase/writeback/utils.ts b/frontend/src/metabase/writeback/utils.ts
index 41acafd2886c7094c517443a57c9d93348fd434c..af3e61520f9b3e8f9412539802f1921e2599bb6e 100644
--- a/frontend/src/metabase/writeback/utils.ts
+++ b/frontend/src/metabase/writeback/utils.ts
@@ -115,7 +115,7 @@ export function isImplicitActionButton(
   const isAction = isActionDashCard(dashCard);
   return (
     isAction &&
-    dashCard.action_id == null &&
+    dashCard.action?.type === "implicit" &&
     isValidImplicitActionClickBehavior(
       dashCard.visualization_settings?.click_behavior,
     )
diff --git a/frontend/src/metabase/writeback/utils.unit.spec.ts b/frontend/src/metabase/writeback/utils.unit.spec.ts
index a839db3031f829fa32c9d94b9268411c71fe228d..f04564d8928f7bd13dcfd6e15e3be5598fc673ff 100644
--- a/frontend/src/metabase/writeback/utils.unit.spec.ts
+++ b/frontend/src/metabase/writeback/utils.unit.spec.ts
@@ -1,6 +1,7 @@
 import {
   createMockDashboardActionButton,
   createMockQueryAction,
+  createMockImplictQueryAction,
 } from "metabase-types/api/mocks";
 import type {
   ActionDashboardCard,
@@ -9,7 +10,6 @@ import type {
 import { isMappedExplicitActionButton, isImplicitActionButton } from "./utils";
 
 const PLAIN_BUTTON = createMockDashboardActionButton({
-  action_id: null,
   action: undefined,
   visualization_settings: { click_behavior: undefined },
 });
@@ -17,7 +17,6 @@ const PLAIN_BUTTON = createMockDashboardActionButton({
 const QUERY_ACTION = createMockQueryAction();
 
 const EXPLICIT_ACTION = createMockDashboardActionButton({
-  action_id: QUERY_ACTION.id,
   action: QUERY_ACTION,
   visualization_settings: {
     click_behavior: undefined,
@@ -33,43 +32,27 @@ const PARAMETER_MAPPINGS: ActionParametersMapping[] = [
 ];
 
 const IMPLICIT_INSERT_ACTION = createMockDashboardActionButton({
-  action_id: null,
-  action: undefined,
+  action: createMockImplictQueryAction({ slug: "insert" }),
   visualization_settings: {
-    click_behavior: {
-      type: "action",
-      actionType: "insert",
-      tableId: 5,
-    },
+    action_slug: "insert",
   },
 });
 
 const IMPLICIT_UPDATE_ACTION = createMockDashboardActionButton({
-  action_id: null,
-  action: undefined,
+  action: createMockImplictQueryAction({ slug: "update" }),
   visualization_settings: {
-    click_behavior: {
-      type: "action",
-      actionType: "update",
-      objectDetailDashCardId: 5,
-    },
+    action_slug: "update",
   },
 });
 
 const IMPLICIT_DELETE_ACTION = createMockDashboardActionButton({
-  action_id: null,
-  action: undefined,
+  action: createMockImplictQueryAction({ slug: "delete" }),
   visualization_settings: {
-    click_behavior: {
-      type: "action",
-      actionType: "delete",
-      objectDetailDashCardId: 5,
-    },
+    action_slug: "delete",
   },
 });
 
 const NAVIGATION_ACTION_BUTTON = createMockDashboardActionButton({
-  action_id: null,
   action: undefined,
   visualization_settings: {
     click_behavior: {
@@ -151,7 +134,6 @@ describe("isImplicitActionButton", () => {
 
   it("returns false for implicit action with incomplete shape", () => {
     const insertActionWithoutTableId = createMockDashboardActionButton({
-      action_id: null,
       action: undefined,
       visualization_settings: {
         click_behavior: {
@@ -166,7 +148,6 @@ describe("isImplicitActionButton", () => {
 
   it("returns false for implicit action with unrecognized `actionType`", () => {
     const unrecognizedAction = createMockDashboardActionButton({
-      action_id: null,
       action: undefined,
       visualization_settings: {
         click_behavior: {
@@ -182,8 +163,8 @@ describe("isImplicitActionButton", () => {
   });
 
   IMPLICIT_ACTIONS.forEach(({ action, type }) => {
-    it(`returns true for implicit ${type} action`, () => {
-      expect(isImplicitActionButton(action)).toBe(true);
+    it(`returns false for implicit ${type} action`, () => {
+      expect(isImplicitActionButton(action)).toBe(false);
     });
   });
 });