diff --git a/frontend/src/metabase/query_builder/components/view/View.jsx b/frontend/src/metabase/query_builder/components/view/View.jsx
deleted file mode 100644
index b8e5f2a141347d3369bfabc28beeca785bc43172..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/query_builder/components/view/View.jsx
+++ /dev/null
@@ -1,683 +0,0 @@
-/* eslint-disable react/prop-types */
-
-import { connect } from "react-redux";
-import { match } from "ts-pattern";
-import { t } from "ttag";
-import _ from "underscore";
-
-import { deletePermanently } from "metabase/archive/actions";
-import { ArchivedEntityBanner } from "metabase/archive/components/ArchivedEntityBanner";
-import ExplicitSize from "metabase/components/ExplicitSize";
-import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
-import Toaster from "metabase/components/Toaster";
-import CS from "metabase/css/core/index.css";
-import QueryBuilderS from "metabase/css/query_builder.module.css";
-import Bookmarks from "metabase/entities/bookmarks";
-import Questions from "metabase/entities/questions";
-import {
-  rememberLastUsedDatabase,
-  setArchivedQuestion,
-} from "metabase/query_builder/actions";
-import { SIDEBAR_SIZES } from "metabase/query_builder/constants";
-import { TimeseriesChrome } from "metabase/querying/filters/components/TimeseriesChrome";
-import { MetricEditor } from "metabase/querying/metrics/components/MetricEditor";
-import { Transition } from "metabase/ui";
-import * as Lib from "metabase-lib";
-
-import DatasetEditor from "../DatasetEditor";
-import NativeQueryEditor from "../NativeQueryEditor";
-import { QueryModals } from "../QueryModals";
-import QueryVisualization from "../QueryVisualization";
-import { SavedQuestionIntroModal } from "../SavedQuestionIntroModal";
-import DataReference from "../dataref/DataReference";
-import { SnippetSidebar } from "../template_tags/SnippetSidebar";
-import { TagEditorSidebar } from "../template_tags/TagEditorSidebar";
-
-import NewQuestionHeader from "./NewQuestionHeader";
-import { NotebookContainer } from "./View/NotebookContainer";
-import {
-  BorderedViewTitleHeader,
-  NativeQueryEditorContainer,
-  QueryBuilderContentContainer,
-  QueryBuilderMain,
-  QueryBuilderViewHeaderContainer,
-  QueryBuilderViewRoot,
-  StyledDebouncedFrame,
-  StyledSyncedParametersList,
-} from "./View.styled";
-import { ViewFooter } from "./ViewFooter";
-import ViewSidebar from "./ViewSidebar";
-import { ChartSettingsSidebar } from "./sidebars/ChartSettingsSidebar";
-import { ChartTypeSidebar } from "./sidebars/ChartTypeSidebar";
-import { QuestionInfoSidebar } from "./sidebars/QuestionInfoSidebar";
-import { QuestionSettingsSidebar } from "./sidebars/QuestionSettingsSidebar";
-import { SummarizeSidebar } from "./sidebars/SummarizeSidebar";
-import TimelineSidebar from "./sidebars/TimelineSidebar";
-
-const fadeIn = {
-  in: { opacity: 1 },
-  out: { opacity: 0 },
-  transitionProperty: "opacity",
-};
-
-const ViewHeaderContainer = props => {
-  const { question, onUnarchive, onMove, onDeletePermanently } = props;
-  const query = question.query();
-  const card = question.card();
-  const { isNative } = Lib.queryDisplayInfo(query);
-
-  const isNewQuestion = !isNative && Lib.sourceTableOrCardId(query) === null;
-
-  return (
-    <QueryBuilderViewHeaderContainer>
-      {card.archived && (
-        <ArchivedEntityBanner
-          name={card.name}
-          entityType={card.type}
-          canWrite={card.can_write}
-          canRestore={card.can_restore}
-          canDelete={card.can_delete}
-          onUnarchive={() => onUnarchive(question)}
-          onMove={collection => onMove(question, collection)}
-          onDeletePermanently={() => onDeletePermanently(card.id)}
-        />
-      )}
-
-      <BorderedViewTitleHeader
-        {...props}
-        style={{
-          transition: "opacity 300ms linear",
-          opacity: isNewQuestion ? 0 : 1,
-        }}
-      />
-      {/*This is used so that the New Question Header is unmounted after the animation*/}
-      <Transition mounted={isNewQuestion} transition={fadeIn} duration={300}>
-        {style => <NewQuestionHeader className={CS.spread} style={style} />}
-      </Transition>
-    </QueryBuilderViewHeaderContainer>
-  );
-};
-
-const ViewMainContainer = props => {
-  const {
-    queryBuilderMode,
-    mode,
-    question,
-    showLeftSidebar,
-    showRightSidebar,
-    parameters,
-    setParameterValue,
-    isLiveResizable,
-    updateQuestion,
-  } = props;
-
-  if (queryBuilderMode === "notebook") {
-    // we need to render main only in view mode
-    return;
-  }
-
-  const queryMode = mode && mode.queryMode();
-  const { isNative } = Lib.queryDisplayInfo(question.query());
-  const isSidebarOpen = showLeftSidebar || showRightSidebar;
-
-  return (
-    <QueryBuilderMain
-      isSidebarOpen={isSidebarOpen}
-      data-testid="query-builder-main"
-    >
-      {isNative ? (
-        <ViewNativeQueryEditor {...props} />
-      ) : (
-        <StyledSyncedParametersList
-          parameters={parameters}
-          setParameterValue={setParameterValue}
-          commitImmediately
-        />
-      )}
-
-      <StyledDebouncedFrame enabled={!isLiveResizable}>
-        <QueryVisualization
-          {...props}
-          noHeader
-          className={CS.spread}
-          mode={queryMode}
-        />
-      </StyledDebouncedFrame>
-      <TimeseriesChrome
-        question={question}
-        updateQuestion={updateQuestion}
-        className={CS.flexNoShrink}
-      />
-      <ViewFooter className={CS.flexNoShrink} />
-    </QueryBuilderMain>
-  );
-};
-
-const ViewLeftSidebarContainer = ({
-  question,
-  result,
-  isShowingChartSettingsSidebar,
-  isShowingChartTypeSidebar,
-}) =>
-  match({
-    isShowingChartSettingsSidebar,
-    isShowingChartTypeSidebar,
-  })
-    .with(
-      {
-        isShowingChartSettingsSidebar: true,
-      },
-      () => <ChartSettingsSidebar question={question} result={result} />,
-    )
-    .with(
-      {
-        isShowingChartTypeSidebar: true,
-      },
-      () => <ChartTypeSidebar question={question} result={result} />,
-    )
-    .otherwise(() => null);
-
-const ViewNativeQueryEditor = props => {
-  const {
-    question,
-    height,
-    isDirty,
-    isNativeEditorOpen,
-    card,
-    setParameterValueToDefault,
-    onSetDatabaseId,
-  } = props;
-
-  const legacyQuery = question.legacyQuery();
-
-  // Normally, when users open native models,
-  // they open an ad-hoc GUI question using the model as a data source
-  // (using the `/dataset` endpoint instead of the `/card/:id/query`)
-  // However, users without data permission open a real model as they can't use the `/dataset` endpoint
-  // So the model is opened as an underlying native question and the query editor becomes visible
-  // This check makes it hide the editor in this particular case
-  // More details: https://github.com/metabase/metabase/pull/20161
-  const { isEditable } = Lib.queryDisplayInfo(question.query());
-  if (question.type() === "model" && !isEditable) {
-    return null;
-  }
-
-  return (
-    <NativeQueryEditorContainer>
-      <NativeQueryEditor
-        {...props}
-        query={legacyQuery}
-        viewHeight={height}
-        isOpen={legacyQuery.isEmpty() || isDirty}
-        isInitiallyOpen={isNativeEditorOpen}
-        datasetQuery={card && card.dataset_query}
-        setParameterValueToDefault={setParameterValueToDefault}
-        onSetDatabaseId={onSetDatabaseId}
-      />
-    </NativeQueryEditorContainer>
-  );
-};
-
-const ViewRightSidebarContainer = props => {
-  const {
-    question,
-    deselectTimelineEvents,
-    hideTimelineEvents,
-    isShowingQuestionInfoSidebar,
-    isShowingQuestionSettingsSidebar,
-    isShowingSummarySidebar,
-    isShowingTimelineSidebar,
-    onCloseQuestionInfo,
-    onCloseSummary,
-    onCloseTimelines,
-    onOpenModal,
-    onSave,
-    selectTimelineEvents,
-    selectedTimelineEventIds,
-    showTimelineEvents,
-    timelines,
-    updateQuestion,
-    visibleTimelineEventIds,
-    xDomain,
-  } = props;
-
-  const { isNative } = Lib.queryDisplayInfo(question.query());
-
-  return !isNative ? (
-    <StructuredQueryRightSidebar
-      deselectTimelineEvents={deselectTimelineEvents}
-      hideTimelineEvents={hideTimelineEvents}
-      isShowingQuestionInfoSidebar={isShowingQuestionInfoSidebar}
-      isShowingQuestionSettingsSidebar={isShowingQuestionSettingsSidebar}
-      isShowingSummarySidebar={isShowingSummarySidebar}
-      isShowingTimelineSidebar={isShowingTimelineSidebar}
-      onCloseQuestionInfo={onCloseQuestionInfo}
-      onCloseSummary={onCloseSummary}
-      onCloseTimelines={onCloseTimelines}
-      onOpenModal={onOpenModal}
-      onSave={onSave}
-      question={question}
-      selectTimelineEvents={selectTimelineEvents}
-      selectedTimelineEventIds={selectedTimelineEventIds}
-      showTimelineEvents={showTimelineEvents}
-      timelines={timelines}
-      updateQuestion={updateQuestion}
-      visibleTimelineEventIds={visibleTimelineEventIds}
-      xDomain={xDomain}
-    />
-  ) : (
-    <NativeQueryRightSidebar {...props} />
-  );
-};
-
-const StructuredQueryRightSidebar = ({
-  deselectTimelineEvents,
-  hideTimelineEvents,
-  isShowingQuestionInfoSidebar,
-  isShowingQuestionSettingsSidebar,
-  isShowingSummarySidebar,
-  isShowingTimelineSidebar,
-  onCloseQuestionInfo,
-  onCloseSummary,
-  onCloseTimelines,
-  onOpenModal,
-  onSave,
-  question,
-  selectTimelineEvents,
-  selectedTimelineEventIds,
-  showTimelineEvents,
-  timelines,
-  updateQuestion,
-  visibleTimelineEventIds,
-  xDomain,
-}) =>
-  match({
-    isSaved: question.isSaved(),
-    isShowingSummarySidebar,
-    isShowingTimelineSidebar,
-    isShowingQuestionInfoSidebar,
-    isShowingQuestionSettingsSidebar,
-  })
-    .with(
-      {
-        isShowingSummarySidebar: true,
-      },
-      () => (
-        <SummarizeSidebar
-          query={question.query()}
-          onQueryChange={nextQuery => {
-            const datesetQuery = Lib.toLegacyQuery(nextQuery);
-            const nextQuestion = question.setDatasetQuery(datesetQuery);
-            updateQuestion(nextQuestion.setDefaultDisplay(), {
-              run: true,
-            });
-          }}
-          onClose={onCloseSummary}
-        />
-      ),
-    )
-    .with({ isShowingTimelineSidebar: true }, () => (
-      <TimelineSidebar
-        question={question}
-        timelines={timelines}
-        visibleTimelineEventIds={visibleTimelineEventIds}
-        selectedTimelineEventIds={selectedTimelineEventIds}
-        xDomain={xDomain}
-        onShowTimelineEvents={showTimelineEvents}
-        onHideTimelineEvents={hideTimelineEvents}
-        onSelectTimelineEvents={selectTimelineEvents}
-        onDeselectTimelineEvents={deselectTimelineEvents}
-        onOpenModal={onOpenModal}
-        onClose={onCloseTimelines}
-      />
-    ))
-    .with(
-      {
-        isSaved: true,
-        isShowingQuestionInfoSidebar: true,
-      },
-      () => (
-        <QuestionInfoSidebar
-          question={question}
-          onSave={onSave}
-          onClose={onCloseQuestionInfo}
-        />
-      ),
-    )
-    .with(
-      {
-        isSaved: true,
-        isShowingQuestionSettingsSidebar: true,
-      },
-      () => <QuestionSettingsSidebar question={question} />,
-    )
-    .otherwise(() => null);
-
-const NativeQueryRightSidebar = props => {
-  const {
-    question,
-    toggleTemplateTagsEditor,
-    toggleDataReference,
-    toggleSnippetSidebar,
-    showTimelineEvent,
-    showTimelineEvents,
-    hideTimelineEvents,
-    selectTimelineEvents,
-    deselectTimelineEvents,
-    onCloseTimelines,
-    onSave,
-    onCloseQuestionInfo,
-    isShowingTemplateTagsEditor,
-    isShowingDataReference,
-    isShowingSnippetSidebar,
-    isShowingTimelineSidebar,
-    isShowingQuestionInfoSidebar,
-    isShowingQuestionSettingsSidebar,
-  } = props;
-
-  return match({
-    isShowingTemplateTagsEditor,
-    isShowingDataReference,
-    isShowingSnippetSidebar,
-    isShowingTimelineSidebar,
-    isShowingQuestionInfoSidebar,
-    isShowingQuestionSettingsSidebar,
-  })
-    .with({ isShowingTemplateTagsEditor: true }, () => (
-      <TagEditorSidebar
-        {...props}
-        query={question.legacyQuery()}
-        onClose={toggleTemplateTagsEditor}
-      />
-    ))
-    .with({ isShowingDataReference: true }, () => (
-      <DataReference {...props} onClose={toggleDataReference} />
-    ))
-    .with({ isShowingSnippetSidebar: true }, () => (
-      <SnippetSidebar {...props} onClose={toggleSnippetSidebar} />
-    ))
-    .with({ isShowingTimelineSidebar: true }, () => (
-      <TimelineSidebar
-        {...props}
-        onShowTimelineEvent={showTimelineEvent}
-        onShowTimelineEvents={showTimelineEvents}
-        onHideTimelineEvents={hideTimelineEvents}
-        onSelectTimelineEvents={selectTimelineEvents}
-        onDeselectTimelineEvents={deselectTimelineEvents}
-        onClose={onCloseTimelines}
-      />
-    ))
-    .with({ isShowingQuestionInfoSidebar: true }, () => (
-      <QuestionInfoSidebar
-        question={question}
-        onSave={onSave}
-        onClose={onCloseQuestionInfo}
-      />
-    ))
-    .with({ isShowingQuestionSettingsSidebar: true }, () => (
-      <QuestionSettingsSidebar question={question} />
-    ))
-    .otherwise(() => null);
-};
-
-const View = props => {
-  const {
-    question,
-    result,
-    rawSeries,
-    databases,
-    isShowingNewbModal,
-    isShowingTimelineSidebar,
-    queryBuilderMode,
-    closeQbNewbModal,
-    onDismissToast,
-    onConfirmToast,
-    isShowingToaster,
-    isHeaderVisible,
-    updateQuestion,
-    reportTimezone,
-    readOnly,
-    isDirty,
-    isRunning,
-    isRunnable,
-    isResultDirty,
-    hasVisualizeButton,
-    runQuestionQuery,
-    cancelQuery,
-    setQueryBuilderMode,
-    runDirtyQuestionQuery,
-    isShowingQuestionInfoSidebar,
-    isShowingQuestionSettingsSidebar,
-    cancelQuestionChanges,
-    onCreate,
-    onSave,
-    onChangeLocation,
-    questionAlerts,
-    user,
-    modal,
-    modalContext,
-    card,
-    onCloseModal,
-    onOpenModal,
-    originalQuestion,
-    isShowingChartSettingsSidebar,
-    isShowingChartTypeSidebar,
-    onCloseChartSettings,
-    addField,
-    initialChartSetting,
-    onReplaceAllVisualizationSettings,
-    onOpenChartType,
-    visualizationSettings,
-    showSidebarTitle,
-    isShowingSummarySidebar,
-    isShowingTemplateTagsEditor,
-    isShowingDataReference,
-    isShowingSnippetSidebar,
-  } = props;
-
-  // if we don't have a question at all or no databases then we are initializing, so keep it simple
-  if (!question || !databases) {
-    return <LoadingAndErrorWrapper className={CS.fullHeight} loading />;
-  }
-
-  const query = question.query();
-  const { isNative } = Lib.queryDisplayInfo(question.query());
-
-  const isNewQuestion = !isNative && Lib.sourceTableOrCardId(query) === null;
-  const isModel = question.type() === "model";
-  const isMetric = question.type() === "metric";
-
-  if ((isModel || isMetric) && queryBuilderMode === "dataset") {
-    return (
-      <>
-        {isModel && <DatasetEditor {...props} />}
-        {isMetric && (
-          <MetricEditor
-            question={question}
-            result={result}
-            rawSeries={rawSeries}
-            reportTimezone={reportTimezone}
-            isDirty={isDirty}
-            isResultDirty={isResultDirty}
-            isRunning={isRunning}
-            onChange={updateQuestion}
-            onCreate={async question => {
-              await onCreate(question);
-              setQueryBuilderMode("view");
-            }}
-            onSave={async question => {
-              await onSave(question);
-              setQueryBuilderMode("view");
-            }}
-            onCancel={question => {
-              if (question.isSaved()) {
-                cancelQuestionChanges();
-                runDirtyQuestionQuery();
-                setQueryBuilderMode("view");
-              } else {
-                onChangeLocation("/");
-              }
-            }}
-            onRunQuery={runQuestionQuery}
-            onCancelQuery={cancelQuery}
-          />
-        )}
-        <QueryModals
-          questionAlerts={questionAlerts}
-          user={user}
-          onSave={onSave}
-          onCreate={onCreate}
-          updateQuestion={updateQuestion}
-          modal={modal}
-          modalContext={modalContext}
-          card={card}
-          question={question}
-          onCloseModal={onCloseModal}
-          onOpenModal={onOpenModal}
-          setQueryBuilderMode={setQueryBuilderMode}
-          originalQuestion={originalQuestion}
-          onChangeLocation={onChangeLocation}
-        />
-      </>
-    );
-  }
-
-  const isNotebookContainerOpen =
-    isNewQuestion || queryBuilderMode === "notebook";
-
-  const showLeftSidebar =
-    isShowingChartSettingsSidebar || isShowingChartTypeSidebar;
-  const showRightSidebar =
-    isShowingTimelineSidebar ||
-    isShowingQuestionInfoSidebar ||
-    isShowingQuestionSettingsSidebar ||
-    (!isNative && isShowingSummarySidebar) ||
-    (isNative &&
-      (isShowingTemplateTagsEditor ||
-        isShowingDataReference ||
-        isShowingSnippetSidebar));
-
-  const rightSidebarWidth = match({
-    isShowingTimelineSidebar,
-    isShowingQuestionInfoSidebar,
-    isShowingQuestionSettingsSidebar,
-  })
-    .with({ isShowingTimelineSidebar: true }, () => SIDEBAR_SIZES.TIMELINE)
-    .with({ isShowingQuestionInfoSidebar: true }, () => 0)
-    .with({ isShowingQuestionSettingsSidebar: true }, () => 0)
-    .otherwise(() => SIDEBAR_SIZES.NORMAL);
-
-  return (
-    <div className={CS.fullHeight}>
-      <QueryBuilderViewRoot
-        className={QueryBuilderS.QueryBuilder}
-        data-testid="query-builder-root"
-      >
-        {isHeaderVisible && <ViewHeaderContainer {...props} />}
-
-        <QueryBuilderContentContainer>
-          {!isNative && (
-            <NotebookContainer
-              isOpen={isNotebookContainerOpen}
-              updateQuestion={updateQuestion}
-              reportTimezone={reportTimezone}
-              readOnly={readOnly}
-              question={question}
-              isDirty={isDirty}
-              isRunnable={isRunnable}
-              isResultDirty={isResultDirty}
-              hasVisualizeButton={hasVisualizeButton}
-              runQuestionQuery={runQuestionQuery}
-              setQueryBuilderMode={setQueryBuilderMode}
-            />
-          )}
-          <ViewSidebar side="left" isOpen={showLeftSidebar}>
-            <ViewLeftSidebarContainer
-              question={question}
-              result={result}
-              isShowingChartSettingsSidebar={isShowingChartSettingsSidebar}
-              isShowingChartTypeSidebar={isShowingChartTypeSidebar}
-              onCloseChartSettings={onCloseChartSettings}
-              addField={addField}
-              initialChartSetting={initialChartSetting}
-              onReplaceAllVisualizationSettings={
-                onReplaceAllVisualizationSettings
-              }
-              onOpenChartType={onOpenChartType}
-              visualizationSettings={visualizationSettings}
-              showSidebarTitle={showSidebarTitle}
-            />
-          </ViewSidebar>
-          <ViewMainContainer
-            showLeftSidebar={showLeftSidebar}
-            showRightSidebar={showRightSidebar}
-            {...props}
-          />
-          <ViewSidebar
-            side="right"
-            isOpen={showRightSidebar}
-            width={rightSidebarWidth}
-          >
-            <ViewRightSidebarContainer {...props} />
-          </ViewSidebar>
-        </QueryBuilderContentContainer>
-      </QueryBuilderViewRoot>
-
-      {isShowingNewbModal && (
-        <SavedQuestionIntroModal
-          question={question}
-          isShowingNewbModal={isShowingNewbModal}
-          onClose={() => closeQbNewbModal()}
-        />
-      )}
-
-      <QueryModals
-        questionAlerts={questionAlerts}
-        user={user}
-        onSave={onSave}
-        onCreate={onCreate}
-        updateQuestion={updateQuestion}
-        modal={modal}
-        modalContext={modalContext}
-        card={card}
-        question={question}
-        onCloseModal={onCloseModal}
-        onOpenModal={onOpenModal}
-        setQueryBuilderMode={setQueryBuilderMode}
-        originalQuestion={originalQuestion}
-        onChangeLocation={onChangeLocation}
-      />
-
-      <Toaster
-        message={t`Would you like to be notified when this question is done loading?`}
-        isShown={isShowingToaster}
-        onDismiss={onDismissToast}
-        onConfirm={onConfirmToast}
-        fixed
-      />
-    </div>
-  );
-};
-
-const mapDispatchToProps = dispatch => ({
-  onSetDatabaseId: id => dispatch(rememberLastUsedDatabase(id)),
-  onUnarchive: async question => {
-    await dispatch(setArchivedQuestion(question, false));
-    await dispatch(Bookmarks.actions.invalidateLists());
-  },
-  onMove: (question, newCollection) =>
-    dispatch(
-      Questions.actions.setCollection({ id: question.id() }, newCollection, {
-        notify: { undo: false },
-      }),
-    ),
-  onDeletePermanently: id => {
-    const deleteAction = Questions.actions.delete({ id });
-    dispatch(deletePermanently(deleteAction));
-  },
-});
-
-export default _.compose(
-  ExplicitSize({ refreshMode: "debounceLeading" }),
-  connect(null, mapDispatchToProps),
-)(View);
diff --git a/frontend/src/metabase/query_builder/components/view/View/NativeQueryRightSidebar/NativeQueryRightSidebar.jsx b/frontend/src/metabase/query_builder/components/view/View/NativeQueryRightSidebar/NativeQueryRightSidebar.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..6703edbb6acc6949d9f092f210509cd1f2b5e1e9
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/NativeQueryRightSidebar/NativeQueryRightSidebar.jsx
@@ -0,0 +1,75 @@
+import { match } from "ts-pattern";
+
+import DataReference from "metabase/query_builder/components/dataref/DataReference";
+import { SnippetSidebar } from "metabase/query_builder/components/template_tags/SnippetSidebar";
+import { TagEditorSidebar } from "metabase/query_builder/components/template_tags/TagEditorSidebar";
+import { QuestionInfoSidebar } from "metabase/query_builder/components/view/sidebars/QuestionInfoSidebar";
+import { QuestionSettingsSidebar } from "metabase/query_builder/components/view/sidebars/QuestionSettingsSidebar";
+import TimelineSidebar from "metabase/query_builder/components/view/sidebars/TimelineSidebar";
+
+export const NativeQueryRightSidebar = props => {
+  const {
+    question,
+    toggleTemplateTagsEditor,
+    toggleDataReference,
+    toggleSnippetSidebar,
+    showTimelineEvent,
+    showTimelineEvents,
+    hideTimelineEvents,
+    selectTimelineEvents,
+    deselectTimelineEvents,
+    onCloseTimelines,
+    onSave,
+    onCloseQuestionInfo,
+    isShowingTemplateTagsEditor,
+    isShowingDataReference,
+    isShowingSnippetSidebar,
+    isShowingTimelineSidebar,
+    isShowingQuestionInfoSidebar,
+    isShowingQuestionSettingsSidebar,
+  } = props;
+
+  return match({
+    isShowingTemplateTagsEditor,
+    isShowingDataReference,
+    isShowingSnippetSidebar,
+    isShowingTimelineSidebar,
+    isShowingQuestionInfoSidebar,
+    isShowingQuestionSettingsSidebar,
+  })
+    .with({ isShowingTemplateTagsEditor: true }, () => (
+      <TagEditorSidebar
+        {...props}
+        query={question.legacyQuery()}
+        onClose={toggleTemplateTagsEditor}
+      />
+    ))
+    .with({ isShowingDataReference: true }, () => (
+      <DataReference {...props} onClose={toggleDataReference} />
+    ))
+    .with({ isShowingSnippetSidebar: true }, () => (
+      <SnippetSidebar {...props} onClose={toggleSnippetSidebar} />
+    ))
+    .with({ isShowingTimelineSidebar: true }, () => (
+      <TimelineSidebar
+        {...props}
+        onShowTimelineEvent={showTimelineEvent}
+        onShowTimelineEvents={showTimelineEvents}
+        onHideTimelineEvents={hideTimelineEvents}
+        onSelectTimelineEvents={selectTimelineEvents}
+        onDeselectTimelineEvents={deselectTimelineEvents}
+        onClose={onCloseTimelines}
+      />
+    ))
+    .with({ isShowingQuestionInfoSidebar: true }, () => (
+      <QuestionInfoSidebar
+        question={question}
+        onSave={onSave}
+        onClose={onCloseQuestionInfo}
+      />
+    ))
+    .with({ isShowingQuestionSettingsSidebar: true }, () => (
+      <QuestionSettingsSidebar question={question} />
+    ))
+    .otherwise(() => null);
+};
diff --git a/frontend/src/metabase/query_builder/components/view/View/NativeQueryRightSidebar/index.ts b/frontend/src/metabase/query_builder/components/view/View/NativeQueryRightSidebar/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..088735e9c65f315d40e99095e3b843081ed2ab30
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/NativeQueryRightSidebar/index.ts
@@ -0,0 +1 @@
+export * from "./NativeQueryRightSidebar";
diff --git a/frontend/src/metabase/query_builder/components/view/View/StructuredQueryRightSidebar/StructuredQueryRightSidebar.jsx b/frontend/src/metabase/query_builder/components/view/View/StructuredQueryRightSidebar/StructuredQueryRightSidebar.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..4059af6a1d703544b53bdfca73d1ce20cd85f709
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/StructuredQueryRightSidebar/StructuredQueryRightSidebar.jsx
@@ -0,0 +1,90 @@
+import { match } from "ts-pattern";
+
+import { QuestionInfoSidebar } from "metabase/query_builder/components/view/sidebars/QuestionInfoSidebar";
+import { QuestionSettingsSidebar } from "metabase/query_builder/components/view/sidebars/QuestionSettingsSidebar";
+import { SummarizeSidebar } from "metabase/query_builder/components/view/sidebars/SummarizeSidebar";
+import TimelineSidebar from "metabase/query_builder/components/view/sidebars/TimelineSidebar";
+import * as Lib from "metabase-lib";
+
+export const StructuredQueryRightSidebar = ({
+  deselectTimelineEvents,
+  hideTimelineEvents,
+  isShowingQuestionInfoSidebar,
+  isShowingQuestionSettingsSidebar,
+  isShowingSummarySidebar,
+  isShowingTimelineSidebar,
+  onCloseQuestionInfo,
+  onCloseSummary,
+  onCloseTimelines,
+  onOpenModal,
+  onSave,
+  question,
+  selectTimelineEvents,
+  selectedTimelineEventIds,
+  showTimelineEvents,
+  timelines,
+  updateQuestion,
+  visibleTimelineEventIds,
+  xDomain,
+}) =>
+  match({
+    isSaved: question.isSaved(),
+    isShowingSummarySidebar,
+    isShowingTimelineSidebar,
+    isShowingQuestionInfoSidebar,
+    isShowingQuestionSettingsSidebar,
+  })
+    .with(
+      {
+        isShowingSummarySidebar: true,
+      },
+      () => (
+        <SummarizeSidebar
+          query={question.query()}
+          onQueryChange={nextQuery => {
+            const datesetQuery = Lib.toLegacyQuery(nextQuery);
+            const nextQuestion = question.setDatasetQuery(datesetQuery);
+            updateQuestion(nextQuestion.setDefaultDisplay(), {
+              run: true,
+            });
+          }}
+          onClose={onCloseSummary}
+        />
+      ),
+    )
+    .with({ isShowingTimelineSidebar: true }, () => (
+      <TimelineSidebar
+        question={question}
+        timelines={timelines}
+        visibleTimelineEventIds={visibleTimelineEventIds}
+        selectedTimelineEventIds={selectedTimelineEventIds}
+        xDomain={xDomain}
+        onShowTimelineEvents={showTimelineEvents}
+        onHideTimelineEvents={hideTimelineEvents}
+        onSelectTimelineEvents={selectTimelineEvents}
+        onDeselectTimelineEvents={deselectTimelineEvents}
+        onOpenModal={onOpenModal}
+        onClose={onCloseTimelines}
+      />
+    ))
+    .with(
+      {
+        isSaved: true,
+        isShowingQuestionInfoSidebar: true,
+      },
+      () => (
+        <QuestionInfoSidebar
+          question={question}
+          onSave={onSave}
+          onClose={onCloseQuestionInfo}
+        />
+      ),
+    )
+    .with(
+      {
+        isSaved: true,
+        isShowingQuestionSettingsSidebar: true,
+      },
+      () => <QuestionSettingsSidebar question={question} />,
+    )
+    .otherwise(() => null);
diff --git a/frontend/src/metabase/query_builder/components/view/View/StructuredQueryRightSidebar/index.ts b/frontend/src/metabase/query_builder/components/view/View/StructuredQueryRightSidebar/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e200a841afee03a624e3b3a7ceeba31b45eae064
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/StructuredQueryRightSidebar/index.ts
@@ -0,0 +1 @@
+export * from "./StructuredQueryRightSidebar";
diff --git a/frontend/src/metabase/query_builder/components/view/View/View.jsx b/frontend/src/metabase/query_builder/components/view/View/View.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..2d77fc00a51f7adbcb58a29d0d18713f1bf64422
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/View.jsx
@@ -0,0 +1,299 @@
+/* eslint-disable react/prop-types */
+
+import { connect } from "react-redux";
+import { match } from "ts-pattern";
+import { t } from "ttag";
+import _ from "underscore";
+
+import { deletePermanently } from "metabase/archive/actions";
+import ExplicitSize from "metabase/components/ExplicitSize";
+import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
+import Toaster from "metabase/components/Toaster";
+import CS from "metabase/css/core/index.css";
+import QueryBuilderS from "metabase/css/query_builder.module.css";
+import Bookmarks from "metabase/entities/bookmarks";
+import Questions from "metabase/entities/questions";
+import {
+  rememberLastUsedDatabase,
+  setArchivedQuestion,
+} from "metabase/query_builder/actions";
+import { ViewHeaderContainer } from "metabase/query_builder/components/view/View/ViewHeaderContainer/ViewHeaderContainer";
+import { ViewLeftSidebarContainer } from "metabase/query_builder/components/view/View/ViewLeftSidebarContainer/ViewLeftSidebarContainer";
+import { ViewMainContainer } from "metabase/query_builder/components/view/View/ViewMainContainer/ViewMainContainer";
+import { ViewRightSidebarContainer } from "metabase/query_builder/components/view/View/ViewRightSidebarContainer/ViewRightSidebarContainer";
+import { SIDEBAR_SIZES } from "metabase/query_builder/constants";
+import { MetricEditor } from "metabase/querying/metrics/components/MetricEditor";
+import * as Lib from "metabase-lib";
+
+import DatasetEditor from "../../DatasetEditor";
+import { QueryModals } from "../../QueryModals";
+import { SavedQuestionIntroModal } from "../../SavedQuestionIntroModal";
+import ViewSidebar from "../ViewSidebar";
+
+import { NotebookContainer } from "./NotebookContainer";
+import {
+  QueryBuilderContentContainer,
+  QueryBuilderViewRoot,
+} from "./View.styled";
+
+const ViewInner = props => {
+  const {
+    question,
+    result,
+    rawSeries,
+    databases,
+    isShowingNewbModal,
+    isShowingTimelineSidebar,
+    queryBuilderMode,
+    closeQbNewbModal,
+    onDismissToast,
+    onConfirmToast,
+    isShowingToaster,
+    isHeaderVisible,
+    updateQuestion,
+    reportTimezone,
+    readOnly,
+    isDirty,
+    isRunning,
+    isRunnable,
+    isResultDirty,
+    hasVisualizeButton,
+    runQuestionQuery,
+    cancelQuery,
+    setQueryBuilderMode,
+    runDirtyQuestionQuery,
+    isShowingQuestionInfoSidebar,
+    isShowingQuestionSettingsSidebar,
+    cancelQuestionChanges,
+    onCreate,
+    onSave,
+    onChangeLocation,
+    questionAlerts,
+    user,
+    modal,
+    modalContext,
+    card,
+    onCloseModal,
+    onOpenModal,
+    originalQuestion,
+    isShowingChartSettingsSidebar,
+    isShowingChartTypeSidebar,
+    onCloseChartSettings,
+    addField,
+    initialChartSetting,
+    onReplaceAllVisualizationSettings,
+    onOpenChartType,
+    visualizationSettings,
+    showSidebarTitle,
+    isShowingSummarySidebar,
+    isShowingTemplateTagsEditor,
+    isShowingDataReference,
+    isShowingSnippetSidebar,
+  } = props;
+
+  // if we don't have a question at all or no databases then we are initializing, so keep it simple
+  if (!question || !databases) {
+    return <LoadingAndErrorWrapper className={CS.fullHeight} loading />;
+  }
+
+  const query = question.query();
+  const { isNative } = Lib.queryDisplayInfo(question.query());
+
+  const isNewQuestion = !isNative && Lib.sourceTableOrCardId(query) === null;
+  const isModel = question.type() === "model";
+  const isMetric = question.type() === "metric";
+
+  if ((isModel || isMetric) && queryBuilderMode === "dataset") {
+    return (
+      <>
+        {isModel && <DatasetEditor {...props} />}
+        {isMetric && (
+          <MetricEditor
+            question={question}
+            result={result}
+            rawSeries={rawSeries}
+            reportTimezone={reportTimezone}
+            isDirty={isDirty}
+            isResultDirty={isResultDirty}
+            isRunning={isRunning}
+            onChange={updateQuestion}
+            onCreate={async question => {
+              await onCreate(question);
+              setQueryBuilderMode("view");
+            }}
+            onSave={async question => {
+              await onSave(question);
+              setQueryBuilderMode("view");
+            }}
+            onCancel={question => {
+              if (question.isSaved()) {
+                cancelQuestionChanges();
+                runDirtyQuestionQuery();
+                setQueryBuilderMode("view");
+              } else {
+                onChangeLocation("/");
+              }
+            }}
+            onRunQuery={runQuestionQuery}
+            onCancelQuery={cancelQuery}
+          />
+        )}
+        <QueryModals
+          questionAlerts={questionAlerts}
+          user={user}
+          onSave={onSave}
+          onCreate={onCreate}
+          updateQuestion={updateQuestion}
+          modal={modal}
+          modalContext={modalContext}
+          card={card}
+          question={question}
+          onCloseModal={onCloseModal}
+          onOpenModal={onOpenModal}
+          setQueryBuilderMode={setQueryBuilderMode}
+          originalQuestion={originalQuestion}
+          onChangeLocation={onChangeLocation}
+        />
+      </>
+    );
+  }
+
+  const isNotebookContainerOpen =
+    isNewQuestion || queryBuilderMode === "notebook";
+
+  const showLeftSidebar =
+    isShowingChartSettingsSidebar || isShowingChartTypeSidebar;
+  const showRightSidebar =
+    isShowingTimelineSidebar ||
+    isShowingQuestionInfoSidebar ||
+    isShowingQuestionSettingsSidebar ||
+    (!isNative && isShowingSummarySidebar) ||
+    (isNative &&
+      (isShowingTemplateTagsEditor ||
+        isShowingDataReference ||
+        isShowingSnippetSidebar));
+
+  const rightSidebarWidth = match({
+    isShowingTimelineSidebar,
+    isShowingQuestionInfoSidebar,
+    isShowingQuestionSettingsSidebar,
+  })
+    .with({ isShowingTimelineSidebar: true }, () => SIDEBAR_SIZES.TIMELINE)
+    .with({ isShowingQuestionInfoSidebar: true }, () => 0)
+    .with({ isShowingQuestionSettingsSidebar: true }, () => 0)
+    .otherwise(() => SIDEBAR_SIZES.NORMAL);
+
+  return (
+    <div className={CS.fullHeight}>
+      <QueryBuilderViewRoot
+        className={QueryBuilderS.QueryBuilder}
+        data-testid="query-builder-root"
+      >
+        {isHeaderVisible && <ViewHeaderContainer {...props} />}
+
+        <QueryBuilderContentContainer>
+          {!isNative && (
+            <NotebookContainer
+              isOpen={isNotebookContainerOpen}
+              updateQuestion={updateQuestion}
+              reportTimezone={reportTimezone}
+              readOnly={readOnly}
+              question={question}
+              isDirty={isDirty}
+              isRunnable={isRunnable}
+              isResultDirty={isResultDirty}
+              hasVisualizeButton={hasVisualizeButton}
+              runQuestionQuery={runQuestionQuery}
+              setQueryBuilderMode={setQueryBuilderMode}
+            />
+          )}
+          <ViewSidebar side="left" isOpen={showLeftSidebar}>
+            <ViewLeftSidebarContainer
+              question={question}
+              result={result}
+              isShowingChartSettingsSidebar={isShowingChartSettingsSidebar}
+              isShowingChartTypeSidebar={isShowingChartTypeSidebar}
+              onCloseChartSettings={onCloseChartSettings}
+              addField={addField}
+              initialChartSetting={initialChartSetting}
+              onReplaceAllVisualizationSettings={
+                onReplaceAllVisualizationSettings
+              }
+              onOpenChartType={onOpenChartType}
+              visualizationSettings={visualizationSettings}
+              showSidebarTitle={showSidebarTitle}
+            />
+          </ViewSidebar>
+          <ViewMainContainer
+            showLeftSidebar={showLeftSidebar}
+            showRightSidebar={showRightSidebar}
+            {...props}
+          />
+          <ViewSidebar
+            side="right"
+            isOpen={showRightSidebar}
+            width={rightSidebarWidth}
+          >
+            <ViewRightSidebarContainer {...props} />
+          </ViewSidebar>
+        </QueryBuilderContentContainer>
+      </QueryBuilderViewRoot>
+
+      {isShowingNewbModal && (
+        <SavedQuestionIntroModal
+          question={question}
+          isShowingNewbModal={isShowingNewbModal}
+          onClose={() => closeQbNewbModal()}
+        />
+      )}
+
+      <QueryModals
+        questionAlerts={questionAlerts}
+        user={user}
+        onSave={onSave}
+        onCreate={onCreate}
+        updateQuestion={updateQuestion}
+        modal={modal}
+        modalContext={modalContext}
+        card={card}
+        question={question}
+        onCloseModal={onCloseModal}
+        onOpenModal={onOpenModal}
+        setQueryBuilderMode={setQueryBuilderMode}
+        originalQuestion={originalQuestion}
+        onChangeLocation={onChangeLocation}
+      />
+
+      <Toaster
+        message={t`Would you like to be notified when this question is done loading?`}
+        isShown={isShowingToaster}
+        onDismiss={onDismissToast}
+        onConfirm={onConfirmToast}
+        fixed
+      />
+    </div>
+  );
+};
+
+const mapDispatchToProps = dispatch => ({
+  onSetDatabaseId: id => dispatch(rememberLastUsedDatabase(id)),
+  onUnarchive: async question => {
+    await dispatch(setArchivedQuestion(question, false));
+    await dispatch(Bookmarks.actions.invalidateLists());
+  },
+  onMove: (question, newCollection) =>
+    dispatch(
+      Questions.actions.setCollection({ id: question.id() }, newCollection, {
+        notify: { undo: false },
+      }),
+    ),
+  onDeletePermanently: id => {
+    const deleteAction = Questions.actions.delete({ id });
+    dispatch(deletePermanently(deleteAction));
+  },
+});
+
+export const View = _.compose(
+  ExplicitSize({ refreshMode: "debounceLeading" }),
+  connect(null, mapDispatchToProps),
+)(ViewInner);
diff --git a/frontend/src/metabase/query_builder/components/view/View.styled.tsx b/frontend/src/metabase/query_builder/components/view/View/View.styled.tsx
similarity index 97%
rename from frontend/src/metabase/query_builder/components/view/View.styled.tsx
rename to frontend/src/metabase/query_builder/components/view/View/View.styled.tsx
index 5163cb765052280b3290a60031f0325964ec7a45..c4d4978f2b51679b3c7e51b722c08075a919c700 100644
--- a/frontend/src/metabase/query_builder/components/view/View.styled.tsx
+++ b/frontend/src/metabase/query_builder/components/view/View/View.styled.tsx
@@ -5,7 +5,7 @@ import DebouncedFrame from "metabase/components/DebouncedFrame";
 import { SyncedParametersList } from "metabase/query_builder/components/SyncedParametersList";
 import { breakpointMaxSmall } from "metabase/styled-components/theme/media-queries";
 
-import { ViewTitleHeader } from "./ViewHeader";
+import { ViewTitleHeader } from "../ViewHeader";
 
 export const QueryBuilderViewRoot = styled.div`
   display: flex;
diff --git a/frontend/src/metabase/query_builder/components/view/View/ViewHeaderContainer/ViewHeaderContainer.jsx b/frontend/src/metabase/query_builder/components/view/View/ViewHeaderContainer/ViewHeaderContainer.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..d3aaad00943bb1b6d225471eb3aa2ef77067a46e
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/ViewHeaderContainer/ViewHeaderContainer.jsx
@@ -0,0 +1,53 @@
+/* eslint-disable react/prop-types */
+import { ArchivedEntityBanner } from "metabase/archive/components/ArchivedEntityBanner";
+import CS from "metabase/css/core/index.css";
+import NewQuestionHeader from "metabase/query_builder/components/view/NewQuestionHeader";
+import {
+  BorderedViewTitleHeader,
+  QueryBuilderViewHeaderContainer,
+} from "metabase/query_builder/components/view/View/View.styled";
+import { Transition } from "metabase/ui";
+import * as Lib from "metabase-lib";
+
+const fadeIn = {
+  in: { opacity: 1 },
+  out: { opacity: 0 },
+  transitionProperty: "opacity",
+};
+export const ViewHeaderContainer = props => {
+  const { question, onUnarchive, onMove, onDeletePermanently } = props;
+  const query = question.query();
+  const card = question.card();
+  const { isNative } = Lib.queryDisplayInfo(query);
+
+  const isNewQuestion = !isNative && Lib.sourceTableOrCardId(query) === null;
+
+  return (
+    <QueryBuilderViewHeaderContainer>
+      {card.archived && (
+        <ArchivedEntityBanner
+          name={card.name}
+          entityType={card.type}
+          canWrite={card.can_write}
+          canRestore={card.can_restore}
+          canDelete={card.can_delete}
+          onUnarchive={() => onUnarchive(question)}
+          onMove={collection => onMove(question, collection)}
+          onDeletePermanently={() => onDeletePermanently(card.id)}
+        />
+      )}
+
+      <BorderedViewTitleHeader
+        {...props}
+        style={{
+          transition: "opacity 300ms linear",
+          opacity: isNewQuestion ? 0 : 1,
+        }}
+      />
+      {/*This is used so that the New Question Header is unmounted after the animation*/}
+      <Transition mounted={isNewQuestion} transition={fadeIn} duration={300}>
+        {style => <NewQuestionHeader className={CS.spread} style={style} />}
+      </Transition>
+    </QueryBuilderViewHeaderContainer>
+  );
+};
diff --git a/frontend/src/metabase/query_builder/components/view/View/ViewHeaderContainer/index.ts b/frontend/src/metabase/query_builder/components/view/View/ViewHeaderContainer/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..435beb477f7226655a7df5f5242f9845ecc8806b
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/ViewHeaderContainer/index.ts
@@ -0,0 +1 @@
+export * from "./ViewHeaderContainer";
diff --git a/frontend/src/metabase/query_builder/components/view/View/ViewLeftSidebarContainer/ViewLeftSidebarContainer.jsx b/frontend/src/metabase/query_builder/components/view/View/ViewLeftSidebarContainer/ViewLeftSidebarContainer.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..bb06e7f3c406d6c560ffdd27ee1165d7fec5649b
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/ViewLeftSidebarContainer/ViewLeftSidebarContainer.jsx
@@ -0,0 +1,28 @@
+import { match } from "ts-pattern";
+
+import { ChartSettingsSidebar } from "metabase/query_builder/components/view/sidebars/ChartSettingsSidebar";
+import { ChartTypeSidebar } from "metabase/query_builder/components/view/sidebars/ChartTypeSidebar";
+
+export const ViewLeftSidebarContainer = ({
+  question,
+  result,
+  isShowingChartSettingsSidebar,
+  isShowingChartTypeSidebar,
+}) =>
+  match({
+    isShowingChartSettingsSidebar,
+    isShowingChartTypeSidebar,
+  })
+    .with(
+      {
+        isShowingChartSettingsSidebar: true,
+      },
+      () => <ChartSettingsSidebar question={question} result={result} />,
+    )
+    .with(
+      {
+        isShowingChartTypeSidebar: true,
+      },
+      () => <ChartTypeSidebar question={question} result={result} />,
+    )
+    .otherwise(() => null);
diff --git a/frontend/src/metabase/query_builder/components/view/View/ViewLeftSidebarContainer/index.ts b/frontend/src/metabase/query_builder/components/view/View/ViewLeftSidebarContainer/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fec1b66f337512ded7bc215a23acd7a04a034906
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/ViewLeftSidebarContainer/index.ts
@@ -0,0 +1 @@
+export * from "./ViewLeftSidebarContainer";
diff --git a/frontend/src/metabase/query_builder/components/view/View/ViewMainContainer/ViewMainContainer.jsx b/frontend/src/metabase/query_builder/components/view/View/ViewMainContainer/ViewMainContainer.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..d53f71afe06af90b30ceb45815d9754be49c9057
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/ViewMainContainer/ViewMainContainer.jsx
@@ -0,0 +1,67 @@
+/* eslint-disable react/prop-types */
+import CS from "metabase/css/core/index.css";
+import QueryVisualization from "metabase/query_builder/components/QueryVisualization";
+import {
+  QueryBuilderMain,
+  StyledDebouncedFrame,
+  StyledSyncedParametersList,
+} from "metabase/query_builder/components/view/View/View.styled";
+import { ViewNativeQueryEditor } from "metabase/query_builder/components/view/View/ViewNativeQueryEditor/ViewNativeQueryEditor";
+import { ViewFooter } from "metabase/query_builder/components/view/ViewFooter";
+import { TimeseriesChrome } from "metabase/querying/filters/components/TimeseriesChrome";
+import * as Lib from "metabase-lib";
+
+export const ViewMainContainer = props => {
+  const {
+    queryBuilderMode,
+    mode,
+    question,
+    showLeftSidebar,
+    showRightSidebar,
+    parameters,
+    setParameterValue,
+    isLiveResizable,
+    updateQuestion,
+  } = props;
+
+  if (queryBuilderMode === "notebook") {
+    // we need to render main only in view mode
+    return;
+  }
+
+  const queryMode = mode && mode.queryMode();
+  const { isNative } = Lib.queryDisplayInfo(question.query());
+  const isSidebarOpen = showLeftSidebar || showRightSidebar;
+
+  return (
+    <QueryBuilderMain
+      isSidebarOpen={isSidebarOpen}
+      data-testid="query-builder-main"
+    >
+      {isNative ? (
+        <ViewNativeQueryEditor {...props} />
+      ) : (
+        <StyledSyncedParametersList
+          parameters={parameters}
+          setParameterValue={setParameterValue}
+          commitImmediately
+        />
+      )}
+
+      <StyledDebouncedFrame enabled={!isLiveResizable}>
+        <QueryVisualization
+          {...props}
+          noHeader
+          className={CS.spread}
+          mode={queryMode}
+        />
+      </StyledDebouncedFrame>
+      <TimeseriesChrome
+        question={question}
+        updateQuestion={updateQuestion}
+        className={CS.flexNoShrink}
+      />
+      <ViewFooter className={CS.flexNoShrink} />
+    </QueryBuilderMain>
+  );
+};
diff --git a/frontend/src/metabase/query_builder/components/view/View/ViewMainContainer/index.ts b/frontend/src/metabase/query_builder/components/view/View/ViewMainContainer/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..38494b7effb148616c16f1a09f767227a1b3f39e
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/ViewMainContainer/index.ts
@@ -0,0 +1 @@
+export * from "./ViewMainContainer";
diff --git a/frontend/src/metabase/query_builder/components/view/View/ViewNativeQueryEditor/ViewNativeQueryEditor.jsx b/frontend/src/metabase/query_builder/components/view/View/ViewNativeQueryEditor/ViewNativeQueryEditor.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..138daae3e6df076112c7098e1b86ec7b51ba1c22
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/ViewNativeQueryEditor/ViewNativeQueryEditor.jsx
@@ -0,0 +1,45 @@
+/* eslint-disable react/prop-types */
+import NativeQueryEditor from "metabase/query_builder/components/NativeQueryEditor";
+import { NativeQueryEditorContainer } from "metabase/query_builder/components/view/View/View.styled";
+import * as Lib from "metabase-lib";
+
+export const ViewNativeQueryEditor = props => {
+  const {
+    question,
+    height,
+    isDirty,
+    isNativeEditorOpen,
+    card,
+    setParameterValueToDefault,
+    onSetDatabaseId,
+  } = props;
+
+  const legacyQuery = question.legacyQuery();
+
+  // Normally, when users open native models,
+  // they open an ad-hoc GUI question using the model as a data source
+  // (using the `/dataset` endpoint instead of the `/card/:id/query`)
+  // However, users without data permission open a real model as they can't use the `/dataset` endpoint
+  // So the model is opened as an underlying native question and the query editor becomes visible
+  // This check makes it hide the editor in this particular case
+  // More details: https://github.com/metabase/metabase/pull/20161
+  const { isEditable } = Lib.queryDisplayInfo(question.query());
+  if (question.type() === "model" && !isEditable) {
+    return null;
+  }
+
+  return (
+    <NativeQueryEditorContainer>
+      <NativeQueryEditor
+        {...props}
+        query={legacyQuery}
+        viewHeight={height}
+        isOpen={legacyQuery.isEmpty() || isDirty}
+        isInitiallyOpen={isNativeEditorOpen}
+        datasetQuery={card && card.dataset_query}
+        setParameterValueToDefault={setParameterValueToDefault}
+        onSetDatabaseId={onSetDatabaseId}
+      />
+    </NativeQueryEditorContainer>
+  );
+};
diff --git a/frontend/src/metabase/query_builder/components/view/View/ViewNativeQueryEditor/index.ts b/frontend/src/metabase/query_builder/components/view/View/ViewNativeQueryEditor/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3d215be688542b84cd5edc1cf6c5501dbe0d7f60
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/ViewNativeQueryEditor/index.ts
@@ -0,0 +1 @@
+export * from "./ViewNativeQueryEditor";
diff --git a/frontend/src/metabase/query_builder/components/view/View/ViewRightSidebarContainer/ViewRightSidebarContainer.jsx b/frontend/src/metabase/query_builder/components/view/View/ViewRightSidebarContainer/ViewRightSidebarContainer.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..aa46b55bcb8b6bce1451d7e5123f110ef13ccd23
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/ViewRightSidebarContainer/ViewRightSidebarContainer.jsx
@@ -0,0 +1,56 @@
+/* eslint-disable react/prop-types */
+import { NativeQueryRightSidebar } from "metabase/query_builder/components/view/View/NativeQueryRightSidebar/NativeQueryRightSidebar";
+import { StructuredQueryRightSidebar } from "metabase/query_builder/components/view/View/StructuredQueryRightSidebar/StructuredQueryRightSidebar";
+import * as Lib from "metabase-lib";
+
+export const ViewRightSidebarContainer = props => {
+  const {
+    question,
+    deselectTimelineEvents,
+    hideTimelineEvents,
+    isShowingQuestionInfoSidebar,
+    isShowingQuestionSettingsSidebar,
+    isShowingSummarySidebar,
+    isShowingTimelineSidebar,
+    onCloseQuestionInfo,
+    onCloseSummary,
+    onCloseTimelines,
+    onOpenModal,
+    onSave,
+    selectTimelineEvents,
+    selectedTimelineEventIds,
+    showTimelineEvents,
+    timelines,
+    updateQuestion,
+    visibleTimelineEventIds,
+    xDomain,
+  } = props;
+
+  const { isNative } = Lib.queryDisplayInfo(question.query());
+
+  return !isNative ? (
+    <StructuredQueryRightSidebar
+      deselectTimelineEvents={deselectTimelineEvents}
+      hideTimelineEvents={hideTimelineEvents}
+      isShowingQuestionInfoSidebar={isShowingQuestionInfoSidebar}
+      isShowingQuestionSettingsSidebar={isShowingQuestionSettingsSidebar}
+      isShowingSummarySidebar={isShowingSummarySidebar}
+      isShowingTimelineSidebar={isShowingTimelineSidebar}
+      onCloseQuestionInfo={onCloseQuestionInfo}
+      onCloseSummary={onCloseSummary}
+      onCloseTimelines={onCloseTimelines}
+      onOpenModal={onOpenModal}
+      onSave={onSave}
+      question={question}
+      selectTimelineEvents={selectTimelineEvents}
+      selectedTimelineEventIds={selectedTimelineEventIds}
+      showTimelineEvents={showTimelineEvents}
+      timelines={timelines}
+      updateQuestion={updateQuestion}
+      visibleTimelineEventIds={visibleTimelineEventIds}
+      xDomain={xDomain}
+    />
+  ) : (
+    <NativeQueryRightSidebar {...props} />
+  );
+};
diff --git a/frontend/src/metabase/query_builder/components/view/View/ViewRightSidebarContainer/index.ts b/frontend/src/metabase/query_builder/components/view/View/ViewRightSidebarContainer/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..abcf94d87f4181586b8907a7c4496b80065d8b24
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/ViewRightSidebarContainer/index.ts
@@ -0,0 +1 @@
+export * from "./ViewRightSidebarContainer";
diff --git a/frontend/src/metabase/query_builder/components/view/View/index.ts b/frontend/src/metabase/query_builder/components/view/View/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..94d4027d3d4702b92437046bc82454caa706bcf4
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/View/index.ts
@@ -0,0 +1 @@
+export { View } from "./View";
diff --git a/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx b/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx
index 6871bfc24019c3b06c06d0b41c4857b866ef63b6..585ee9dfc7bbc2fd8d6a1abcbe99923d39783130 100644
--- a/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx
+++ b/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx
@@ -28,7 +28,7 @@ import {
 } from "metabase/selectors/user";
 
 import * as actions from "../actions";
-import View from "../components/view/View";
+import { View } from "../components/view/View";
 import { VISUALIZATION_SLOW_TIMEOUT } from "../constants";
 import {
   getAutocompleteResultsFn,