diff --git a/ui/src/app/store.ts b/ui/src/app/store.ts
index d932606578d5e14540d4977953c4341f89a30f0b..3f7ae146c8ef9e198d03464fae625393f43f4356 100644
--- a/ui/src/app/store.ts
+++ b/ui/src/app/store.ts
@@ -23,6 +23,7 @@ import { dummyPropsFormApi } from '@/services/dummyPropsForm';
 import { pageDataFormApi } from '@/services/pageDataForm';
 import { configurationSlice } from '@/features/configuration/configurationSlice';
 import { sectionApi } from '@/services/sections';
+import { extensionsSlice } from '@/features/extensions/extensionsSlice';
 import { extensionsApi } from '@/services/extensions';
 import { codeComponentApi } from '@/services/codeComponents';
 import { formStateSlice } from '@/features/form/formStateSlice';
@@ -102,6 +103,7 @@ const rootReducer = combineSlices(
   codeComponentDialogSlice,
   uiSlice,
   formStateSlice,
+  extensionsSlice,
   pendingChangesApi,
   publishReviewSlice,
   contentListApi,
diff --git a/ui/src/components/Dialog.tsx b/ui/src/components/Dialog.tsx
index e23ed599510b1cc2d477b715cdee8b3914620f21..6e6e394a00ac614a1fcda59d097d32f6c11f1201 100644
--- a/ui/src/components/Dialog.tsx
+++ b/ui/src/components/Dialog.tsx
@@ -1,14 +1,16 @@
-import { Button, Dialog as RadixDialog, Flex, Text } from '@radix-ui/themes';
+import { Button, Dialog as ThemedDialog, Flex, Text } from '@radix-ui/themes';
 import ErrorCard from '@/components/error/ErrorCard';
 import styles from './Dialog.module.css';
-import type { ReactNode } from 'react';
+import DraggableDialogWrapper from '@/components/DraggableDialogWrapper';
+import type React from 'react';
 
 export interface DialogProps {
   open: boolean;
   onOpenChange: (open: boolean) => void;
   title: string;
-  description?: ReactNode;
-  children?: ReactNode;
+  modal?: boolean;
+  description?: React.ReactNode;
+  children?: React.ReactNode;
   error?: {
     title: string;
     message: string;
@@ -25,6 +27,33 @@ export interface DialogProps {
   };
 }
 
+const DialogWrap = ({ open, handleOpenChange, children, description }: any) => (
+  <ThemedDialog.Root open={open} onOpenChange={handleOpenChange}>
+    <ThemedDialog.Content
+      width="287px"
+      className={styles.dialogContent}
+      {...(!description && { 'aria-describedby': undefined })}
+    >
+      {children}
+    </ThemedDialog.Content>
+  </ThemedDialog.Root>
+);
+
+const DraggableDialogWrap = ({
+  handleOpenChange,
+  open,
+  description,
+  children,
+}: any) => (
+  <DraggableDialogWrapper
+    open={open}
+    onOpenChange={handleOpenChange}
+    description={description}
+  >
+    {children}
+  </DraggableDialogWrapper>
+);
+
 const Dialog = ({
   open,
   onOpenChange,
@@ -32,6 +61,7 @@ const Dialog = ({
   description,
   children,
   error,
+  modal = true,
   footer = {
     cancelText: 'Cancel',
     confirmText: 'Confirm',
@@ -41,66 +71,76 @@ const Dialog = ({
     onOpenChange(isOpen);
   };
 
+  const Wrapper = modal ? DialogWrap : DraggableDialogWrap;
+
   return (
-    <RadixDialog.Root open={open} onOpenChange={handleOpenChange}>
-      <RadixDialog.Content
-        width="287px"
-        className={styles.dialogContent}
-        // aria-describedby={undefined} is needed when there is no description.
-        // @see https://www.radix-ui.com/primitives/docs/components/dialog#description
-        {...(!description && { 'aria-describedby': undefined })}
-      >
-        <RadixDialog.Title className={styles.title}>
-          <Text size="1" weight="bold">
-            {title}
-          </Text>
-        </RadixDialog.Title>
+    <Wrapper
+      open={open}
+      handleOpenChange={handleOpenChange}
+      description={description}
+    >
+      <ThemedDialog.Title className={styles.title}>
+        <Text size="1" weight="bold">
+          {title}
+        </Text>
+      </ThemedDialog.Title>
 
-        {description && (
-          <RadixDialog.Description size="2" mb="4">
-            {description}
-          </RadixDialog.Description>
-        )}
+      {description && (
+        <ThemedDialog.Description size="2" mb="4">
+          {description}
+        </ThemedDialog.Description>
+      )}
 
-        <Flex direction="column" gap="2">
-          <Flex direction="column" gap="1">
-            {children}
-          </Flex>
+      <Flex direction="column" gap="2">
+        <Flex direction="column" gap="1">
+          {children}
+        </Flex>
 
-          {error && (
-            <ErrorCard
-              title={error.title}
-              error={error.message}
-              resetButtonText={error.resetButtonText}
-              resetErrorBoundary={error.onReset}
-            />
-          )}
+        {error && (
+          <ErrorCard
+            title={error.title}
+            error={error.message}
+            resetButtonText={error.resetButtonText}
+            resetErrorBoundary={error.onReset}
+          />
+        )}
 
-          <Flex gap="2" justify="end">
-            <RadixDialog.Close>
-              <Button variant="outline" size="1">
-                {footer.cancelText}
-              </Button>
-            </RadixDialog.Close>
-            {footer.onConfirm && (
-              <Button
-                onClick={footer.onConfirm}
-                disabled={footer.isConfirmDisabled}
-                loading={footer.isConfirmLoading}
-                size="1"
-                color={footer.isDanger ? 'red' : 'blue'}
-              >
-                {footer.confirmText}
-              </Button>
-            )}
-          </Flex>
+        <Flex gap="2" justify="end">
+          <ThemedDialog.Close>
+            <Button variant="outline" size="1">
+              {footer.cancelText}
+            </Button>
+          </ThemedDialog.Close>
+          {footer.onConfirm && (
+            <Button
+              onClick={footer.onConfirm}
+              disabled={footer.isConfirmDisabled}
+              loading={footer.isConfirmLoading}
+              size="1"
+              color={footer.isDanger ? 'red' : 'blue'}
+            >
+              {footer.confirmText}
+            </Button>
+          )}
         </Flex>
-      </RadixDialog.Content>
-    </RadixDialog.Root>
+      </Flex>
+    </Wrapper>
   );
 };
 
-const DialogFieldLabel = ({ children }: { children: ReactNode }) => {
+// const DialogContent = ({
+//   title,
+//   description,
+//   children,
+//   error,
+//   footer,
+// }: any) => (
+//   <>
+//
+//   </>
+// );
+
+const DialogFieldLabel = ({ children }: { children: React.ReactNode }) => {
   return (
     <Text as="label" size="1" weight="bold" className={styles.fieldLabel}>
       {children}
diff --git a/ui/src/components/DraggableDialogWrapper.module.css b/ui/src/components/DraggableDialogWrapper.module.css
new file mode 100644
index 0000000000000000000000000000000000000000..496fa85d338331f828421b25fb6725951508fa57
--- /dev/null
+++ b/ui/src/components/DraggableDialogWrapper.module.css
@@ -0,0 +1,30 @@
+.DialogContent {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 90vw;
+  max-width: 500px;
+  max-height: 85vh;
+  padding: 25px;
+  animation: content-show 250ms cubic-bezier(0.16, 1, 0.3, 1);
+  border-radius: 6px;
+  background-color: var(--gray-1);
+  box-shadow: var(--shadow-6);
+}
+.DialogContent:focus {
+  outline: none;
+}
+.DraggableArea {
+  position: absolute;
+  width: 100%;
+  height: var(--space-7);
+}
+
+@keyframes content-show {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
diff --git a/ui/src/components/DraggableDialogWrapper.tsx b/ui/src/components/DraggableDialogWrapper.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..064b881202cbbc27e97127d657d2f4d2ff7898bd
--- /dev/null
+++ b/ui/src/components/DraggableDialogWrapper.tsx
@@ -0,0 +1,135 @@
+import { Dialog } from 'radix-ui';
+import type { ReactNode } from 'react';
+import React, { useCallback, useRef, useState, useMemo } from 'react';
+
+import clsx from 'clsx';
+import styles from './DraggableDialogWrapper.module.css';
+import { Box, Theme } from '@radix-ui/themes';
+import Panel from '@/components/Panel';
+
+interface DraggableDialogWrapperProps {
+  onOpenChange: Function;
+  open: boolean;
+  description: ReactNode;
+  children: ReactNode;
+}
+
+const PANEL_PADDING = '4';
+
+const DraggableDialogWrapper: React.FC<DraggableDialogWrapperProps> = ({
+  onOpenChange,
+  open,
+  description,
+  children,
+}) => {
+  const dialogWidth = 500;
+  const windowWidth = window.visualViewport?.width || 100;
+  const windowHeight = window.visualViewport?.height || 100;
+  const [isDragging, setIsDragging] = useState(false);
+  const initialPosition = useMemo(() => {
+    return {
+      x: windowWidth / 2 - dialogWidth / 2,
+      y: 200,
+    };
+  }, [windowWidth, dialogWidth]);
+  const [position, setPosition] = useState(initialPosition);
+  const dialogRef = useRef<HTMLDivElement | null>(null);
+
+  const handleOpenChange = useCallback(
+    (open: boolean) => {
+      onOpenChange(open);
+      setPosition(initialPosition);
+    },
+    [initialPosition, onOpenChange],
+  );
+  const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
+    setIsDragging(true);
+  };
+
+  const handleMouseMove = useCallback(
+    (e: MouseEvent) => {
+      if (isDragging && dialogRef.current) {
+        // Ensure the dialog cannot be dragged so far off the edge that it can't be dragged back on again.
+        const innerBound = 40;
+        const minX = 0 - dialogWidth + innerBound;
+        const maxX = windowWidth - innerBound;
+        const minY = 0 - innerBound / 2;
+        const maxY = windowHeight - innerBound;
+        setPosition((prevPosition) => {
+          const newX = prevPosition.x + e.movementX;
+          const newY = prevPosition.y + e.movementY;
+
+          return {
+            x: Math.max(minX, Math.min(newX, maxX)),
+            y: Math.max(minY, Math.min(newY, maxY)),
+          };
+        });
+      }
+    },
+    [isDragging, windowHeight, windowWidth],
+  );
+
+  const handleMouseUp = () => {
+    setIsDragging(false);
+  };
+
+  React.useEffect(() => {
+    if (isDragging) {
+      document.addEventListener('mousemove', handleMouseMove);
+      document.addEventListener('mouseup', handleMouseUp);
+    } else {
+      document.removeEventListener('mousemove', handleMouseMove);
+      document.removeEventListener('mouseup', handleMouseUp);
+    }
+
+    return () => {
+      document.removeEventListener('mousemove', handleMouseMove);
+      document.removeEventListener('mouseup', handleMouseUp);
+    };
+  }, [handleMouseMove, isDragging]);
+
+  return (
+    <Dialog.Root modal={false} open={open} onOpenChange={handleOpenChange}>
+      <Dialog.Portal>
+        <Theme>
+          <Dialog.Content
+            className={clsx(styles.DialogContent)}
+            asChild
+            style={{
+              transform: `translate(${position.x}px, ${position.y}px)`,
+              position: 'absolute',
+            }}
+            onPointerDownOutside={(event) => {
+              event.preventDefault();
+            }}
+            onInteractOutside={(event) => {
+              event.preventDefault();
+            }}
+            ref={dialogRef}
+            // aria-describedby={undefined} is needed when there is no description.
+            // @see https://www.radix-ui.com/primitives/docs/components/dialog#description
+            {...(!description && { 'aria-describedby': undefined })}
+          >
+            <Panel p={PANEL_PADDING}>
+              <Box
+                mt={`-${PANEL_PADDING}`}
+                pt={PANEL_PADDING}
+                mx={`-${PANEL_PADDING}`}
+                px={PANEL_PADDING}
+                className={styles.DraggableArea}
+                onMouseDown={handleMouseDown}
+                style={{
+                  cursor: 'move',
+                }}
+              />
+
+              {children}
+            </Panel>
+          </Dialog.Content>
+        </Theme>
+      </Dialog.Portal>
+    </Dialog.Root>
+  );
+};
+
+export default DraggableDialogWrapper;
diff --git a/ui/src/components/extensions/ExtensionButton.tsx b/ui/src/components/extensions/ExtensionButton.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..06f1b2deb890946c3dac60491f8de7345198c5f0
--- /dev/null
+++ b/ui/src/components/extensions/ExtensionButton.tsx
@@ -0,0 +1,42 @@
+import clsx from 'clsx';
+import { Flex, Text, Tooltip } from '@radix-ui/themes';
+import styles from './ExtensionsList.module.css';
+import type React from 'react';
+import { useCallback } from 'react';
+import type { ExtensionDefinition } from '@/types/Extensions';
+import { useAppDispatch } from '@/app/hooks';
+import { setDialogOpen } from '@/features/ui/dialogSlice';
+import { setActiveExtension } from '@/features/extensions/extensionsSlice';
+
+const ExtensionButton: React.FC<ExtensionsPopoverProps> = ({ extension }) => {
+  const { name, imgSrc, description } = extension;
+  const dispatch = useAppDispatch();
+
+  const handleClick = useCallback(
+    (e: React.MouseEvent<HTMLButtonElement>) => {
+      e.preventDefault();
+      dispatch(setDialogOpen('extension'));
+      dispatch(setActiveExtension(extension));
+    },
+    [dispatch, extension],
+  );
+
+  return (
+    <Tooltip content={description}>
+      <Flex justify="start" align="center" direction="column" asChild>
+        <button className={clsx(styles.extensionIcon)} onClick={handleClick}>
+          <img alt={name} src={imgSrc} height="42" width="42" />
+          <Text align="center" size="1">
+            {name}
+          </Text>
+        </button>
+      </Flex>
+    </Tooltip>
+  );
+};
+
+interface ExtensionsPopoverProps {
+  extension: ExtensionDefinition;
+}
+
+export default ExtensionButton;
diff --git a/ui/src/components/extensions/ExtensionDialog.module.css b/ui/src/components/extensions/ExtensionDialog.module.css
new file mode 100644
index 0000000000000000000000000000000000000000..4f4f9a0d6076adf6ae252c51dd42ff34bb84ef06
--- /dev/null
+++ b/ui/src/components/extensions/ExtensionDialog.module.css
@@ -0,0 +1,25 @@
+.DialogContent {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 90vw;
+  max-width: 500px;
+  max-height: 85vh;
+  padding: 25px;
+   animation: content-show 250ms cubic-bezier(0.16, 1, 0.3, 1);
+  border-radius: 6px;
+  background-color: var(--gray-1);
+  box-shadow: var(--shadow-6);
+}
+.DialogContent:focus {
+  outline: none;
+}
+
+@keyframes content-show {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
diff --git a/ui/src/components/extensions/ExtensionDialog.tsx b/ui/src/components/extensions/ExtensionDialog.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..cb9cb4a27d01bca1d4632b2d37f01856f352e5c4
--- /dev/null
+++ b/ui/src/components/extensions/ExtensionDialog.tsx
@@ -0,0 +1,59 @@
+import Dialog from '@/components/Dialog';
+import type React from 'react';
+import { useCallback } from 'react';
+
+import { Text } from '@radix-ui/themes';
+import { useAppDispatch, useAppSelector } from '@/app/hooks';
+import {
+  selectDialogOpen,
+  setDialogClosed,
+  setDialogOpen,
+} from '@/features/ui/dialogSlice';
+import {
+  selectActiveExtension,
+  unsetActiveExtension,
+} from '@/features/extensions/extensionsSlice';
+
+interface ExtensionDialogProps {}
+
+const ExtensionDialog: React.FC<ExtensionDialogProps> = () => {
+  const { extension } = useAppSelector(selectDialogOpen);
+  const activeExtension = useAppSelector(selectActiveExtension);
+  const dispatch = useAppDispatch();
+
+  const handleOpenChange = useCallback(
+    (open: boolean) => {
+      if (open) {
+        dispatch(setDialogOpen('extension'));
+      } else {
+        dispatch(setDialogClosed('extension'));
+        dispatch(unsetActiveExtension());
+      }
+    },
+    [dispatch],
+  );
+  if (!extension || activeExtension === null) {
+    return null;
+  }
+
+  return (
+    <Dialog
+      open={extension}
+      onOpenChange={handleOpenChange}
+      title={activeExtension.name}
+      modal={false}
+      footer={{ cancelText: 'Close' }}
+      description={activeExtension.description}
+    >
+      {/* @todo https://www.drupal.org/i/3485692 - render the proof of concept into this div */}
+      <div
+        id="extensionPortalContainer"
+        className={`xb-extension-${activeExtension.id}`}
+      >
+        <Text as="p">Not yet supported</Text>
+      </div>
+    </Dialog>
+  );
+};
+
+export default ExtensionDialog;
diff --git a/ui/src/components/extensionsPopover/ExtensionsList.module.css b/ui/src/components/extensions/ExtensionsList.module.css
similarity index 100%
rename from ui/src/components/extensionsPopover/ExtensionsList.module.css
rename to ui/src/components/extensions/ExtensionsList.module.css
diff --git a/ui/src/components/extensionsPopover/ExtensionsList.tsx b/ui/src/components/extensions/ExtensionsList.tsx
similarity index 96%
rename from ui/src/components/extensionsPopover/ExtensionsList.tsx
rename to ui/src/components/extensions/ExtensionsList.tsx
index 1dcc7c6fa7f5b79723e4f91835142f4eaa5ea38f..ccd2b51971699dfd0c875a2bb84b0ef6d1cb8367 100644
--- a/ui/src/components/extensionsPopover/ExtensionsList.tsx
+++ b/ui/src/components/extensions/ExtensionsList.tsx
@@ -1,6 +1,6 @@
 import { Flex, Heading, Link, Grid, Spinner } from '@radix-ui/themes';
 import { ExternalLinkIcon } from '@radix-ui/react-icons';
-import ExtensionButton from '@/components/extensionsPopover/ExtensionButton';
+import ExtensionButton from '@/components/extensions/ExtensionButton';
 import { handleNonWorkingBtn } from '@/utils/function-utils';
 import type React from 'react';
 import { useGetExtensionsQuery } from '@/services/extensions';
diff --git a/ui/src/components/extensionsPopover/ExtensionsListDisplay.stories.tsx b/ui/src/components/extensions/ExtensionsListDisplay.stories.tsx
similarity index 96%
rename from ui/src/components/extensionsPopover/ExtensionsListDisplay.stories.tsx
rename to ui/src/components/extensions/ExtensionsListDisplay.stories.tsx
index 7ce64b4060fb39d60821ddc8c089757ef4018922..45b4f8b9a9f6319883d96b98e4818c68e000c81f 100644
--- a/ui/src/components/extensionsPopover/ExtensionsListDisplay.stories.tsx
+++ b/ui/src/components/extensions/ExtensionsListDisplay.stories.tsx
@@ -1,5 +1,5 @@
 import type { Meta, StoryObj } from '@storybook/react';
-import { ExtensionsListDisplay } from '@/components/extensionsPopover/ExtensionsList';
+import { ExtensionsListDisplay } from '@/components/extensions/ExtensionsList';
 
 const kittenBase64 =
   /* cspell:disable-next-line */
diff --git a/ui/src/components/extensionsPopover/ExtensionButton.tsx b/ui/src/components/extensionsPopover/ExtensionButton.tsx
deleted file mode 100644
index f639da7f415109bcf3f41eeeff7888d58ce98761..0000000000000000000000000000000000000000
--- a/ui/src/components/extensionsPopover/ExtensionButton.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import clsx from 'clsx';
-import { Flex, Text } from '@radix-ui/themes';
-import styles from './ExtensionsList.module.css';
-import type React from 'react';
-import { useCallback } from 'react';
-import { handleNonWorkingBtn } from '@/utils/function-utils';
-import type { Extension } from '@/types/Extensions';
-
-interface ExtensionsPopoverProps {
-  extension: Extension;
-}
-
-const ExtensionButton: React.FC<ExtensionsPopoverProps> = ({ extension }) => {
-  const { name, imgSrc } = extension;
-  const handleClick = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
-    e.preventDefault();
-    handleNonWorkingBtn();
-  }, []);
-
-  return (
-    <Flex justify="start" align="center" direction="column" asChild>
-      <button className={clsx(styles.extensionIcon)} onClick={handleClick}>
-        <img alt={name} src={imgSrc} height="42" width="42" />
-        <Text align="center" size="1">
-          {name}
-        </Text>
-      </button>
-    </Flex>
-  );
-};
-
-export default ExtensionButton;
diff --git a/ui/src/components/topbar/Topbar.tsx b/ui/src/components/topbar/Topbar.tsx
index 72cb59bdc0ef53cb51432fc6e9565bb8083b6318..783d601decf1acd14fa38a6f590e6829e3998b55 100644
--- a/ui/src/components/topbar/Topbar.tsx
+++ b/ui/src/components/topbar/Topbar.tsx
@@ -18,7 +18,7 @@ import { useLocation, useNavigate } from 'react-router-dom';
 import clsx from 'clsx';
 import UnpublishedChanges from '@/components/review/UnpublishedChanges';
 import PageInfo from '../pageInfo/PageInfo';
-import ExtensionsList from '@/components/extensionsPopover/ExtensionsList';
+import ExtensionsList from '@/components/extensions/ExtensionsList';
 import type React from 'react';
 import { handleNonWorkingBtn } from '@/utils/function-utils';
 import TopbarPopover from '@/components/topbar/menu/TopbarPopover';
diff --git a/ui/src/features/editor/Editor.tsx b/ui/src/features/editor/Editor.tsx
index 3e7afb6e4e02e4a84eb592aa4ae57c536ea9977c..54e7cbaeec36220760cb5c4ffa74b94a0c9d8be7 100644
--- a/ui/src/features/editor/Editor.tsx
+++ b/ui/src/features/editor/Editor.tsx
@@ -7,6 +7,7 @@ import ContextualPanel from '@/components/panel/ContextualPanel';
 import { useEffect } from 'react';
 import { setFirstLoadComplete } from '@/features/ui/uiSlice';
 import { useAppDispatch } from '@/app/hooks';
+import ExtensionDialog from '@/components/extensions/ExtensionDialog';
 const Editor = () => {
   const dispatch = useAppDispatch();
 
@@ -26,6 +27,7 @@ const Editor = () => {
       <div id="menuBarSubmenuContainer"></div>
       <SaveSectionDialog />
       <CodeComponentDialogs />
+      <ExtensionDialog />
     </>
   );
 };
diff --git a/ui/src/features/extensions/extensionsSlice.ts b/ui/src/features/extensions/extensionsSlice.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ffac25fe44e1a111027a2c7ecd4d001b049fa5ff
--- /dev/null
+++ b/ui/src/features/extensions/extensionsSlice.ts
@@ -0,0 +1,39 @@
+import { createAppSlice } from '@/app/createAppSlice';
+import type { PayloadAction } from '@reduxjs/toolkit';
+import type { ExtensionDefinition, ActiveExtension } from '@/types/Extensions';
+
+export interface ExtensionsSliceState {
+  activeExtension: ActiveExtension;
+}
+
+const initialState: ExtensionsSliceState = {
+  activeExtension: null,
+};
+
+type UpdateExtensionsPayload = ExtensionDefinition;
+
+export const extensionsSlice = createAppSlice({
+  name: 'extensions',
+  initialState,
+  reducers: (create) => ({
+    setActiveExtension: create.reducer(
+      (state, action: PayloadAction<UpdateExtensionsPayload>) => {
+        state.activeExtension = action.payload;
+      },
+    ),
+    unsetActiveExtension: create.reducer((state) => {
+      state.activeExtension = null;
+    }),
+  }),
+  selectors: {
+    selectActiveExtension: (state): ActiveExtension => {
+      return state.activeExtension;
+    },
+  },
+});
+
+export const extensionsReducer = extensionsSlice.reducer;
+
+export const { setActiveExtension, unsetActiveExtension } =
+  extensionsSlice.actions;
+export const { selectActiveExtension } = extensionsSlice.selectors;
diff --git a/ui/src/features/ui/dialogSlice.ts b/ui/src/features/ui/dialogSlice.ts
index 1b89609e215630ecef95133c96fb3e8a26c13944..80dc1dc0fbab35e4168e3719af373247255f1d83 100644
--- a/ui/src/features/ui/dialogSlice.ts
+++ b/ui/src/features/ui/dialogSlice.ts
@@ -3,13 +3,15 @@ import type { PayloadAction } from '@reduxjs/toolkit';
 
 export interface DialogSliceState {
   saveAsSection: boolean;
+  extension: boolean;
 }
 
 const initialState: DialogSliceState = {
   saveAsSection: false,
+  extension: false,
 };
 
-type UpdateDialogPayload = 'saveAsSection'; // only one dialog so far
+type UpdateDialogPayload = keyof DialogSliceState;
 
 export const dialogSlice = createAppSlice({
   name: 'dialog',
diff --git a/ui/src/services/extensions.ts b/ui/src/services/extensions.ts
index 1ac50e3cb2a65eb97b7884e82caec58c904a6bc2..064db720ee6db8f2cce7f01c1fc4ccf4bcbc719a 100644
--- a/ui/src/services/extensions.ts
+++ b/ui/src/services/extensions.ts
@@ -10,26 +10,31 @@ const kittenBase64 =
 const dummyExtensionsList = [
   {
     name: 'Extension 1',
+    description: 'a description of extension 1',
     imgSrc: kittenBase64,
     id: 'extension1',
   },
   {
     name: 'Extension with longer name 2',
+    description: 'a description of extension 2',
     imgSrc: kittenBase64,
     id: 'extension2',
   },
   {
     name: 'Extension 3',
+    description: 'a description of extension 3',
     imgSrc: kittenBase64,
     id: 'extension3',
   },
   {
     name: 'Extension 4',
+    description: 'a description of extension 4',
     imgSrc: kittenBase64,
     id: 'extension4',
   },
   {
     name: 'Extension name 5',
+    description: 'a description of extension 5',
     imgSrc: kittenBase64,
     id: 'extension5',
   },
diff --git a/ui/src/types/Extensions.ts b/ui/src/types/Extensions.ts
index 940b59bd4b6dba3e2fe6b3407e11496465d6e73a..0e04cc61f23d7b312df3e145e04e4a1946a8aa4a 100644
--- a/ui/src/types/Extensions.ts
+++ b/ui/src/types/Extensions.ts
@@ -1,7 +1,9 @@
-export interface Extension {
+export interface ExtensionDefinition {
   name: string;
-  imgSrc: string;
   id: string;
+  description: string;
+  imgSrc: string;
 }
 
-export type ExtensionsList = Extension[];
+export type ExtensionsList = ExtensionDefinition[];
+export type ActiveExtension = ExtensionDefinition | null;