From 69a1349c20b55854c9c1882927865f459f347d1d Mon Sep 17 00:00:00 2001
From: Leonardo <leomilho@gmail.com>
Date: Wed, 12 Jun 2024 20:11:41 +0200
Subject: [PATCH] fix: settings panel and visualization loading

---
 .../dbConnectionSelector.tsx                  |   2 -
 .../dropdowns/dropdowns.module.scss           |  26 +--
 .../dropdowns/dropdowns.module.scss.d.ts      |   5 +-
 .../shared/lib/components/dropdowns/index.tsx |  31 +++-
 .../components/inputs/dropdown.stories.tsx    |   6 +-
 libs/shared/lib/components/inputs/index.tsx   |  18 +-
 libs/shared/lib/components/layout/Popover.tsx |   2 +-
 libs/shared/lib/data-access/api/eventBus.tsx  |  13 +-
 .../shared/lib/data-access/broker/wsState.tsx |   3 +-
 libs/shared/lib/data-access/store/hooks.ts    |   4 +-
 .../data-access/store/visualizationSlice.ts   |  98 ++++++++---
 libs/shared/lib/inspector/InspectorPanel.tsx  |  16 +-
 libs/shared/lib/vis/common/types.ts           |  28 ++-
 .../lib/vis/components/VisualizationPanel.tsx | 119 ++++++++++---
 .../vis/components/VisualizationTabBar.tsx    | 120 +++++++++++++
 libs/shared/lib/vis/components/bar.tsx        | 115 -------------
 .../config/ActiveVisualizationConfig.tsx      |  43 -----
 .../vis/components/config/SelectionConfig.tsx |   1 -
 .../config/VisualizationSettings.tsx          | 113 +++++++++++++
 .../lib/vis/components/config/components.tsx  |   2 +-
 .../lib/vis/components/config/index.tsx       |   2 +-
 .../lib/vis/components/config/panel.tsx       |  18 --
 .../lib/vis/manager/VisualizationManager.tsx  | 159 ------------------
 libs/shared/lib/vis/manager/index.ts          |   2 -
 libs/shared/lib/vis/manager/manager.types.ts  |  12 --
 .../lib/vis/views/{noData.tsx => NoData.tsx}  |   0
 .../vis/views/{querying.tsx => Querying.tsx}  |   0
 .../{recommender.tsx => Recommender.tsx}      |  13 +-
 libs/shared/lib/vis/views/index.tsx           |   6 +-
 .../vis/visualizations/mapvis/MapSettings.tsx |  63 +++++++
 .../visualizations/mapvis/configuration.tsx   |  65 -------
 .../lib/vis/visualizations/mapvis/mapvis.tsx  |  61 +++----
 .../matrixvis/components/MatrixPixi.tsx       |  13 +-
 .../matrixvis/matrix.stories.tsx              |   1 -
 .../visualizations/matrixvis/matrixvis.tsx    |  32 ++--
 .../nodelinkvis/components/NLPixi.tsx         |   7 +-
 .../nodelinkvis/nodelinkvis.tsx               |  70 ++++----
 .../vis/visualizations/paohvis/paohvis.tsx    | 152 ++++++++---------
 .../visualizations/rawjsonvis/rawjsonvis.tsx  |  36 ++--
 .../semanticsubstratesvis.tsx                 |  24 +--
 .../tablevis/tablevis.stories.tsx             |   6 +-
 .../vis/visualizations/tablevis/tablevis.tsx  |  70 ++++----
 42 files changed, 788 insertions(+), 789 deletions(-)
 create mode 100644 libs/shared/lib/vis/components/VisualizationTabBar.tsx
 delete mode 100644 libs/shared/lib/vis/components/bar.tsx
 delete mode 100644 libs/shared/lib/vis/components/config/ActiveVisualizationConfig.tsx
 create mode 100644 libs/shared/lib/vis/components/config/VisualizationSettings.tsx
 delete mode 100644 libs/shared/lib/vis/components/config/panel.tsx
 delete mode 100644 libs/shared/lib/vis/manager/VisualizationManager.tsx
 delete mode 100644 libs/shared/lib/vis/manager/index.ts
 delete mode 100644 libs/shared/lib/vis/manager/manager.types.ts
 rename libs/shared/lib/vis/views/{noData.tsx => NoData.tsx} (100%)
 rename libs/shared/lib/vis/views/{querying.tsx => Querying.tsx} (100%)
 rename libs/shared/lib/vis/views/{recommender.tsx => Recommender.tsx} (62%)
 create mode 100644 libs/shared/lib/vis/visualizations/mapvis/MapSettings.tsx
 delete mode 100644 libs/shared/lib/vis/visualizations/mapvis/configuration.tsx

diff --git a/apps/web/src/components/navbar/DatabaseManagement/dbConnectionSelector.tsx b/apps/web/src/components/navbar/DatabaseManagement/dbConnectionSelector.tsx
index 2775725cf..488156b24 100644
--- a/apps/web/src/components/navbar/DatabaseManagement/dbConnectionSelector.tsx
+++ b/apps/web/src/components/navbar/DatabaseManagement/dbConnectionSelector.tsx
@@ -76,8 +76,6 @@ export default function DatabaseSelector({}) {
         <DropdownContainer
           open={dbSelectionMenuOpen}
           onOpenChange={(ret) => {
-            console.log('dbSelectionMenuOpen', dbSelectionMenuOpen, ret);
-
             if (!ret) {
               if (session.saveStates && Object.keys(session.saveStates).length === 0) setSettingsMenuOpen('add');
               else setDbSelectionMenuOpen(!dbSelectionMenuOpen);
diff --git a/libs/shared/lib/components/dropdowns/dropdowns.module.scss b/libs/shared/lib/components/dropdowns/dropdowns.module.scss
index 8d45e1520..c051a7c9f 100644
--- a/libs/shared/lib/components/dropdowns/dropdowns.module.scss
+++ b/libs/shared/lib/components/dropdowns/dropdowns.module.scss
@@ -1,19 +1,19 @@
 .dropdown {
 }
 .dropdown-item {
-  //todo: color
-  //@apply cursor-pointer block px-4 py-2 text-sm bg-secondary-200;
-  @apply cursor-pointer block px-4 py-2 text-sm;
+  // //todo: color
+  // //@apply cursor-pointer block px-4 py-2 text-sm bg-secondary-200;
+  // @apply cursor-pointer block text-sm px-2 py-1 rounded hover:bg-secondary-200 border-0;
 }
 .dropdown-container {
-  width: inherit;
-  max-width: 100%;
-  @apply absolute z-10 mt-2 origin-top-right rounded-sm shadow-lg border border-secondary-200 truncate;
-  ul {
-    //todo: color
-    @apply divide-y;
-    //@apply divide-y divide-secondary-100;
-    li {
-    }
-  }
+  // width: inherit;
+  // max-width: 100%;
+  // @apply absolute z-10 mt-2 origin-top-right rounded-sm shadow-lg truncate;
+  // ul {
+  //   //todo: color
+  //   @apply divide-y;
+  //   //@apply divide-y divide-secondary-100;
+  //   li {
+  //   }
+  // }
 }
diff --git a/libs/shared/lib/components/dropdowns/dropdowns.module.scss.d.ts b/libs/shared/lib/components/dropdowns/dropdowns.module.scss.d.ts
index 9b29e9805..5fc8829cc 100644
--- a/libs/shared/lib/components/dropdowns/dropdowns.module.scss.d.ts
+++ b/libs/shared/lib/components/dropdowns/dropdowns.module.scss.d.ts
@@ -1,5 +1,2 @@
-declare const classNames: {
-  readonly 'dropdown-item': 'dropdown-item';
-  readonly 'dropdown-container': 'dropdown-container';
-};
+declare const classNames: {};
 export = classNames;
diff --git a/libs/shared/lib/components/dropdowns/index.tsx b/libs/shared/lib/components/dropdowns/index.tsx
index cc2171f84..cc1ffae20 100644
--- a/libs/shared/lib/components/dropdowns/index.tsx
+++ b/libs/shared/lib/components/dropdowns/index.tsx
@@ -2,21 +2,37 @@ import React, { useState, useEffect, useRef, ReactNode } from 'react';
 import styles from './dropdowns.module.scss';
 import Icon from '../icon';
 import { ArrowDropDown } from '@mui/icons-material';
-import { PopoverContent, PopoverTrigger, Popover } from '../layout/Popover';
+import { PopoverContent, PopoverTrigger, Popover, PopoverOptions } from '../layout/Popover';
 
-export const DropdownContainer = Popover;
+export const DropdownContainer = ({ children, ...props }: { children: React.ReactNode } & PopoverOptions) => {
+  return (
+    <Popover placement="bottom-start" {...props}>
+      {children}
+    </Popover>
+  );
+};
 
 type DropdownTriggerProps = {
-  title: string | ReactNode;
+  title?: string | ReactNode;
   size?: 'xs' | 'sm' | 'md' | 'xl';
   disabled?: boolean;
   variant?: 'primary' | 'ghost' | 'outline';
   className?: string;
   popover?: boolean;
   onClick?: () => void;
+  children?: ReactNode;
 };
 
-export function DropdownTrigger({ title, size, disabled, variant, className, onClick, popover = true }: DropdownTriggerProps) {
+export function DropdownTrigger({
+  title,
+  size,
+  disabled,
+  variant,
+  className,
+  onClick,
+  popover = true,
+  children = undefined,
+}: DropdownTriggerProps) {
   const paddingClass = size === 'xs' ? 'py-0' : size === 'sm' ? 'px-1 py-1' : size === 'md' ? 'px-2 py-1' : 'px-4 py-2';
   const textSizeClass = size === 'xs' ? 'text-xs' : size === 'sm' ? 'text-sm' : size === 'md' ? 'text-base' : 'text-lg';
 
@@ -27,7 +43,7 @@ export function DropdownTrigger({ title, size, disabled, variant, className, onC
         ? 'bg-transparent shadow-none'
         : 'border rounded bg-transparent';
 
-  const inner = (
+  const inner = children || (
     <div
       className={`inline-flex w-full truncate justify-between items-center gap-x-1.5 ${variantClass} ${textSizeClass} ${paddingClass} text-secondary-900 shadow-sm hover:bg-secondary-50 disabled:bg-secondary-100 disabled:cursor-not-allowed disabled:text-secondary-400 pl-1 truncate${className ? ` ${className}` : ''}`}
     >
@@ -57,7 +73,7 @@ export const DropdownItemContainer = React.forwardRef<HTMLDivElement, DropdownIt
   return (
     <PopoverContent
       ref={ref}
-      className={`${styles['dropdown-container']} ${className} bg-light`}
+      className={`bg-light p-1 rounded border`}
       role="menu"
       aria-orientation="vertical"
       aria-labelledby="menu-button"
@@ -85,7 +101,8 @@ export function DropdownItem({ value, disabled, className, onClick, submenu, sel
   return (
     <li
       ref={itemRef}
-      className={`${styles['dropdown-item']} ${className && className} hover:bg-primary-100 ${selected ? 'bg-primary text-white hover:text-black' : ''}`}
+      style={{ border: 0 }}
+      className={`cursor-pointer divide-y origin-top-right rounded-sm truncate block text-sm px-2 py-1 hover:bg-secondary-200 ${className && className} ${selected ? 'bg-secondary-400 text-white hover:text-black' : ''}`}
       onClick={() => {
         !disabled && onClick && onClick(value);
       }}
diff --git a/libs/shared/lib/components/inputs/dropdown.stories.tsx b/libs/shared/lib/components/inputs/dropdown.stories.tsx
index 319132e5a..166f8892f 100644
--- a/libs/shared/lib/components/inputs/dropdown.stories.tsx
+++ b/libs/shared/lib/components/inputs/dropdown.stories.tsx
@@ -1,10 +1,10 @@
 import React from 'react';
 import type { Meta, StoryObj } from '@storybook/react';
-import { DropDownInput } from '.';
+import { DropdownInput } from '.';
 
-const Component: Meta<typeof DropDownInput> = {
+const Component: Meta<typeof DropdownInput> = {
   title: 'Components/Inputs',
-  component: DropDownInput,
+  component: DropdownInput,
   argTypes: { onChange: {} },
   decorators: [(Story) => <div className="w-52 m-5">{Story()}</div>],
 };
diff --git a/libs/shared/lib/components/inputs/index.tsx b/libs/shared/lib/components/inputs/index.tsx
index b2160102c..637887824 100644
--- a/libs/shared/lib/components/inputs/index.tsx
+++ b/libs/shared/lib/components/inputs/index.tsx
@@ -85,19 +85,19 @@ type RadioProps = {
 
 type DropdownProps = {
   label?: string;
-  value: string | number | undefined;
   overrideRender?: React.ReactNode;
   type: 'dropdown';
-  options: any;
   size?: 'xs' | 'sm' | 'md' | 'xl';
   tooltip?: string;
-  onChange?: (value: string | number) => void;
   required?: boolean;
   inline?: boolean;
   buttonVariant?: 'primary' | 'outline' | 'ghost';
   info?: string;
   disabled?: boolean;
   className?: string;
+  value?: number | string;
+  options: number[] | string[];
+  onChange?: (value: number | string) => void;
 };
 
 export type InputProps = TextProps | SliderProps | CheckboxProps | DropdownProps | RadioProps | BooleanProps | NumberProps;
@@ -111,7 +111,7 @@ export const Input = (props: InputProps) => {
     case 'checkbox':
       return <CheckboxInput {...(props as CheckboxProps)} />;
     case 'dropdown':
-      return <DropDownInput {...(props as DropdownProps)} />;
+      return <DropdownInput {...(props as DropdownProps)} />;
     case 'radio':
       return <RadioInput {...(props as RadioProps)} />;
     case 'boolean':
@@ -195,7 +195,7 @@ export const TextInput = ({
           type={visible ? 'text' : 'password'}
           placeholder={placeholder}
           className={
-            `${size} bg-light border border-secondary-300 placeholder-secondary-400 focus:outline-none block w-full focus:ring-1 ${
+            `${size} bg-light border border-secondary-200 placeholder-secondary-400 focus:outline-none block w-full focus:ring-1 ${
               isValid ? '' : 'input-error'
             }` + (className ? ` ${className}` : '')
           }
@@ -253,7 +253,7 @@ export const NumberInput = ({
         <input
           type="number"
           placeholder={placeholder}
-          className={`${size} bg-light border border-secondary-300 placeholder-secondary-400 focus:outline-none block w-full sm:text-sm focus:ring-1 ${
+          className={`${size} bg-light border border-secondary-200 placeholder-secondary-400 focus:outline-none block w-full sm:text-sm focus:ring-1 ${
             isValid ? '' : 'input-error'
           }`}
           value={value.toString()}
@@ -371,7 +371,7 @@ export const BooleanInput = ({ label, value, onChange, tooltip }: BooleanProps)
   );
 };
 
-export const DropDownInput = ({
+export const DropdownInput = ({
   label,
   value,
   overrideRender,
@@ -396,7 +396,7 @@ export const DropDownInput = ({
         {label && (
           <label className="label p-0">
             <span
-              className={`text-sm text-left truncate font-medium text-secondary-700 ${required && "after:content-['*'] after:ml-0.5 after:text-danger-500"}`}
+              className={`text-${size} text-left truncate font-medium text-secondary-700 ${required && "after:content-['*'] after:ml-0.5 after:text-danger-500"}`}
             >
               {label}
             </span>
@@ -413,7 +413,7 @@ export const DropDownInput = ({
             variant={buttonVariant}
             title={overrideRender || value}
             size={size}
-            className=""
+            className="cursor-pointer"
             disabled={disabled}
             onClick={() => {
               setIsDropdownOpen(!isDropdownOpen);
diff --git a/libs/shared/lib/components/layout/Popover.tsx b/libs/shared/lib/components/layout/Popover.tsx
index 70af69867..7a2543de1 100644
--- a/libs/shared/lib/components/layout/Popover.tsx
+++ b/libs/shared/lib/components/layout/Popover.tsx
@@ -16,7 +16,7 @@ import {
   useId,
 } from '@floating-ui/react';
 
-interface PopoverOptions {
+export interface PopoverOptions {
   initialOpen?: boolean;
   placement?: Placement;
   modal?: boolean;
diff --git a/libs/shared/lib/data-access/api/eventBus.tsx b/libs/shared/lib/data-access/api/eventBus.tsx
index 01c72fb6a..838c1bb93 100644
--- a/libs/shared/lib/data-access/api/eventBus.tsx
+++ b/libs/shared/lib/data-access/api/eventBus.tsx
@@ -46,7 +46,7 @@ import {
   setFetchingSaveStates,
 } from '../store/sessionSlice';
 import { URLParams, getParam, deleteParam } from './url';
-import { setVisualizationState } from '../store/visualizationSlice';
+import { VisState, setVisualizationState } from '../store/visualizationSlice';
 import { isEqual } from 'lodash-es';
 import { addSchemaAttributeDimensions } from '../store/schemaSlice';
 import { addError } from '@graphpolaris/shared/lib/data-access/store/configSlice';
@@ -70,7 +70,16 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
       const state = saveStates[saveStateID];
       if (state) {
         dispatch(setQuerybuilderNodes(state.queryBuilder));
-        dispatch(setVisualizationState(state.visualization));
+        dispatch(
+          setVisualizationState(
+            Object.keys(state.visualization).length !== 0 // should only occur in mock data
+              ? (state.visualization as VisState)
+              : {
+                  activeVisualizationIndex: -1,
+                  openVisualizationArray: [],
+                },
+          ),
+        );
       }
     }
   }
diff --git a/libs/shared/lib/data-access/broker/wsState.tsx b/libs/shared/lib/data-access/broker/wsState.tsx
index 3634da71a..bc302e7cb 100644
--- a/libs/shared/lib/data-access/broker/wsState.tsx
+++ b/libs/shared/lib/data-access/broker/wsState.tsx
@@ -2,6 +2,7 @@ import { QueryBuilderState } from '../store/querybuilderSlice';
 import { URLParams, setParam } from '../api/url';
 import { Broker } from './broker';
 import { DateStringStatement } from '../../querybuilder/model/logic/general';
+import { VisState } from '../store/visualizationSlice';
 
 export const databaseNameMapping: string[] = ['arangodb', 'neo4j'];
 export const databaseProtocolMapping: string[] = ['neo4j://', 'neo4j+s://', 'bolt://', 'bolt+s://'];
@@ -36,7 +37,7 @@ export type SaveStateI = {
   db: DatabaseInfo;
   schema: any;
   queryBuilder: QueryBuilderState;
-  visualization: any;
+  visualization: VisState | {};
   share_state: any;
 };
 
diff --git a/libs/shared/lib/data-access/store/hooks.ts b/libs/shared/lib/data-access/store/hooks.ts
index 3cf9e53fa..8e52b38f4 100644
--- a/libs/shared/lib/data-access/store/hooks.ts
+++ b/libs/shared/lib/data-access/store/hooks.ts
@@ -14,7 +14,7 @@ import {
 } from '@graphpolaris/shared/lib/data-access/store/querybuilderSlice';
 import { SessionCacheI, sessionCacheState } from './sessionSlice';
 import { UseIsAuthorizedState, authState } from './authSlice';
-import { visualizationState, VisState } from './visualizationSlice';
+import { visualizationState, VisState, visualizationActive } from './visualizationSlice';
 import { ML, allMLEnabled, selectML } from './mlSlice';
 import {
   searchResultState,
@@ -30,6 +30,7 @@ import { QueryGraphEdgeHandle, QueryMultiGraph } from '../../querybuilder';
 import { SchemaGraph } from '../../schema';
 import { GraphMetadata } from '../statistics';
 import { SelectionStateI, FocusStateI, focusState, selectionState } from './interactionSlice';
+import { VisualizationSettingsType } from '../../vis/common';
 
 // Use throughout your app instead of plain `useDispatch` and `useSelector`
 export const useAppDispatch: () => AppDispatch = useDispatch;
@@ -70,6 +71,7 @@ export const useRecentSearches: () => string[] = () => useAppSelector(recentSear
 
 // Visualization Slices
 export const useVisualization: () => VisState = () => useAppSelector(visualizationState);
+export const useActiveVisualization: () => VisualizationSettingsType | undefined = () => useAppSelector(visualizationActive);
 
 // Interaction Slices
 export const useSelection: () => SelectionStateI | undefined = () => useAppSelector(selectionState);
diff --git a/libs/shared/lib/data-access/store/visualizationSlice.ts b/libs/shared/lib/data-access/store/visualizationSlice.ts
index 217118a0e..1f206d932 100644
--- a/libs/shared/lib/data-access/store/visualizationSlice.ts
+++ b/libs/shared/lib/data-access/store/visualizationSlice.ts
@@ -1,53 +1,103 @@
 import { createSlice, PayloadAction } from '@reduxjs/toolkit';
 import type { RootState } from './store';
-import { VisualizationConfiguration } from '../../vis/common';
+import { VisualizationSettingsType } from '../../vis/common';
 import { isEqual } from 'lodash-es';
 
-export type VisStateSettings = {
-  [id: string]: VisualizationConfiguration;
-};
+export type VisStateSettings = VisualizationSettingsType[];
 export type VisState = {
-  activeVisualization?: string;
-  openVisualizations: VisStateSettings;
+  activeVisualizationIndex: number;
+  openVisualizationArray: VisStateSettings;
 };
 
 export const initialState: VisState = {
-  // activeVisualization: 'NodeLinkVis',
-  openVisualizations: {},
+  activeVisualizationIndex: -1,
+  openVisualizationArray: [],
 };
 
 export const visualizationSlice = createSlice({
   name: 'visualization',
   initialState,
   reducers: {
-    removeVisualization: (state, action: PayloadAction<string>) => {
-      if (state.openVisualizations[action.payload]) {
-        delete state.openVisualizations[action.payload];
+    removeVisualization: (state, action: PayloadAction<number | undefined>) => {
+      let index = action.payload || state.activeVisualizationIndex;
+      state.openVisualizationArray.splice(index, 1);
+      if (state.activeVisualizationIndex === index) {
+        if (state.openVisualizationArray.length === 0) state.activeVisualizationIndex = -1;
+        else {
+          state.activeVisualizationIndex = Math.max(state.openVisualizationArray.length - 1, 0);
+        }
       }
     },
-    setActiveVisualization: (state, action: PayloadAction<string>) => {
-      state.activeVisualization = action.payload;
+    setActiveVisualization: (state, action: PayloadAction<number>) => {
+      state.activeVisualizationIndex = action.payload;
     },
     setVisualizationState: (state, action: PayloadAction<VisState>) => {
-      if (action.payload.activeVisualization && !isEqual(action.payload, state)) {
-        state.activeVisualization = action.payload.activeVisualization;
-        state.openVisualizations = action.payload.openVisualizations || {};
+      if (action.payload.activeVisualizationIndex !== undefined && !isEqual(action.payload, state)) {
+        state.openVisualizationArray = action.payload.openVisualizationArray || [];
+        state.activeVisualizationIndex = action.payload.activeVisualizationIndex;
       }
     },
-    updateVisualization: (state, action: PayloadAction<{ id: string; settings: any }>) => {
+    updateVisualization: (state, action: PayloadAction<{ id: number; settings: VisualizationSettingsType }>) => {
       const { id, settings } = action.payload;
-      state.openVisualizations[id] = settings;
+      state.openVisualizationArray[id] = settings;
+    },
+    addVisualization: (state, action: PayloadAction<VisualizationSettingsType>) => {
+      state.openVisualizationArray.push(action.payload);
+      state.activeVisualizationIndex = state.openVisualizationArray.length - 1;
     },
-    reorderVisState: (state, action: PayloadAction<{ [id: string]: VisualizationConfiguration }>) => {
-      state.openVisualizations = action.payload;
+    updateActiveVisualization: (state, action: PayloadAction<VisualizationSettingsType>) => {
+      if (state.activeVisualizationIndex === -1) {
+        return;
+      }
+
+      state.openVisualizationArray[state.activeVisualizationIndex] = action.payload;
+    },
+    updateActiveVisualizationAttributes: (state, action: PayloadAction<Record<string, any>>) => {
+      if (state.activeVisualizationIndex === -1) {
+        return;
+      }
+
+      state.openVisualizationArray[state.activeVisualizationIndex] = {
+        ...state.openVisualizationArray[state.activeVisualizationIndex],
+        ...action.payload,
+      };
+    },
+    reorderVisState: (
+      state,
+      action: PayloadAction<{
+        id: number;
+        newPosition: number;
+      }>,
+    ) => {
+      const { id, newPosition } = action.payload;
+      const settingsCopy = [...state.openVisualizationArray];
+      settingsCopy.splice(newPosition, 0, settingsCopy.splice(id, 1)[0]);
+      state.openVisualizationArray = settingsCopy;
+
+      if (state.activeVisualizationIndex === id) {
+        state.activeVisualizationIndex = newPosition;
+      } else if (state.activeVisualizationIndex === newPosition) {
+        state.activeVisualizationIndex = id;
+      }
     },
   },
 });
 
-export const { removeVisualization, setActiveVisualization, setVisualizationState, updateVisualization, reorderVisState } =
-  visualizationSlice.actions;
+export const {
+  removeVisualization,
+  setActiveVisualization,
+  updateActiveVisualization,
+  setVisualizationState,
+  updateVisualization,
+  reorderVisState,
+  addVisualization,
+  updateActiveVisualizationAttributes,
+} = visualizationSlice.actions;
 
 export const visualizationState = (state: RootState) => state.visualize;
-export const visualizationAllSettings = (state: RootState) => state.visualize.openVisualizations;
-
+export const visualizationAllSettings = (state: RootState) => state.visualize.openVisualizationArray;
+export const visualizationActive = (state: RootState) =>
+  state.visualize.activeVisualizationIndex !== -1
+    ? state.visualize.openVisualizationArray?.[state.visualize.activeVisualizationIndex]
+    : undefined;
 export default visualizationSlice.reducer;
diff --git a/libs/shared/lib/inspector/InspectorPanel.tsx b/libs/shared/lib/inspector/InspectorPanel.tsx
index 48c07f40b..9d570ef29 100644
--- a/libs/shared/lib/inspector/InspectorPanel.tsx
+++ b/libs/shared/lib/inspector/InspectorPanel.tsx
@@ -1,26 +1,30 @@
 import React, { useMemo } from 'react';
 import { Button, Panel } from '../components';
-import { useFocus, useSelection } from '../data-access';
+import { useFocus, useSelection, useVisualization } from '../data-access';
 import { resultSetFocus } from '../data-access/store/interactionSlice';
 import { useDispatch } from 'react-redux';
 import { ConnectionInspector } from './ConnectionInspector';
-import { VisualizationConfigPanel } from '../vis/components/config/panel';
+import { VisualizationSettings } from '../vis/components/config/VisualizationSettings';
 import { SelectionConfig } from '../vis/components/config/SelectionConfig';
 import { SchemaDialog } from '../schema/panel/SchemaSettings';
 import { QuerySettings } from '../querybuilder/panel/querysidepanel/QuerySettings';
+import { useActiveVisualization } from '@graphpolaris/shared/lib/data-access';
 
 export function InspectorPanel(props: { children?: React.ReactNode }) {
   const buildInfo = import.meta.env.GRAPHPOLARIS_VERSION;
   const selection = useSelection();
   const focus = useFocus();
   const dispatch = useDispatch();
+  const { activeVisualizationIndex } = useVisualization();
 
   const inspector = useMemo(() => {
     if (selection) return <SelectionConfig />;
-    if (!focus) return <ConnectionInspector />;
-    if (focus.focusType === 'visualization') return <VisualizationConfigPanel />;
-    else if (focus.focusType === 'schema') return <SchemaDialog />;
-    else if (focus.focusType === 'query') return <QuerySettings />;
+    // if (!focus) return <ConnectionInspector />;
+    // if (activeVisualizationIndex !== -1) return <ConnectionInspector />;
+    return <VisualizationSettings />;
+    // if (focus.focusType === 'visualization') return <VisualizationConfigPanel />;
+    // else if (focus.focusType === 'schema') return <SchemaDialog />;
+    // else if (focus.focusType === 'query') return <QuerySettings />;
     return null;
   }, [focus, selection]);
 
diff --git a/libs/shared/lib/vis/common/types.ts b/libs/shared/lib/vis/common/types.ts
index 2d8f8bf3d..d3eda36aa 100644
--- a/libs/shared/lib/vis/common/types.ts
+++ b/libs/shared/lib/vis/common/types.ts
@@ -2,25 +2,29 @@ import { GraphQueryResult } from '../../data-access/store/graphQueryResultSlice'
 import { ML } from '../../data-access/store/mlSlice';
 import { SchemaGraph } from '../../schema';
 import type { AppDispatch } from '../../data-access';
-import { FC } from 'react';
-import { Visualizations } from '../manager';
+import { FC, ReactElement } from 'react';
 import { GraphMetadata } from '../../data-access/statistics';
 import { Node, Edge } from '../../data-access/store/graphQueryResultSlice';
+import { Visualizations } from '../components/VisualizationPanel';
 
-export type VisualizationConfiguration = { [id: string]: any };
+export type VisualizationSettingsType = {
+  id: string;
+  name: string;
+  [id: string]: any;
+};
 
-export type VISComponentType = {
+export type VISComponentType<T> = {
   displayName: keyof typeof Visualizations;
-  component: FC<VisualizationPropTypes>;
-  settings: FC<any>;
-  configuration: { [id: string]: any };
+  component: React.FC<VisualizationPropTypes<T>>;
+  settingsComponent: FC<VisualizationSettingsPropTypes<T>>;
+  settings: T;
 };
 
-export type VisualizationPropTypes = {
+export type VisualizationPropTypes<T = {}> = {
   data: GraphQueryResult;
   schema: SchemaGraph;
   ml: ML;
-  configuration: VisualizationConfiguration;
+  settings: T & VisualizationSettingsType;
   dispatch: AppDispatch;
   graphMetadata: GraphMetadata;
   updateSettings: (newSettings: any) => void;
@@ -28,6 +32,12 @@ export type VisualizationPropTypes = {
   handleSelect: (selection?: { nodes?: Node[]; edges?: Edge[] }) => void;
 };
 
+export type VisualizationSettingsPropTypes<T = {}> = {
+  settings: T & VisualizationSettingsType;
+  graphMetadata: GraphMetadata;
+  updateSettings: (val: Partial<T>) => void;
+};
+
 export type SchemaElements = {
   nodes: Node[];
   edges: Edge[];
diff --git a/libs/shared/lib/vis/components/VisualizationPanel.tsx b/libs/shared/lib/vis/components/VisualizationPanel.tsx
index 61bcfb78e..bbe2ffaac 100644
--- a/libs/shared/lib/vis/components/VisualizationPanel.tsx
+++ b/libs/shared/lib/vis/components/VisualizationPanel.tsx
@@ -1,36 +1,115 @@
-import React, { useMemo } from 'react';
-import { useGraphQueryResult, useQuerybuilderGraph } from '@graphpolaris/shared/lib/data-access';
-import VisualizationBar from './bar';
-import { VisualizationManager, VisualizationManagerType } from '../manager';
+import React, { Suspense, lazy, useEffect, useMemo, useState } from 'react';
+import {
+  Edge,
+  Node,
+  useActiveVisualization,
+  useAppDispatch,
+  useGraphQueryResult,
+  useGraphQueryResultMeta,
+  useML,
+  useQuerybuilderGraph,
+  useSchemaGraph,
+  useVisualization,
+} from '@graphpolaris/shared/lib/data-access';
+import VisualizationTabBar from './VisualizationTabBar';
 import { Recommender, NoData, Querying } from '../views';
-import { resultSetFocus } from '../../data-access/store/interactionSlice';
-import { useDispatch } from 'react-redux';
+import { resultSetFocus, resultSetSelection, unSelect } from '../../data-access/store/interactionSlice';
+import {
+  setActiveVisualization,
+  removeVisualization,
+  reorderVisState,
+  updateVisualization,
+  addVisualization,
+} from '../../data-access/store/visualizationSlice';
+import { VisualizationSettingsType, VisualizationPropTypes, VISComponentType } from '../common';
+
+type PromiseFunc = () => Promise<{ default: VISComponentType<any> }>;
+export const Visualizations: Record<string, PromiseFunc> = {
+  TableVis: () => import('../visualizations/tablevis/tablevis'),
+  PaohVis: () => import('../visualizations/paohvis/paohvis'),
+  // PaohVis: () => Promise.resolve({ default: Paohviz }),
+  RawJSONVis: () => import('../visualizations/rawjsonvis/rawjsonvis'),
+  NodeLinkVis: () => import('../visualizations/nodelinkvis/nodelinkvis'),
+  // NodeLinkVis: () => Promise.resolve({ default: NodeLinkComponent }),
+  MatrixVis: () => import('../visualizations/matrixvis/matrixvis'),
+  SemanticSubstratesVis: () => import('../visualizations/semanticsubstratesvis/semanticsubstratesvis'),
+  MapVis: () => import('../visualizations/mapvis/mapvis'),
+};
+export const VISUALIZATION_TYPES: string[] = Object.keys(Visualizations);
 
 export const VisualizationPanel = ({ fullSize }: { fullSize: () => void }) => {
-  const manager = VisualizationManager();
   const query = useQuerybuilderGraph();
   const graphQueryResult = useGraphQueryResult();
-  const dispatch = useDispatch();
-
-  const renderContent = useMemo(() => {
-    if (graphQueryResult.queryingBackend) {
-      return <Querying />;
-    } else if (graphQueryResult.nodes.length === 0) {
-      return <NoData dataAvailable={query.nodes.length > 0} />;
-    } else if (manager.tabs.length === 0) {
-      return <Recommender onClick={(id: string) => manager.changeActive(id)} />;
+  const dispatch = useAppDispatch();
+  const { activeVisualizationIndex, openVisualizationArray } = useVisualization();
+  const activeVisualization = useActiveVisualization();
+  const ml = useML();
+  const schema = useSchemaGraph();
+  const graphMetadata = useGraphQueryResultMeta();
+  const [viz, setViz] = useState<{ component: React.FC<VisualizationPropTypes> } | undefined>(undefined);
+
+  useEffect(() => {
+    loadVisualization();
+  }, [activeVisualizationIndex]);
+
+  const loadVisualization = async (add = false) => {
+    if (!activeVisualization) {
+      setViz(undefined);
+      return;
+    }
+    const componentModule = await Visualizations[activeVisualization.id]();
+    const component = componentModule.default;
+
+    if (add) {
+      dispatch(addVisualization(component.settings));
+    }
+    setViz({ component: component.component });
+  };
+
+  const handleSelect = (selection?: { nodes?: Node[]; edges?: Edge[] }) => {
+    if (selection?.nodes && selection.nodes.length > 0) dispatch(resultSetSelection(selection.nodes));
+    else dispatch(unSelect());
+  };
+
+  const updateSettings = (newSettings: Record<string, any>) => {
+    if (activeVisualizationIndex) {
+      const updatedSettings = { ...openVisualizationArray[activeVisualizationIndex], ...newSettings };
+      dispatch(updateVisualization({ id: activeVisualizationIndex, settings: updatedSettings }));
     }
-    return <div className="w-full h-full flex">{manager.renderComponent()}</div>;
-  }, [graphQueryResult, manager]);
+  };
 
   return (
     <div
       className="vis-panel h-full w-full flex flex-col border bg-light"
       onMouseDownCapture={() => dispatch(resultSetFocus({ focusType: 'visualization' }))}
     >
-      <VisualizationBar manager={manager} fullSize={fullSize} />
+      <VisualizationTabBar fullSize={fullSize} />
       <div className="grow overflow-y-auto" style={graphQueryResult.nodes.length === 0 ? { overflow: 'hidden' } : {}}>
-        {renderContent}
+        {graphQueryResult.queryingBackend ? (
+          <Querying />
+        ) : graphQueryResult.nodes.length === 0 ? (
+          <NoData dataAvailable={query.nodes.length > 0} />
+        ) : openVisualizationArray.length === 0 ? (
+          <Recommender />
+        ) : (
+          <div className="w-full h-full flex">
+            <Suspense fallback={<div>Loading...</div>}>
+              {!!viz && !!activeVisualization && (
+                <viz.component
+                  data={graphQueryResult}
+                  schema={schema}
+                  ml={ml}
+                  settings={activeVisualization}
+                  dispatch={dispatch}
+                  handleSelect={handleSelect}
+                  graphMetadata={graphMetadata}
+                  updateSettings={updateSettings}
+                  handleHover={() => {}}
+                />
+              )}
+            </Suspense>
+          </div>
+        )}
       </div>
     </div>
   );
diff --git a/libs/shared/lib/vis/components/VisualizationTabBar.tsx b/libs/shared/lib/vis/components/VisualizationTabBar.tsx
new file mode 100644
index 000000000..1c39bdc3f
--- /dev/null
+++ b/libs/shared/lib/vis/components/VisualizationTabBar.tsx
@@ -0,0 +1,120 @@
+import React, { useState } from 'react';
+import { Button, DropdownContainer, DropdownItem, DropdownItemContainer, DropdownTrigger } from '../../components';
+import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../components/tooltip';
+import { Add, Close, Fullscreen } from '@mui/icons-material';
+import { ControlContainer } from '../../components/controls';
+import { Tabs, Tab } from '../../components/tabs';
+import { useAppDispatch, useVisualization } from '../../data-access';
+import { addVisualization, removeVisualization, reorderVisState, setActiveVisualization } from '../../data-access/store/visualizationSlice';
+import { Visualizations } from './VisualizationPanel';
+
+export default function VisualizationTabBar(props: { fullSize: () => void }) {
+  const { activeVisualizationIndex, openVisualizationArray } = useVisualization();
+  const [open, setOpen] = useState(false);
+  const dispatch = useAppDispatch();
+
+  const handleDragStart = (e: React.DragEvent<HTMLDivElement>, i: number) => {
+    e.dataTransfer.setData('text/plain', i.toString());
+  };
+
+  const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
+    e.preventDefault();
+  };
+
+  const handleDrop = (e: React.DragEvent<HTMLDivElement>, i: number) => {
+    e.preventDefault();
+    const draggedVisIndex = e.dataTransfer.getData('text/plain');
+    dispatch(reorderVisState({ id: Number(draggedVisIndex), newPosition: i }));
+  };
+
+  const onSelect = async (id?: number) => {
+    if (id === undefined) return;
+    dispatch(setActiveVisualization(id));
+  };
+
+  const onDelete = (id: number) => {
+    dispatch(removeVisualization(id));
+  };
+
+  return (
+    <div className="sticky shrink-0 top-0 flex items-stretch justify-between h-7 bg-secondary-100 border-b border-secondary-200 max-w-full">
+      <div className="flex items-center">
+        <h1 className="text-xs font-semibold text-secondary-600 px-2 truncate">Visualization</h1>
+      </div>
+      <div className="items-center shrink-0 px-0.5">
+        <TooltipProvider delayDuration={0}>
+          <Tooltip>
+            <TooltipTrigger>
+              <DropdownContainer open={open} onOpenChange={setOpen}>
+                <DropdownTrigger onClick={() => setOpen((v) => !v)}>
+                  <Button as={'a'} variantType="secondary" variant="ghost" size="xs" iconComponent={<Add />} onClick={() => {}} />
+                </DropdownTrigger>
+                <DropdownItemContainer>
+                  {Object.keys(Visualizations).map((name, i) => (
+                    <DropdownItem
+                      value={name}
+                      key={name}
+                      className=""
+                      onClick={async (e) => {
+                        // onSelect(i);
+                        const component = await Visualizations[name]();
+                        dispatch(addVisualization({ ...component.default.settings, name: name, id: name }));
+                        setOpen(false);
+                      }}
+                    ></DropdownItem>
+                  ))}
+                </DropdownItemContainer>
+              </DropdownContainer>
+            </TooltipTrigger>
+            <TooltipContent side={'top'}>
+              <p>Add visualization</p>
+            </TooltipContent>
+          </Tooltip>
+        </TooltipProvider>
+      </div>
+      <Tabs>
+        {openVisualizationArray.map((vis, i) => {
+          const isActive = activeVisualizationIndex === i;
+          return (
+            <Tab
+              key={i}
+              activeTab={isActive}
+              text={vis.name}
+              onClick={() => onSelect(i)}
+              onDragStart={(e) => handleDragStart(e, i)}
+              onDragOver={(e) => handleDragOver(e)}
+              onDrop={(e) => handleDrop(e, i)}
+              draggable
+            >
+              <Button
+                variantType="secondary"
+                variant="ghost"
+                rounded
+                size="2xs"
+                iconComponent={<Close />}
+                onClick={(e) => {
+                  e.stopPropagation();
+                  onDelete(i);
+                }}
+              />
+            </Tab>
+          );
+        })}
+      </Tabs>
+      <div className="shrink-0 sticky right-0 px-0.5 ml-auto items-center flex">
+        <ControlContainer>
+          <TooltipProvider delayDuration={0}>
+            <Tooltip>
+              <TooltipTrigger asChild>
+                <Button variantType="secondary" variant="ghost" size="xs" iconComponent={<Fullscreen />} onClick={props.fullSize} />
+              </TooltipTrigger>
+              <TooltipContent side={'top'}>
+                <p>Full screen</p>
+              </TooltipContent>
+            </Tooltip>
+          </TooltipProvider>
+        </ControlContainer>
+      </div>
+    </div>
+  );
+}
diff --git a/libs/shared/lib/vis/components/bar.tsx b/libs/shared/lib/vis/components/bar.tsx
deleted file mode 100644
index fa1c79de7..000000000
--- a/libs/shared/lib/vis/components/bar.tsx
+++ /dev/null
@@ -1,115 +0,0 @@
-import React from 'react';
-import { Button, DropdownItem } from '../../components';
-import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../components/tooltip';
-import { Add, Close, Fullscreen } from '@mui/icons-material';
-import { ControlContainer } from '../../components/controls';
-import { Visualizations } from '../manager';
-import { VisualizationManagerType } from '../manager';
-import { Tabs, Tab } from '../../components/tabs';
-import { Popover, PopoverContent, PopoverTrigger } from '../../components/layout/Popover';
-
-type Props = {
-  manager: VisualizationManagerType;
-  fullSize: () => void;
-};
-
-export default function VisualizationBar({ manager, fullSize }: Props) {
-  const [open, setOpen] = React.useState(false);
-
-  const handleDragStart = (e: React.DragEvent<HTMLDivElement>, visId: string) => {
-    e.dataTransfer.setData('text/plain', visId);
-  };
-
-  const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
-    e.preventDefault();
-  };
-
-  const handleDrop = (e: React.DragEvent<HTMLDivElement>, dropVisId: string) => {
-    e.preventDefault();
-    const draggedVisId = e.dataTransfer.getData('text/plain');
-    manager.reorderVisualizations({ draggedVisId, dropVisId });
-    manager.changeActive(draggedVisId);
-  };
-
-  return (
-    <div className="sticky shrink-0 top-0 flex items-stretch justify-between h-7 bg-secondary-100 border-b border-secondary-200 max-w-full">
-      <div className="flex items-center">
-        <h1 className="text-xs font-semibold text-secondary-600 px-2 truncate">Visualization</h1>
-      </div>
-      <div className="items-center shrink-0 px-0.5">
-        <TooltipProvider delayDuration={0}>
-          <Tooltip>
-            <TooltipTrigger>
-              <Popover open={open} onOpenChange={setOpen}>
-                <PopoverTrigger onClick={() => setOpen((v) => !v)}>
-                  <Button as={'a'} variantType="secondary" variant="ghost" size="xs" iconComponent={<Add />} onClick={() => {}} />
-                </PopoverTrigger>
-                <PopoverContent>
-                  <div className="bg-light p-1 rounded border">
-                    {Object.keys(Visualizations).map((key) => (
-                      <DropdownItem
-                        value={key}
-                        key={key}
-                        className="text-sm px-2 py-1 rounded cursor-pointer hover:bg-secondary-200"
-                        onClick={(e) => {
-                          manager.changeActive(key);
-                          setOpen(false);
-                        }}
-                      ></DropdownItem>
-                    ))}
-                  </div>
-                </PopoverContent>
-              </Popover>
-            </TooltipTrigger>
-            <TooltipContent side={'top'}>
-              <p>Add visualization</p>
-            </TooltipContent>
-          </Tooltip>
-        </TooltipProvider>
-      </div>
-      <Tabs>
-        {manager.tabs.map((visId: string) => {
-          const isActive = manager.activeVisualization === visId;
-          return (
-            <Tab
-              key={visId}
-              activeTab={isActive}
-              text={visId}
-              onClick={() => manager.changeActive(visId)}
-              onDragStart={(e) => handleDragStart(e, visId)}
-              onDragOver={(e) => handleDragOver(e)}
-              onDrop={(e) => handleDrop(e, visId)}
-              draggable
-            >
-              <Button
-                variantType="secondary"
-                variant="ghost"
-                rounded
-                size="2xs"
-                iconComponent={<Close />}
-                onClick={(e) => {
-                  e.stopPropagation();
-                  manager.deleteVisualization(visId);
-                }}
-              />
-            </Tab>
-          );
-        })}
-      </Tabs>
-      <div className="shrink-0 sticky right-0 px-0.5 ml-auto items-center flex">
-        <ControlContainer>
-          <TooltipProvider delayDuration={0}>
-            <Tooltip>
-              <TooltipTrigger asChild>
-                <Button variantType="secondary" variant="ghost" size="xs" iconComponent={<Fullscreen />} onClick={fullSize} />
-              </TooltipTrigger>
-              <TooltipContent side={'top'}>
-                <p>Full screen</p>
-              </TooltipContent>
-            </Tooltip>
-          </TooltipProvider>
-        </ControlContainer>
-      </div>
-    </div>
-  );
-}
diff --git a/libs/shared/lib/vis/components/config/ActiveVisualizationConfig.tsx b/libs/shared/lib/vis/components/config/ActiveVisualizationConfig.tsx
deleted file mode 100644
index 38fe19fa9..000000000
--- a/libs/shared/lib/vis/components/config/ActiveVisualizationConfig.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import { Delete } from '@mui/icons-material';
-import { Button, Input, Panel } from '../../..';
-import { VisualizationManagerType, VISUALIZATION_TYPES } from '../../manager';
-import { SettingsHeader } from './components';
-
-type Props = {
-  manager: VisualizationManagerType;
-};
-
-export const ActiveVisualizationConfig = ({ manager }: Props) => {
-  return (
-    <>
-      <div className="flex justify-between items-center px-4 py-2">
-        <span className="text-xs font-bold">Visualization</span>
-        <Button
-          variantType="secondary"
-          variant="ghost"
-          size="xs"
-          iconComponent={<Delete />}
-          onClick={() => {
-            if (manager.activeVisualization) manager.deleteVisualization(manager.activeVisualization);
-          }}
-        />
-      </div>
-      <div className="flex justify-between items-center px-4 py-1">
-        <span className="text-xs font-normal">Type</span>
-        <div className="w-36">
-          <Input type="dropdown" size="xs" options={VISUALIZATION_TYPES} value={manager.activeVisualization} onChange={() => {}} />
-        </div>
-      </div>
-      <div className="flex justify-between items-center px-4 py-1">
-        <span className="text-xs font-normal">Name</span>
-        <input type="text" className="border rounded text-xs w-36" value={manager.activeVisualization} onChange={() => {}} />
-      </div>
-      {manager.activeVisualization && (
-        <div className="border-b p-4 w-full">
-          <SettingsHeader name="Configuration" />
-          {manager.renderSettings()}
-        </div>
-      )}
-    </>
-  );
-};
diff --git a/libs/shared/lib/vis/components/config/SelectionConfig.tsx b/libs/shared/lib/vis/components/config/SelectionConfig.tsx
index 496bad2c7..7d41cf4a1 100644
--- a/libs/shared/lib/vis/components/config/SelectionConfig.tsx
+++ b/libs/shared/lib/vis/components/config/SelectionConfig.tsx
@@ -2,7 +2,6 @@ import { SelectionStateI, unSelect } from '@graphpolaris/shared/lib/data-access/
 import { Delete } from '@mui/icons-material';
 import { useDispatch } from 'react-redux';
 import { Button, EntityPill, useSelection } from '../../..';
-import { VISUALIZATION_TYPES } from '../../manager';
 import { SettingsHeader } from './components';
 
 export const SelectionConfig = () => {
diff --git a/libs/shared/lib/vis/components/config/VisualizationSettings.tsx b/libs/shared/lib/vis/components/config/VisualizationSettings.tsx
new file mode 100644
index 000000000..9fdb7269d
--- /dev/null
+++ b/libs/shared/lib/vis/components/config/VisualizationSettings.tsx
@@ -0,0 +1,113 @@
+import React, { Suspense, useEffect, useState } from 'react';
+import { Delete } from '@mui/icons-material';
+import {
+  Button,
+  Input,
+  VISUALIZATION_TYPES,
+  Visualizations,
+  useAppDispatch,
+  useGraphQueryResultMeta,
+  useVisualization,
+  useActiveVisualization,
+} from '../../..';
+import { SettingsHeader } from './components';
+import {
+  removeVisualization,
+  updateActiveVisualization,
+  updateVisualization,
+  updateActiveVisualizationAttributes,
+} from '@graphpolaris/shared/lib/data-access/store/visualizationSlice';
+import { VisualizationSettingsPropTypes, VisualizationSettingsType } from '../../common';
+
+type Props = {};
+
+export function VisualizationSettings({}: Props) {
+  // const manager = VisualizationManager();
+  // const activeVisualization = useActiveVisualization();
+  const { activeVisualizationIndex, openVisualizationArray } = useVisualization();
+  const activeVisualization = openVisualizationArray[activeVisualizationIndex];
+  const graphMetadata = useGraphQueryResultMeta();
+
+  const dispatch = useAppDispatch();
+
+  const [component, setComponent] = useState<
+    | undefined
+    | {
+        component: React.FC<VisualizationSettingsPropTypes>;
+      }
+  >(undefined);
+
+  useEffect(() => {
+    loadVisualization(activeVisualization);
+  }, [activeVisualization]);
+
+  const loadVisualization = async (vis?: VisualizationSettingsType) => {
+    if (!vis) {
+      setComponent(undefined);
+      return;
+    }
+
+    const componentModule = await Visualizations[vis.id]();
+    const component = componentModule.default;
+
+    setComponent({
+      component: component.settingsComponent,
+    });
+  };
+
+  const updateSettings = (newSettings: Record<string, any>) => {
+    if (activeVisualization) {
+      dispatch(updateActiveVisualizationAttributes(newSettings));
+    }
+  };
+
+  return (
+    <div className="flex flex-col w-full">
+      <div className="text-sm px-4 py-2 flex flex-col gap-1">
+        <div className="flex justify-between items-center">
+          <span className="font-bold">Visualization</span>
+          <Button
+            variantType="secondary"
+            variant="ghost"
+            size="xs"
+            iconComponent={<Delete />}
+            onClick={() => {
+              if (activeVisualization) removeVisualization();
+            }}
+          />
+        </div>
+        <Input
+          type="dropdown"
+          size="xs"
+          options={VISUALIZATION_TYPES}
+          value={activeVisualization?.id}
+          onChange={(val) => {
+            updateSettings({ id: val });
+          }}
+          label="Type"
+          inline
+        />
+        <Input
+          type="text"
+          size="sm"
+          value={activeVisualization?.name || ''}
+          onChange={(val) => {
+            updateSettings({ name: val });
+          }}
+          label="Name"
+          inline
+        />
+        {activeVisualization && (
+          <>
+            <SettingsHeader name="Visualization Settings" />
+            <Suspense fallback={<div>Loading...</div>}>
+              {component && component.component && activeVisualization && (
+                <component.component settings={activeVisualization} graphMetadata={graphMetadata} updateSettings={updateSettings} />
+              )}
+            </Suspense>
+          </>
+        )}
+      </div>
+    </div>
+  );
+}
diff --git a/libs/shared/lib/vis/components/config/components.tsx b/libs/shared/lib/vis/components/config/components.tsx
index 842f508ce..6f704987c 100644
--- a/libs/shared/lib/vis/components/config/components.tsx
+++ b/libs/shared/lib/vis/components/config/components.tsx
@@ -17,7 +17,7 @@ type SettingsHeaderProps = {
 export function SettingsHeader({ name, icon, onClickIcon }: SettingsHeaderProps) {
   return (
     <div className="flex justify-between items-center">
-      <span className="text-xs font-bold">{name}</span>
+      <span className="text-sm font-bold">{name}</span>
       {icon && icon}
     </div>
   );
diff --git a/libs/shared/lib/vis/components/config/index.tsx b/libs/shared/lib/vis/components/config/index.tsx
index 4bf7db1e4..028738a4c 100644
--- a/libs/shared/lib/vis/components/config/index.tsx
+++ b/libs/shared/lib/vis/components/config/index.tsx
@@ -1,2 +1,2 @@
-export { VisualizationConfigPanel as ConfigPanel } from './panel';
+export { VisualizationSettings as VisualizationConfigPanel } from './VisualizationSettings';
 export { SettingsContainer, SettingsHeader } from './components';
diff --git a/libs/shared/lib/vis/components/config/panel.tsx b/libs/shared/lib/vis/components/config/panel.tsx
deleted file mode 100644
index 4f0bd9e03..000000000
--- a/libs/shared/lib/vis/components/config/panel.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import React from 'react';
-import { Button } from '../../../components';
-import { VisualizationManager, VisualizationManagerType } from '../../manager';
-import { useSelection, useSessionCache } from '../../../data-access';
-import { SelectionConfig } from './SelectionConfig';
-import { ActiveVisualizationConfig } from './ActiveVisualizationConfig';
-
-type Props = {};
-
-export function VisualizationConfigPanel({}: Props) {
-  const manager = VisualizationManager();
-
-  return (
-    <div className="flex flex-col w-full">
-      <ActiveVisualizationConfig manager={manager}></ActiveVisualizationConfig>
-    </div>
-  );
-}
diff --git a/libs/shared/lib/vis/manager/VisualizationManager.tsx b/libs/shared/lib/vis/manager/VisualizationManager.tsx
deleted file mode 100644
index 94866c583..000000000
--- a/libs/shared/lib/vis/manager/VisualizationManager.tsx
+++ /dev/null
@@ -1,159 +0,0 @@
-import React, { useState, useMemo, useEffect, Suspense } from 'react';
-import { VISComponentType, VisualizationConfiguration } from '../common';
-import {
-  removeVisualization,
-  reorderVisState,
-  setActiveVisualization,
-  updateVisualization,
-} from '../../data-access/store/visualizationSlice';
-import {
-  useAppDispatch,
-  useGraphQueryResult,
-  useGraphQueryResultMeta,
-  useML,
-  useSchemaGraph,
-  useSessionCache,
-  useVisualization,
-} from '../../data-access';
-import { VisualizationManagerType } from '.';
-import { Node, Edge } from '../../data-access/store/graphQueryResultSlice';
-import { SelectionStateI, resultSetSelection, unSelect } from '../../data-access/store/interactionSlice';
-import { NodeLinkComponent } from '../visualizations';
-
-export const Visualizations: Record<string, Function> = {
-  TableVis: () => import('../visualizations/tablevis/tablevis'),
-  PaohVis: () => import('../visualizations/paohvis/paohvis'),
-  // PaohVis: () => Promise.resolve({ default: PaohVisComponent }),
-  RawJSONVis: () => import('../visualizations/rawjsonvis/rawjsonvis'),
-  // NodeLinkVis: () => import('../visualizations/nodelinkvis/nodelinkvis'),
-  NodeLinkVis: () => Promise.resolve({ default: NodeLinkComponent }),
-  MatrixVis: () => import('../visualizations/matrixvis/matrixvis'),
-  SemanticSubstratesVis: () => import('../visualizations/semanticsubstratesvis/semanticsubstratesvis'),
-  MapVis: () => import('../visualizations/mapvis/mapvis'),
-};
-
-export const VISUALIZATION_TYPES: string[] = Object.keys(Visualizations);
-
-export const VisualizationManager = (): VisualizationManagerType => {
-  const dispatch = useAppDispatch();
-  const session = useSessionCache();
-  const ml = useML();
-  const schema = useSchemaGraph();
-  const graphQueryResult = useGraphQueryResult();
-  const graphMetadata = useGraphQueryResultMeta();
-  const { activeVisualization, openVisualizations } = useVisualization();
-
-  const [configuration, setConfiguration] = useState<any>();
-  const [visualization, setVisualization] = useState<VISComponentType>();
-  const [selected, setSelected] = useState<any>();
-  const activeType = useMemo(
-    () => (activeVisualization ? openVisualizations[activeVisualization]?.displayName : undefined),
-    [openVisualizations, activeVisualization],
-  );
-  const tabs = useMemo(() => (Object.keys(openVisualizations).length ? Object.keys(openVisualizations) : []), [openVisualizations]);
-
-  useEffect(() => {
-    loadVisualization();
-  }, [activeVisualization]);
-
-  const loadVisualization = async () => {
-    if (activeVisualization && Visualizations[activeVisualization]) {
-      const componentModule = await Visualizations[activeVisualization]();
-      const component = componentModule.default;
-
-      if (!(activeVisualization in Object.keys(openVisualizations))) {
-        // Visualization doesn't yet exist so add its configuration
-        const configuration = component.configuration;
-        dispatch(updateVisualization({ id: activeVisualization, settings: configuration }));
-        setConfiguration(configuration);
-      } else {
-        setConfiguration(openVisualizations[activeVisualization]);
-      }
-
-      setVisualization(component);
-    }
-  };
-
-  const changeActive = (id: string) => {
-    dispatch(setActiveVisualization(id));
-  };
-
-  const deleteVisualization = (id: string) => {
-    dispatch(removeVisualization(id));
-    if (Object.keys(openVisualizations).length > 0) {
-      const newActive = tabs.find((v: string) => id !== v);
-      changeActive(newActive || '');
-    }
-  };
-
-  const reorderVisualizations = ({ draggedVisId, dropVisId }: { draggedVisId: string; dropVisId: string }) => {
-    const settingsCopy = { ...openVisualizations };
-    const keys = Object.keys(settingsCopy);
-    const draggedIndex = keys.indexOf(draggedVisId);
-    const dropIndex = keys.indexOf(dropVisId);
-
-    if (draggedIndex !== -1 && dropIndex !== -1) {
-      keys.splice(dropIndex, 0, draggedVisId);
-      const newSettings: { [id: string]: VisualizationConfiguration } = {};
-      keys.forEach((key) => {
-        newSettings[key] = settingsCopy[key];
-      });
-
-      dispatch(reorderVisState(newSettings));
-    }
-  };
-
-  const handleSelect = (selection?: { nodes?: Node[]; edges?: Edge[] }) => {
-    if (selection?.nodes && selection.nodes.length > 0) dispatch(resultSetSelection(selection.nodes));
-    else dispatch(unSelect());
-  };
-
-  const updateSettings = (newSettings: Record<string, any>) => {
-    if (activeVisualization) {
-      const updatedSettings = { ...configuration, ...newSettings };
-      setConfiguration(updatedSettings);
-      dispatch(updateVisualization({ id: activeVisualization, settings: updatedSettings }));
-    }
-  };
-
-  const renderSettings = () => {
-    return (
-      visualization?.settings &&
-      configuration && (
-        <visualization.settings configuration={configuration} graphMetadata={graphMetadata} updateSettings={updateSettings} />
-      )
-    );
-  };
-
-  // TODO: we should remove the renderable part of this useFunction into its own component, since this here is an anti-pattern
-  const renderComponent = () => {
-    return (
-      <Suspense fallback={<div>Loading...</div>}>
-        {visualization?.component && configuration && (
-          <visualization.component
-            data={graphQueryResult}
-            schema={schema}
-            ml={ml}
-            configuration={configuration}
-            dispatch={dispatch}
-            handleSelect={handleSelect}
-            graphMetadata={graphMetadata}
-            updateSettings={updateSettings}
-            handleHover={() => {}}
-          />
-        )}
-      </Suspense>
-    );
-  };
-
-  return {
-    renderComponent,
-    renderSettings,
-    activeVisualization,
-    activeType,
-    tabs,
-    changeActive,
-    reorderVisualizations,
-    deleteVisualization,
-  };
-};
diff --git a/libs/shared/lib/vis/manager/index.ts b/libs/shared/lib/vis/manager/index.ts
deleted file mode 100644
index 96616a248..000000000
--- a/libs/shared/lib/vis/manager/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { VisualizationManager, Visualizations, VISUALIZATION_TYPES } from './VisualizationManager';
-export type { VisualizationManagerType } from './manager.types';
diff --git a/libs/shared/lib/vis/manager/manager.types.ts b/libs/shared/lib/vis/manager/manager.types.ts
deleted file mode 100644
index fca458010..000000000
--- a/libs/shared/lib/vis/manager/manager.types.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import React from 'react';
-
-export type VisualizationManagerType = {
-  renderComponent: () => React.ReactNode;
-  renderSettings: () => React.ReactNode;
-  activeVisualization: string | undefined;
-  activeType: string | undefined;
-  tabs: string[];
-  changeActive: (id: string) => void;
-  reorderVisualizations: (args: { draggedVisId: string; dropVisId: string }) => void;
-  deleteVisualization: (id: string) => void;
-};
diff --git a/libs/shared/lib/vis/views/noData.tsx b/libs/shared/lib/vis/views/NoData.tsx
similarity index 100%
rename from libs/shared/lib/vis/views/noData.tsx
rename to libs/shared/lib/vis/views/NoData.tsx
diff --git a/libs/shared/lib/vis/views/querying.tsx b/libs/shared/lib/vis/views/Querying.tsx
similarity index 100%
rename from libs/shared/lib/vis/views/querying.tsx
rename to libs/shared/lib/vis/views/Querying.tsx
diff --git a/libs/shared/lib/vis/views/recommender.tsx b/libs/shared/lib/vis/views/Recommender.tsx
similarity index 62%
rename from libs/shared/lib/vis/views/recommender.tsx
rename to libs/shared/lib/vis/views/Recommender.tsx
index 5f85f9a0d..a021353d0 100644
--- a/libs/shared/lib/vis/views/recommender.tsx
+++ b/libs/shared/lib/vis/views/Recommender.tsx
@@ -1,10 +1,12 @@
 import React from 'react';
 import Info from '../../components/info';
-import { Visualizations } from '../manager';
+import { addVisualization } from '../../data-access/store/visualizationSlice';
+import { useAppDispatch } from '../../data-access';
+import { Visualizations } from '../components/VisualizationPanel';
 
-type Props = { onClick: (id: string) => void };
+export function Recommender() {
+  const dispatch = useAppDispatch();
 
-export function Recommender({ onClick }: Props) {
   return (
     <div className="p-4">
       <span className="text-md">Select a visualization</span>
@@ -13,9 +15,10 @@ export function Recommender({ onClick }: Props) {
           <div
             key={name}
             className="p-4 cursor-pointer border hover:bg-secondary-100"
-            onClick={(e) => {
+            onClick={async (e) => {
               e.preventDefault();
-              onClick(name);
+              const component = await Visualizations[name]();
+              dispatch(addVisualization({ ...component.default.settings, name: name, id: name }));
             }}
           >
             <div className="flex items-center justify-between">
diff --git a/libs/shared/lib/vis/views/index.tsx b/libs/shared/lib/vis/views/index.tsx
index de85438c8..d16d4d610 100644
--- a/libs/shared/lib/vis/views/index.tsx
+++ b/libs/shared/lib/vis/views/index.tsx
@@ -1,3 +1,3 @@
-export { NoData } from './noData';
-export { Recommender } from './recommender';
-export { Querying } from './querying';
+export { NoData } from './NoData';
+export { Recommender } from './Recommender';
+export { Querying } from './Querying';
diff --git a/libs/shared/lib/vis/visualizations/mapvis/MapSettings.tsx b/libs/shared/lib/vis/visualizations/mapvis/MapSettings.tsx
new file mode 100644
index 000000000..5e411a08c
--- /dev/null
+++ b/libs/shared/lib/vis/visualizations/mapvis/MapSettings.tsx
@@ -0,0 +1,63 @@
+import React, { useMemo } from 'react';
+import { SettingsContainer } from '../../components/config';
+import { layerTypes } from './components/layers';
+import { Input } from '../../..';
+import { VisualizationSettingsPropTypes } from '../../common';
+import { MapProps } from './mapvis';
+
+export const MapSettings = ({ settings, graphMetadata, updateSettings }: VisualizationSettingsPropTypes<MapProps>) => {
+  // const spatialAttributes = useMemo(() => {
+  //   if (!settings.node) return [];
+  //   return Object.entries(graphMetadata.nodes.types[settings.node].attributes)
+  //     .filter((kv) => kv[1].dimension === 'spatial')
+  //     .map((kv) => kv[0]);
+  // }, [settings.node]);
+  const spatialAttributes = useMemo(() => {
+    if (!settings.node) return [];
+    return Object.entries(graphMetadata.nodes.types[settings.node].attributes).map((kv) => kv[0]);
+  }, [settings.node]);
+
+  return (
+    <SettingsContainer>
+      <Input
+        label="Data layer"
+        type="dropdown"
+        inline
+        value={settings.layer}
+        options={Object.keys(layerTypes)}
+        onChange={(val) => updateSettings({ layer: val as string })}
+      />
+
+      <Input
+        label="Node Label"
+        type="dropdown"
+        inline
+        value={settings.node}
+        options={[...Object.keys(graphMetadata.nodes.types)]}
+        disabled={Object.keys(graphMetadata.nodes.types).length < 1}
+        onChange={(val) => {
+          updateSettings({ node: val as string });
+        }}
+      />
+      <Input
+        label="Latitude Location"
+        type="dropdown"
+        inline
+        value={settings.lat}
+        options={[...spatialAttributes]}
+        disabled={!settings.node || spatialAttributes.length < 1}
+        onChange={(val) => updateSettings({ lat: val as string })}
+      />
+
+      <Input
+        inline
+        label="Longitude Location accessor"
+        type="dropdown"
+        value={settings.lon}
+        options={[...spatialAttributes]}
+        disabled={!settings.node || spatialAttributes.length < 1}
+        onChange={(val) => updateSettings({ lon: val as string })}
+      />
+    </SettingsContainer>
+  );
+};
diff --git a/libs/shared/lib/vis/visualizations/mapvis/configuration.tsx b/libs/shared/lib/vis/visualizations/mapvis/configuration.tsx
deleted file mode 100644
index b295e90df..000000000
--- a/libs/shared/lib/vis/visualizations/mapvis/configuration.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import React, { useMemo } from 'react';
-import { SettingsContainer } from '../../components/config';
-import { layerTypes } from './components/layers';
-import { Input } from '../../..';
-import { GraphMetadata } from '@graphpolaris/shared/lib/data-access/statistics';
-import { MapProps } from './mapvis';
-
-export const MapSettings = ({
-  configuration,
-  graphMetadata,
-  updateSettings,
-}: {
-  configuration: MapProps;
-  graphMetadata: GraphMetadata;
-  updateSettings: (val: any) => void;
-}) => {
-  // const spatialAttributes = useMemo(() => {
-  //   if (!configuration.node) return [];
-  //   return Object.entries(graphMetadata.nodes.types[configuration.node].attributes)
-  //     .filter((kv) => kv[1].dimension === 'spatial')
-  //     .map((kv) => kv[0]);
-  // }, [configuration.node]);
-  const spatialAttributes = useMemo(() => {
-    if (!configuration.node) return [];
-    return Object.entries(graphMetadata.nodes.types[configuration.node].attributes).map((kv) => kv[0]);
-  }, [configuration.node]);
-
-  return (
-    <SettingsContainer>
-      <span className="text-xs font-semibold">Data layer</span>
-      <Input
-        type="dropdown"
-        value={configuration.layer}
-        options={Object.keys(layerTypes)}
-        onChange={(val) => updateSettings({ layer: val })}
-      />
-
-      <span className="text-xs font-semibold">Node Label</span>
-      <Input
-        type="dropdown"
-        value={configuration.node}
-        options={[...Object.keys(graphMetadata.nodes.types)]}
-        disabled={Object.keys(graphMetadata.nodes.types).length < 1}
-        onChange={(val) => updateSettings({ node: val })}
-      />
-      <span className="text-xs font-semibold">Location accessor (lat)</span>
-      <Input
-        type="dropdown"
-        value={configuration.lat}
-        options={[...spatialAttributes]}
-        disabled={!configuration.node || spatialAttributes.length < 1}
-        onChange={(val) => updateSettings({ lat: val })}
-      />
-
-      <span className="text-xs font-semibold">Location accessor (lon)</span>
-      <Input
-        type="dropdown"
-        value={configuration.lon}
-        options={[...spatialAttributes]}
-        disabled={!configuration.node || spatialAttributes.length < 1}
-        onChange={(val) => updateSettings({ lon: val })}
-      />
-    </SettingsContainer>
-  );
-};
diff --git a/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx b/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx
index 56d182548..c2d00d429 100644
--- a/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx
+++ b/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx
@@ -6,16 +6,16 @@ import { Coordinate, Layer } from './mapvis.types';
 import { VISComponentType, VisualizationPropTypes } from '../../common';
 import { layerTypes } from './components/layers';
 import { createBaseMap } from './components/BaseMap';
-import { MapSettings } from './configuration';
+import { MapSettings } from './MapSettings';
 
 export type MapProps = {
-  layer: undefined | string;
+  layer: string;
   node: undefined | string;
-  lat: undefined | string;
-  lon: undefined | string;
+  lat: string;
+  lon: string;
 };
 
-const configuration: MapProps = {
+const settings: MapProps = {
   layer: 'node',
   node: undefined,
   lat: 'gp_latitude',
@@ -34,7 +34,7 @@ const FLY_SPEED = 1000;
 
 const baseLayer = createBaseMap();
 
-export const MapVis = ({ data, configuration, updateSettings, graphMetadata }: VisualizationPropTypes) => {
+export const MapVis = ({ data, settings, updateSettings, graphMetadata }: VisualizationPropTypes<MapProps>) => {
   const [layer, setLayer] = React.useState<Layer | undefined>(undefined);
   const [viewport, setViewport] = React.useState<Record<string, any>>(INITIAL_VIEW_STATE);
   const [hoverObject, setHoverObject] = React.useState<Node | null>(null);
@@ -72,34 +72,36 @@ export const MapVis = ({ data, configuration, updateSettings, graphMetadata }: V
   );
 
   useEffect(() => {
-    if (configuration.layer) {
-      const layerType = layerTypes[configuration.layer] as any;
-
-      setLayer({
-        id: Date.now(),
-        name: 'New layer',
-        type: layerType,
-        config: {
-          ...layerType.layerOptions,
-        },
-        visible: true,
-      });
-    }
-  }, [configuration.layer]);
+    const layerType = settings.layer ? layerTypes?.[settings.layer] : layerTypes.node;
+
+    setLayer({
+      id: Date.now(),
+      name: 'New layer',
+      type: layerType,
+      config: {
+        ...layerType.layerOptions,
+      },
+      visible: true,
+    });
+  }, [settings.layer]);
+
+  useEffect(() => {
+    console.log('configuration.node', settings.node);
+  }, [settings.node]);
 
   useEffect(() => {
-    if (configuration.node != undefined && !graphMetadata.nodes.labels.includes(configuration.node)) {
+    if (settings.node != undefined && !graphMetadata.nodes.labels.includes(settings.node)) {
       updateSettings({ node: undefined });
     }
-  }, [graphMetadata.nodes.types, data, configuration]);
+  }, [graphMetadata.nodes.types, data, settings]);
 
   const dataLayer = useMemo(() => {
-    if (!layer || !configuration.node || !configuration.lat || !configuration.lon) return null;
+    if (!layer || !settings.node || !settings.lat || !settings.lon) return null;
 
     const coordinateLookup: { [id: string]: Coordinate } = data.nodes.reduce(
       (acc, node) => {
-        const latitude = node?.attributes?.[configuration.lat] as string | undefined;
-        const longitude = node?.attributes?.[configuration.lon] as string | undefined;
+        const latitude = settings.lat ? (node?.attributes?.[settings.lat] as string) : undefined;
+        const longitude = settings.lon ? (node?.attributes?.[settings.lon] as string) : undefined;
 
         if (!!latitude && !!longitude) {
           acc[node._id] = [parseFloat(longitude), parseFloat(latitude)];
@@ -109,6 +111,7 @@ export const MapVis = ({ data, configuration, updateSettings, graphMetadata }: V
       },
       {} as { [id: string]: Coordinate },
     );
+    console.log('coordinateLookup', coordinateLookup);
 
     return new layer.type({
       id: `${layer.id}`,
@@ -121,7 +124,7 @@ export const MapVis = ({ data, configuration, updateSettings, graphMetadata }: V
       getNodeLocation: (id: string) => coordinateLookup[id],
       flyToBoundingBox: flyToBoundingBox,
     });
-  }, [layer, data, selected, hoverObject, isSelecting, configuration.lat, configuration.lon, configuration.node]);
+  }, [layer, data, selected, hoverObject, isSelecting, settings.lat, settings.lon, settings.node]);
 
   const selectionLayer = useMemo(
     () =>
@@ -173,11 +176,11 @@ export const MapVis = ({ data, configuration, updateSettings, graphMetadata }: V
   );
 };
 
-const MapComponent: VISComponentType = {
+const MapComponent: VISComponentType<MapProps> = {
   displayName: 'MapVis',
   component: MapVis,
-  settings: MapSettings,
-  configuration: configuration,
+  settingsComponent: MapSettings,
+  settings: settings,
 };
 
 export default MapComponent;
diff --git a/libs/shared/lib/vis/visualizations/matrixvis/components/MatrixPixi.tsx b/libs/shared/lib/vis/visualizations/matrixvis/components/MatrixPixi.tsx
index 3db2cb6d1..a53fd8beb 100644
--- a/libs/shared/lib/vis/visualizations/matrixvis/components/MatrixPixi.tsx
+++ b/libs/shared/lib/vis/visualizations/matrixvis/components/MatrixPixi.tsx
@@ -23,8 +23,9 @@ import { Actions, Interpolations } from 'pixi-actions';
 import Color from 'color';
 import { createColumn } from './ColumnGraphicsComponent';
 import { ReorderingManager } from './ReorderingManager';
-import { VisualizationConfiguration } from '../../../common';
+import { VisualizationSettingsType } from '../../../common';
 import { range, scaleLinear, scaleOrdinal, schemeCategory10 } from 'd3';
+import { MatrixVisProps } from '../matrixvis';
 
 type Props = {
   // onClick: (node: NodeType, pos: IPointData) => void;
@@ -34,7 +35,7 @@ type Props = {
   currentShortestPathEdges?: LinkType[];
   highlightedLinks?: LinkType[];
   graph?: GraphQueryResult;
-  configuration: VisualizationConfiguration;
+  settings: MatrixVisProps;
 };
 
 const columnsContainer = new Container();
@@ -121,7 +122,7 @@ export const MatrixPixi = (props: Props) => {
     if (props.graph && ref.current && ref.current.children.length > 0) {
       setup();
     }
-  }, [props.configuration]);
+  }, [props.settings]);
 
   // TODO implement search results
   // useEffect(() => {
@@ -345,7 +346,7 @@ export const MatrixPixi = (props: Props) => {
     config.cellWidth = Math.max((size?.width || 1000) / props.graph.nodes.length, (size?.height || 1000) / props.graph.nodes.length);
     config.cellHeight = config.cellWidth;
 
-    setupVisualizationEncodingMapping(props.configuration);
+    setupVisualizationEncodingMapping(props.settings);
 
     setupColumns(props.graph.edges, columnOrder, rowOrder);
     setupColumnLegend(columnOrder);
@@ -364,7 +365,7 @@ export const MatrixPixi = (props: Props) => {
     isSetup.current = true;
   };
 
-  const setupVisualizationEncodingMapping = (configuration: VisualizationConfiguration) => {
+  const setupVisualizationEncodingMapping = (settings: MatrixVisProps) => {
     if (!props.graph) throw new Error('Graph is undefined; cannot setup matrix');
     const visMapping = []; // TODO type
 
@@ -376,7 +377,7 @@ export const MatrixPixi = (props: Props) => {
     const adjacenyScale = scaleLinear([colorNeutral, visualizationColors.GPSelected.colors[1][0]]);
     visMapping.push({
       attribute: 'adjacency',
-      encoding: configuration.marks,
+      encoding: settings.marks,
       colorScale: adjacenyScale,
       renderFunction: function (i: number, color: ColorSource, gfxContext: Graphics) {
         gfxContext.beginFill(color, 1);
diff --git a/libs/shared/lib/vis/visualizations/matrixvis/matrix.stories.tsx b/libs/shared/lib/vis/visualizations/matrixvis/matrix.stories.tsx
index 1a961e293..05522042c 100644
--- a/libs/shared/lib/vis/visualizations/matrixvis/matrix.stories.tsx
+++ b/libs/shared/lib/vis/visualizations/matrixvis/matrix.stories.tsx
@@ -3,7 +3,6 @@ import { Meta } from '@storybook/react';
 import { configureStore } from '@reduxjs/toolkit';
 import { Provider } from 'react-redux';
 import { big2ndChamberQueryResult, smallFlightsQueryResults, mockLargeQueryResults } from '../../../mock-data';
-import { VisualizationPanel } from '../../components/VisualizationPanel';
 
 import {
   setNewGraphQueryResult,
diff --git a/libs/shared/lib/vis/visualizations/matrixvis/matrixvis.tsx b/libs/shared/lib/vis/visualizations/matrixvis/matrixvis.tsx
index c225b2994..3b9223034 100644
--- a/libs/shared/lib/vis/visualizations/matrixvis/matrixvis.tsx
+++ b/libs/shared/lib/vis/visualizations/matrixvis/matrixvis.tsx
@@ -3,7 +3,7 @@ import { useImmer } from 'use-immer';
 import { GraphQueryResult } from '../../../data-access/store';
 import { LinkType, NodeType } from './types';
 import { MatrixPixi } from './components/MatrixPixi';
-import { VisualizationPropTypes, VISComponentType } from '../../common';
+import { VisualizationPropTypes, VISComponentType, VisualizationSettingsPropTypes } from '../../common';
 import { Input } from '@graphpolaris/shared/lib/components/inputs';
 import { GraphMetadata } from '@graphpolaris/shared/lib/data-access/statistics';
 import { SettingsContainer } from '@graphpolaris/shared/lib/vis/components/config';
@@ -13,12 +13,12 @@ export interface MatrixVisProps {
   color: string;
 }
 
-const configuration: MatrixVisProps = {
+const settings: MatrixVisProps = {
   marks: 'rect',
   color: 'blue',
 };
 
-export const MatrixVis = React.memo(({ data, ml, configuration }: VisualizationPropTypes) => {
+export const MatrixVis = React.memo(({ data, ml, settings }: VisualizationPropTypes<MatrixVisProps>) => {
   const ref = useRef<HTMLDivElement>(null);
   const [graph, setGraph] = useImmer<GraphQueryResult | undefined>(undefined);
   const [highlightNodes, setHighlightNodes] = useState<NodeType[]>([]);
@@ -33,47 +33,39 @@ export const MatrixVis = React.memo(({ data, ml, configuration }: VisualizationP
   return (
     <>
       <div className="h-full w-full overflow-hidden" ref={ref}>
-        <MatrixPixi graph={graph} highlightNodes={highlightNodes} highlightedLinks={highlightedLinks} configuration={configuration} />
+        <MatrixPixi graph={graph} highlightNodes={highlightNodes} highlightedLinks={highlightedLinks} settings={settings} />
       </div>
     </>
   );
 });
 
-const MatrixSettings = ({
-  configuration,
-  graph,
-  updateSettings,
-}: {
-  configuration: MatrixVisProps;
-  graph: GraphMetadata;
-  updateSettings: (val: any) => void;
-}) => {
+const MatrixSettings = ({ settings, updateSettings }: VisualizationSettingsPropTypes<MatrixVisProps>) => {
   return (
     <SettingsContainer>
       <Input
         type="dropdown"
         label="Configure marks"
-        value={configuration.marks}
+        value={settings.marks}
         options={['rect', 'circle']}
-        onChange={(val) => updateSettings({ marks: val })}
+        onChange={(val) => updateSettings({ marks: val as string })}
       />
 
       <Input
         type="dropdown"
         label="Color"
-        value={configuration.color}
+        value={settings.color}
         options={['blue', 'green']}
-        onChange={(val) => updateSettings({ color: val })}
+        onChange={(val) => updateSettings({ color: val as string })}
       />
     </SettingsContainer>
   );
 };
 
-export const MatrixVisComponent: VISComponentType = {
+export const MatrixVisComponent: VISComponentType<MatrixVisProps> = {
   displayName: 'MatrixVis',
   component: MatrixVis,
-  settings: MatrixSettings,
-  configuration: configuration,
+  settingsComponent: MatrixSettings,
+  settings: settings,
 };
 
 export default MatrixVisComponent;
diff --git a/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx b/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx
index 257e6c3e5..0b14261d0 100644
--- a/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx
+++ b/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx
@@ -7,15 +7,16 @@ import { NLPopup } from './NLPopup';
 import { hslStringToHex, nodeColor } from './utils';
 import { CytoscapeLayout, GraphologyLayout, LayoutFactory, Layouts } from '../../../../graph-layout';
 import { MultiGraph } from 'graphology';
-import { VisualizationConfiguration } from '../../../common';
+import { VisualizationSettingsType } from '../../../common';
 import { Viewport } from 'pixi-viewport';
+import { NodelinkVisProps } from '../nodelinkvis';
 
 type Props = {
   onClick: (event?: { node: NodeType; pos: IPointData }) => void;
   // onHover: (data: { node: NodeType; pos: IPointData }) => void;
   // onUnHover: (data: { node: NodeType; pos: IPointData }) => void;
   highlightNodes: NodeType[];
-  configuration: VisualizationConfiguration;
+  configuration: NodelinkVisProps;
   currentShortestPathEdges?: LinkType[];
   highlightedLinks?: LinkType[];
   graph?: GraphType;
@@ -90,7 +91,7 @@ export const NLPixi = (props: Props) => {
         LAYOUT_ALGORITHM: (props.layoutAlgorithm as Layouts) || lastConfig.LAYOUT_ALGORITHM,
       };
     });
-  }, [props.layoutAlgorithm]);
+  }, [props.layoutAlgorithm, props.configuration]);
 
   const imperative = useRef<any>(null);
 
diff --git a/libs/shared/lib/vis/visualizations/nodelinkvis/nodelinkvis.tsx b/libs/shared/lib/vis/visualizations/nodelinkvis/nodelinkvis.tsx
index 2bdf3c3c6..05406c258 100644
--- a/libs/shared/lib/vis/visualizations/nodelinkvis/nodelinkvis.tsx
+++ b/libs/shared/lib/vis/visualizations/nodelinkvis/nodelinkvis.tsx
@@ -8,13 +8,15 @@ import { Layouts } from '../../../graph-layout/types';
 import { Input } from '@graphpolaris/shared/lib/components/inputs';
 import { GraphMetadata } from '@graphpolaris/shared/lib/data-access/statistics';
 import { SettingsContainer } from '@graphpolaris/shared/lib/vis/components/config';
-import { VISComponentType, VisualizationPropTypes } from '../../common';
 import { EntityPill } from '@graphpolaris/shared/lib/components/pills/Pill';
 import { nodeColorHex } from './components/utils';
 import { Node } from '@graphpolaris/shared/lib/data-access/store/graphQueryResultSlice';
 import { IPointData } from 'pixi.js';
+import { VisualizationPropTypes, VISComponentType, VisualizationSettingsPropTypes } from '../../common';
 
 export interface NodelinkVisProps {
+  id: string;
+  name: string;
   layout: string;
   showPopUpOnHover: boolean;
   shapes: {
@@ -31,7 +33,9 @@ export interface NodelinkVisProps {
   nodeList: string[];
 }
 
-const configuration: NodelinkVisProps = {
+const settings: NodelinkVisProps = {
+  id: 'NodeLinkVis',
+  name: 'NodeLinkVis',
   layout: Layouts.FORCEATLAS2WEBWORKER as string,
   showPopUpOnHover: false,
   shapes: {
@@ -45,7 +49,7 @@ const configuration: NodelinkVisProps = {
   nodeList: [],
 };
 
-export const NodeLinkVis = React.memo(({ data, ml, dispatch, configuration, handleSelect }: VisualizationPropTypes) => {
+export const NodeLinkVis = React.memo(({ data, ml, dispatch, settings, handleSelect }: VisualizationPropTypes<NodelinkVisProps>) => {
   const ref = useRef<HTMLDivElement>(null);
   const [graph, setGraph] = useImmer<GraphType | undefined>(undefined);
   const [highlightNodes, setHighlightNodes] = useState<NodeType[]>([]);
@@ -104,27 +108,19 @@ export const NodeLinkVis = React.memo(({ data, ml, dispatch, configuration, hand
   return (
     <NLPixi
       graph={graph}
-      configuration={configuration}
+      configuration={settings}
       highlightNodes={highlightNodes}
       highlightedLinks={highlightedLinks}
       onClick={(event) => {
         onClickedNode(event, ml);
       }}
-      layoutAlgorithm={configuration.layout}
-      showPopupsOnHover={configuration.showPopUpOnHover}
+      layoutAlgorithm={settings.layout}
+      showPopupsOnHover={settings.showPopUpOnHover}
     />
   );
 });
 
-const NodelinkSettings = ({
-  configuration,
-  graphMetadata,
-  updateSettings,
-}: {
-  configuration: NodelinkVisProps;
-  graphMetadata: GraphMetadata;
-  updateSettings: (val: any) => void;
-}) => {
+const NodelinkSettings = ({ settings, graphMetadata, updateSettings }: VisualizationSettingsPropTypes<NodelinkVisProps>) => {
   useEffect(() => {
     if (graphMetadata && graphMetadata.nodes && graphMetadata.nodes.labels.length > 0) {
       updateSettings({ nodeList: graphMetadata.nodes.labels });
@@ -133,11 +129,11 @@ const NodelinkSettings = ({
 
   return (
     <SettingsContainer>
-      <div className="mb-4">
-        <h1 className="text-sm font-bold">General</h1>
-        <div className="m-1 flex flex-col space-y-4">
-          <h1>Nodes Labels:</h1>
-          {configuration.nodeList.map((item, index) => (
+      <div className="mb-4 text-xs">
+        <h1 className="font-bold">General</h1>
+        <div className="m-1 flex flex-col space-y-2 mb-2">
+          <h4 className="font-semibold">Nodes Labels:</h4>
+          {settings.nodeList.map((item, index) => (
             <div className="flex m-1 items-center" key={item}>
               <div className="w-3/4 mr-6">
                 <EntityPill title={item} />
@@ -151,36 +147,36 @@ const NodelinkSettings = ({
         <Input
           type="dropdown"
           label="Layout"
-          value={configuration.layout}
+          value={settings.layout}
           options={Object.values(Layouts) as string[]}
-          onChange={(val) => updateSettings({ layout: val })}
+          onChange={(val) => updateSettings({ layout: val as string })}
         />
         <Input
           type="boolean"
           label="Show pop-up on hover"
-          value={configuration.showPopUpOnHover}
+          value={settings.showPopUpOnHover}
           onChange={(val) => updateSettings({ showPopUpOnHover: val })}
         />
       </div>
 
       <div className="mb-4">
-        <h1 className="text-sm font-bold">Nodes</h1>
+        <h1 className="font-bold">Nodes</h1>
 
         <div>
           <span className="text-xs font-semibold">Shape</span>
           <Input
             type="boolean"
             label="Common shape?"
-            value={configuration.shapes.similar}
-            onChange={(val) => updateSettings({ shapes: { ...configuration.shapes, similar: val } })}
+            value={settings.shapes.similar}
+            onChange={(val) => updateSettings({ shapes: { ...settings.shapes, similar: val } })}
           />
-          {configuration.shapes.similar ? (
+          {settings.shapes.similar ? (
             <Input
               type="dropdown"
               label="Shape"
-              value={configuration.shapes.shape}
+              value={settings.shapes.shape}
               options={['Circle', 'Square']}
-              onChange={(val) => updateSettings({ shapes: { ...configuration.shapes, shape: val } })}
+              onChange={(val) => updateSettings({ shapes: { ...settings.shapes, shape: val as any } })}
             />
           ) : (
             <span>Map shapes to labels (to be implemented)</span>
@@ -193,20 +189,20 @@ const NodelinkSettings = ({
       </div>
 
       <div>
-        <h1 className="text-sm font-bold">Edges</h1>
+        <h1 className="font-bold">Edges</h1>
         <div>
           <span className="text-xs font-semibold">Edge width</span>
           <Input
             type="boolean"
             label="Common width"
-            value={configuration.edges.width.similar}
-            onChange={(val) => updateSettings({ edges: { ...configuration.edges, width: { ...configuration.edges.width, similar: val } } })}
+            value={settings.edges.width.similar}
+            onChange={(val) => updateSettings({ edges: { ...settings.edges, width: { ...settings.edges.width, similar: val } } })}
           />
           <Input
             type="slider"
             label="Width"
-            value={configuration.edges.width.width}
-            onChange={(val) => updateSettings({ edges: { ...configuration.edges, width: { ...configuration.edges.width, width: val } } })}
+            value={settings.edges.width.width}
+            onChange={(val) => updateSettings({ edges: { ...settings.edges, width: { ...settings.edges.width, width: val } } })}
             min={0.1}
             max={2}
             step={0.1}
@@ -217,11 +213,11 @@ const NodelinkSettings = ({
   );
 };
 
-export const NodeLinkComponent: VISComponentType = {
+export const NodeLinkComponent: VISComponentType<NodelinkVisProps> = {
   displayName: 'NodeLinkVis',
   component: NodeLinkVis,
-  settings: NodelinkSettings,
-  configuration: configuration,
+  settingsComponent: NodelinkSettings,
+  settings: settings,
 };
 
 export default NodeLinkComponent;
diff --git a/libs/shared/lib/vis/visualizations/paohvis/paohvis.tsx b/libs/shared/lib/vis/visualizations/paohvis/paohvis.tsx
index 9a848bd69..821eb6c80 100644
--- a/libs/shared/lib/vis/visualizations/paohvis/paohvis.tsx
+++ b/libs/shared/lib/vis/visualizations/paohvis/paohvis.tsx
@@ -11,7 +11,7 @@ import { select, selectAll } from 'd3';
 
 import { SettingsContainer } from '@graphpolaris/shared/lib/vis/components/config';
 import { Input } from '@graphpolaris/shared/lib/components/inputs';
-import { VisualizationPropTypes, VISComponentType } from '../../common';
+import { VisualizationPropTypes, VISComponentType, VisualizationSettingsPropTypes } from '../../common';
 import { Button } from '@graphpolaris/shared/lib/components/buttons';
 import { EntityPill } from '@graphpolaris/shared/lib/components/pills/Pill';
 import { ArrowDropDown } from '@mui/icons-material';
@@ -32,7 +32,7 @@ export type PaohVisProps = {
   mergeData: boolean;
 };
 
-const configuration: PaohVisProps = {
+const settings: PaohVisProps = {
   rowHeight: 20,
   rowNode: '',
   columnNode: '',
@@ -47,9 +47,8 @@ const configuration: PaohVisProps = {
 
 const devEnv: string = 'dev_env'; //'dev_env','sb'
 
-export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, updateSettings }: VisualizationPropTypes) => {
+export const PaohVis = ({ data, graphMetadata, schema, settings, updateSettings }: VisualizationPropTypes<PaohVisProps>) => {
   // general
-  const configuration = conf as PaohVisProps;
   const [loading, setLoading] = useState(true);
 
   // row states
@@ -129,15 +128,15 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
     () => ({
       rowHeight: 30,
       hyperEdgeRanges: 30,
-      rowsMaxPerPage: configuration.numRowsDisplay,
-      columnsMaxPerPage: configuration.numColumnsDisplay,
+      rowsMaxPerPage: settings.numRowsDisplay,
+      columnsMaxPerPage: settings.numColumnsDisplay,
       maxSizeTextColumns: 120,
       maxSizeTextRows: 120,
       maxSizeTextID: 70,
       marginText: 0.05,
       sizeIcons: 16,
     }),
-    [configuration],
+    [settings],
   );
 
   //
@@ -312,9 +311,7 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
     }));
 
     // update rows
-    const sortedRowInformationSlicedFiltered = sortedRowInformationSliced.filter((row) =>
-      configuration.attributeRowShow.includes(row.header),
-    );
+    const sortedRowInformationSlicedFiltered = sortedRowInformationSliced.filter((row) => settings.attributeRowShow.includes(row.header));
 
     setInformationRow(sortedRowInformationSlicedFiltered);
     setInformationRowAllData(sortedRowInformation);
@@ -437,7 +434,7 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
 
     // update rows
     const sortedColumnInformationSlicedFiltered = sortedColumnInformationSliced.filter((row) =>
-      configuration.attributeColumnShow.includes(row.header),
+      settings.attributeColumnShow.includes(row.header),
     );
 
     setInformationColumn(sortedColumnInformationSlicedFiltered);
@@ -486,27 +483,27 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
   useEffect(() => {
     if (
       graphMetadata &&
-      configuration.columnNode !== '' &&
-      configuration.rowNode !== '' &&
-      graphMetadata.nodes.types[configuration.rowNode] &&
-      graphMetadata.nodes.types[configuration.columnNode]
+      settings.columnNode !== '' &&
+      settings.rowNode !== '' &&
+      graphMetadata.nodes.types[settings.rowNode] &&
+      graphMetadata.nodes.types[settings.columnNode]
     ) {
-      const firstColumnLabels = Object.keys(graphMetadata.nodes.types[configuration.columnNode].attributes).slice(0, 2);
-      const firstRowLabels = Object.keys(graphMetadata.nodes.types[configuration.rowNode].attributes).slice(0, 2);
+      const firstColumnLabels = Object.keys(graphMetadata.nodes.types[settings.columnNode].attributes).slice(0, 2);
+      const firstRowLabels = Object.keys(graphMetadata.nodes.types[settings.rowNode].attributes).slice(0, 2);
       if (firstColumnLabels && firstRowLabels) {
-        if (configuration.attributeColumnShow.includes('_id')) {
+        if (settings.attributeColumnShow.includes('_id')) {
           updateSettings({ attributeColumnShow: [...firstColumnLabels, '# Connections'] });
         }
-        if (configuration.attributeRowShow.includes('_id')) {
+        if (settings.attributeRowShow.includes('_id')) {
           updateSettings({ attributeRowShow: [...firstRowLabels, '# Connections'] });
         }
         setTimeout(() => setLoading(false), 100); // wait for the settings to update first
       }
     }
-  }, [graphMetadata, configuration]);
+  }, [graphMetadata, settings]);
 
   useEffect(() => {
-    if (loading || configuration.rowNode === '' || configuration.columnNode === '') return;
+    if (loading || settings.rowNode === '' || settings.columnNode === '') return;
 
     // set new data
     // for dev env
@@ -532,13 +529,13 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
       }
 
       //const toNode = edgeSchema?.target as string; //devEnv
-      const columnNodeAttributes = Object.keys(graphMetadata.nodes.types[configuration.columnNode].attributes);
-      const newData = parseQueryResult(data, configuration as PaohVisProps, toNode, configuration.mergeData);
+      const columnNodeAttributes = Object.keys(graphMetadata.nodes.types[settings.columnNode].attributes);
+      const newData = parseQueryResult(data, settings as PaohVisProps, toNode, settings.mergeData);
       // original data without slicing
       setNumRowsVisible(Math.min(configPaohvis.rowsMaxPerPage, newData.rowLabels.length));
 
-      const rowNodes = newData.nodes.filter((obj) => obj[devEnv === 'sb' ? '_id' : 'label'].includes(configuration.rowNode));
-      const columnNodes = newData.nodes.filter((obj) => obj[devEnv === 'sb' ? '_id' : 'label'].includes(configuration.columnNode));
+      const rowNodes = newData.nodes.filter((obj) => obj[devEnv === 'sb' ? '_id' : 'label'].includes(settings.rowNode));
+      const columnNodes = newData.nodes.filter((obj) => obj[devEnv === 'sb' ? '_id' : 'label'].includes(settings.columnNode));
 
       // to keep order of new attributes
       prevDisplayAttributesColumns.current = [...columnNodeAttributes];
@@ -582,7 +579,7 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
 
       // columnInformation
       const informationColumnTemporalOriginal: { header: string; data: any[]; width: number }[] = Object.entries(
-        graphMetadata.nodes.types[configuration.columnNode].attributes,
+        graphMetadata.nodes.types[settings.columnNode].attributes,
       ).map(([k, v]) => {
         const mappedData = columnNodes.map((node) => node.attributes[k]);
         return {
@@ -634,7 +631,7 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
 
         // select necessary variables to show
         const filteredInformationColumnTemporal = informationColumnTemporal.filter((row) =>
-          configuration.attributeColumnShow.includes(row.header),
+          settings.attributeColumnShow.includes(row.header),
         );
 
         // set data
@@ -651,7 +648,7 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
       // build
 
       const informationRowTemporalOriginal: { header: string; data: any[]; width: number }[] = Object.entries(
-        graphMetadata.nodes.types[configuration.rowNode].attributes,
+        graphMetadata.nodes.types[settings.rowNode].attributes,
       ).map(([k, v]) => {
         const mappedData = rowNodes.map((node) => node.attributes[k]);
 
@@ -693,7 +690,7 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
       setIndicesRowsForColumnSort(originalIndices);
 
       // select necessary variables to show
-      const filteredInformationRowTemporal = informationRowTemporal.filter((row) => configuration.attributeRowShow.includes(row.header));
+      const filteredInformationRowTemporal = informationRowTemporal.filter((row) => settings.attributeRowShow.includes(row.header));
 
       // set data
       setInformationRow(filteredInformationRowTemporal);
@@ -704,12 +701,12 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
       setWidthTotalRowInformation(totalWidthRowInformation);
     }
   }, [
-    configuration.rowNode,
-    configuration.columnNode,
+    settings.rowNode,
+    settings.columnNode,
     configPaohvis,
-    configuration.attributeRowShow,
-    configuration.attributeColumnShow,
-    configuration.mergeData,
+    settings.attributeRowShow,
+    settings.attributeColumnShow,
+    settings.mergeData,
     loading,
   ]);
 
@@ -734,7 +731,7 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
     let tableWidthWithExtraColumnLabelWidth = 0;
 
     dataModel.pageData.hyperEdgeRanges.forEach((hyperEdgeRange) => {
-      const columnWidth = 1 * configuration.rowHeight;
+      const columnWidth = 1 * settings.rowHeight;
       tableWidth += columnWidth;
 
       if (tableWidth > tableWidthWithExtraColumnLabelWidth) tableWidthWithExtraColumnLabelWidth = tableWidth;
@@ -750,21 +747,21 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
     };
   }, [
     dataModel,
-    configuration.rowHeight,
+    settings.rowHeight,
     widthTotalColumnInformation,
     widthTotalRowInformation,
-    configuration.attributeColumnShow,
-    configuration.attributeRowShow,
+    settings.attributeColumnShow,
+    settings.attributeRowShow,
   ]);
 
   const onWheel = (event: React.WheelEvent<SVGSVGElement>) => {
     if (event.deltaY !== 0) {
-      if (event.shiftKey) onPageChangeColumns(event.deltaY > 0 ? configuration.colJumpAmount : -configuration.colJumpAmount);
-      else onPageChangeRows(event.deltaY > 0 ? configuration.rowJumpAmount : -configuration.rowJumpAmount);
+      if (event.shiftKey) onPageChangeColumns(event.deltaY > 0 ? settings.colJumpAmount : -settings.colJumpAmount);
+      else onPageChangeRows(event.deltaY > 0 ? settings.rowJumpAmount : -settings.rowJumpAmount);
     }
 
     if (event.deltaX !== 0) {
-      onPageChangeColumns(event.deltaX > 0 ? configuration.colJumpAmount : -configuration.colJumpAmount);
+      onPageChangeColumns(event.deltaX > 0 ? settings.colJumpAmount : -settings.colJumpAmount);
     }
   };
 
@@ -796,9 +793,7 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
       data: table.data.slice(startIndexColumn, endIndexColumn),
     }));
 
-    const filteredInformationColumnsTemporal = dataColumnsSortedSliced.filter((row) =>
-      configuration.attributeColumnShow.includes(row.header),
-    );
+    const filteredInformationColumnsTemporal = dataColumnsSortedSliced.filter((row) => settings.attributeColumnShow.includes(row.header));
 
     setInformationColumn(filteredInformationColumnsTemporal);
 
@@ -823,7 +818,7 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
       data: table.data.slice(startIndexRow, endIndexRow),
     }));
 
-    const filteredInformationRowTemporal = dataRowsSortedSliced.filter((row) => configuration.attributeRowShow.includes(row.header));
+    const filteredInformationRowTemporal = dataRowsSortedSliced.filter((row) => settings.attributeRowShow.includes(row.header));
 
     setInformationRow(filteredInformationRowTemporal);
 
@@ -846,13 +841,13 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
       style={{
         // width: computedSizesSvg.tableWidthWithExtraColumnLabelWidth,
         width: '100%',
-        height: computedSizesSvg.colWidth + (numRowsVisible + 1) * configuration.rowHeight,
+        height: computedSizesSvg.colWidth + (numRowsVisible + 1) * settings.rowHeight,
       }}
       onWheel={onWheel}
     >
       <RowLabels
         dataRows={informationRow}
-        rowHeight={configuration.rowHeight}
+        rowHeight={settings.rowHeight}
         yOffset={computedSizesSvg.colWidth}
         rowLabelColumnWidth={widthTotalRowInformation}
         classTopTextColumns={classTopTextColumns}
@@ -867,7 +862,7 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
       <HyperEdgeRangesBlock
         dataModel={dataModel}
         dataLinesHyperedges={lineHyperEdges}
-        rowHeight={configuration.rowHeight}
+        rowHeight={settings.rowHeight}
         yOffset={computedSizesSvg.colWidth}
         rowLabelColumnWidth={widthTotalRowInformation}
         classTopTextColumns={classTopTextColumns}
@@ -887,15 +882,7 @@ export const PaohVis = ({ data, graphMetadata, schema, configuration: conf, upda
   );
 };
 
-const PaohSettings = ({
-  configuration,
-  graphMetadata,
-  updateSettings,
-}: {
-  configuration: PaohVisProps;
-  graphMetadata: GraphMetadata;
-  updateSettings: (val: any) => void;
-}) => {
+const PaohSettings = ({ settings, graphMetadata, updateSettings }: VisualizationSettingsPropTypes<PaohVisProps>) => {
   const [areCollapsedAttrRows, setAreCollapsedAttrRows] = useState<boolean>(true);
   const [areCollapsedAttrColumns, setAreCollapsedAttrColumns] = useState<boolean>(true);
 
@@ -908,8 +895,8 @@ const PaohSettings = ({
   };
 
   const rowNodeAttributes = useMemo(() => {
-    if (configuration.rowNode) {
-      const nodeType = graphMetadata.nodes.types[configuration.rowNode];
+    if (settings.rowNode) {
+      const nodeType = graphMetadata.nodes.types[settings.rowNode];
       if (nodeType && nodeType.attributes) {
         const attributes = Object.keys(nodeType.attributes);
         attributes.unshift('# Connections');
@@ -918,11 +905,11 @@ const PaohSettings = ({
       }
     }
     return [];
-  }, [configuration.rowNode, graphMetadata]);
+  }, [settings.rowNode, graphMetadata]);
 
   const columnsNodeAttributes = useMemo(() => {
-    if (configuration.columnNode) {
-      const nodeType = graphMetadata.nodes.types[configuration.columnNode];
+    if (settings.columnNode) {
+      const nodeType = graphMetadata.nodes.types[settings.columnNode];
       if (nodeType && nodeType.attributes) {
         const attributes = Object.keys(nodeType.attributes);
         attributes.unshift('# Connections');
@@ -931,7 +918,7 @@ const PaohSettings = ({
       }
     }
     return [];
-  }, [configuration.columnNode, graphMetadata]);
+  }, [settings.columnNode, graphMetadata]);
 
   useEffect(() => {
     if (graphMetadata && graphMetadata.nodes && graphMetadata.nodes.labels.length > 1) {
@@ -946,10 +933,10 @@ const PaohSettings = ({
           <span className="text-xs font-semibold">Node used in Row</span>
           <Input
             type="dropdown"
-            value={configuration.rowNode}
+            value={settings.rowNode}
             options={graphMetadata.nodes.labels}
-            onChange={(val) => updateSettings({ rowNode: val })}
-            overrideRender={<EntityPill title={configuration.rowNode} />}
+            onChange={(val) => updateSettings({ rowNode: val as string })}
+            overrideRender={<EntityPill title={settings.rowNode} />}
           />
         </div>
         <Button
@@ -966,7 +953,7 @@ const PaohSettings = ({
           <div className="">
             <Input
               type="checkbox"
-              value={configuration.attributeRowShow}
+              value={settings.attributeRowShow}
               options={rowNodeAttributes}
               onChange={(val: string[] | string) => {
                 const updatedVal = Array.isArray(val) ? val : [val];
@@ -980,10 +967,10 @@ const PaohSettings = ({
           <span className="text-xs font-semibold">Node used in Column</span>
           <Input
             type="dropdown"
-            value={configuration.columnNode}
+            value={settings.columnNode}
             options={graphMetadata.nodes.labels}
-            onChange={(val) => updateSettings({ columnNode: val })}
-            overrideRender={<EntityPill title={configuration.columnNode} />}
+            onChange={(val) => updateSettings({ columnNode: val as string })}
+            overrideRender={<EntityPill title={settings.columnNode} />}
           />
         </div>
 
@@ -1002,7 +989,7 @@ const PaohSettings = ({
           <div className="">
             <Input
               type="checkbox"
-              value={configuration.attributeColumnShow}
+              value={settings.attributeColumnShow}
               options={columnsNodeAttributes}
               onChange={(val: string[] | string) => {
                 const updatedVal = Array.isArray(val) ? val : [val];
@@ -1012,43 +999,38 @@ const PaohSettings = ({
           </div>
         )}
 
-        <Input type="number" label="Row height" value={configuration.rowHeight} onChange={(val) => updateSettings({ rowHeight: val })} />
+        <Input type="number" label="Row height" value={settings.rowHeight} onChange={(val) => updateSettings({ rowHeight: val })} />
 
-        <Input
-          type="number"
-          label="# Rows"
-          value={configuration.numRowsDisplay}
-          onChange={(val) => updateSettings({ numRowsDisplay: val })}
-        />
+        <Input type="number" label="# Rows" value={settings.numRowsDisplay} onChange={(val) => updateSettings({ numRowsDisplay: val })} />
         <Input
           type="number"
           label="# Columns"
-          value={configuration.numColumnsDisplay}
+          value={settings.numColumnsDisplay}
           onChange={(val) => updateSettings({ numColumnsDisplay: val })}
         />
         <Input
           type="number"
           label="Row jump sensitivity"
-          value={configuration.rowJumpAmount}
+          value={settings.rowJumpAmount}
           onChange={(val) => updateSettings({ rowJumpAmount: val })}
         />
         <Input
           type="number"
           label="Column jump sensitivity"
-          value={configuration.colJumpAmount}
+          value={settings.colJumpAmount}
           onChange={(val) => updateSettings({ colJumpAmount: val })}
         />
-        <Input type="boolean" label="Merge Data" value={configuration.mergeData} onChange={(val) => updateSettings({ mergeData: val })} />
+        <Input type="boolean" label="Merge Data" value={settings.mergeData} onChange={(val) => updateSettings({ mergeData: val })} />
       </div>
     </SettingsContainer>
   );
 };
 
-export const PaohVisComponent: VISComponentType = {
+export const PaohVisComponent: VISComponentType<PaohVisProps> = {
   displayName: 'PaohVis',
   component: PaohVis,
-  settings: PaohSettings,
-  configuration: configuration,
+  settingsComponent: PaohSettings,
+  settings: settings,
 };
 
 export default PaohVisComponent;
diff --git a/libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.tsx b/libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.tsx
index 7aa8e7549..3b0932a59 100644
--- a/libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.tsx
+++ b/libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.tsx
@@ -1,67 +1,59 @@
 import React, { useEffect } from 'react';
 import ReactJSONView from 'react-json-view';
-import { VisualizationPropTypes, VISComponentType } from '../../common';
+import { VisualizationPropTypes, VISComponentType, VisualizationSettingsPropTypes } from '../../common';
 import { GraphMetadata } from '@graphpolaris/shared/lib/data-access/statistics';
 import { SettingsContainer } from '@graphpolaris/shared/lib/vis/components/config';
 import { Input } from '@graphpolaris/shared/lib/components/inputs';
 
 export interface RawJSONVisProps {
   theme: string;
-  iconStyle: string;
+  iconStyle: 'circle' | 'triangle' | 'square' | undefined;
 }
 
-const configuration: RawJSONVisProps = {
+const settings: RawJSONVisProps = {
   theme: 'bright:inverted',
   iconStyle: 'circle',
 };
 
-export const RawJSONVis = React.memo(({ data, configuration }: VisualizationPropTypes) => {
+export const RawJSONVis = React.memo(({ data, settings }: VisualizationPropTypes) => {
   return (
     <ReactJSONView
       src={data}
       collapsed={1}
       quotesOnKeys={false}
       style={{ padding: '20px', flexGrow: 1 }}
-      theme={configuration.theme}
-      iconStyle={configuration.iconStyle}
+      theme={settings.theme || 'bright:inverted'}
+      iconStyle={settings.iconStyle}
       enableClipboard={true}
     />
   );
 });
 
-const RawJSONSettings = ({
-  configuration,
-  graph,
-  updateSettings,
-}: {
-  configuration: RawJSONVisProps;
-  graph: GraphMetadata;
-  updateSettings: (val: any) => void;
-}) => {
+const RawJSONSettings = ({ settings, updateSettings }: VisualizationSettingsPropTypes<RawJSONVisProps>) => {
   return (
     <SettingsContainer>
       <Input
         type="dropdown"
         label="Select a theme"
-        value={configuration.theme}
+        value={settings.theme}
         options={['bright:inverted', 'monokai', 'ocean']}
-        onChange={(val) => updateSettings({ theme: val })}
+        onChange={(val) => updateSettings({ theme: val as any })}
       />
       <Input
         type="dropdown"
         label="Icon style"
-        value={configuration.iconStyle}
+        value={settings.iconStyle}
         options={['circle', 'square', 'triangle']}
-        onChange={(val) => updateSettings({ iconStyle: val })}
+        onChange={(val) => updateSettings({ iconStyle: val as any })}
       />
     </SettingsContainer>
   );
 };
 
-export const RawJSONComponent: VISComponentType = {
+export const RawJSONComponent: VISComponentType<RawJSONVisProps> = {
   displayName: 'RawJSONVis',
   component: RawJSONVis,
-  settings: RawJSONSettings,
-  configuration: configuration,
+  settingsComponent: RawJSONSettings,
+  settings: settings,
 };
 export default RawJSONComponent;
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/semanticsubstratesvis.tsx b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/semanticsubstratesvis.tsx
index cddb8a206..40e03c4ee 100644
--- a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/semanticsubstratesvis.tsx
+++ b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/semanticsubstratesvis.tsx
@@ -4,7 +4,7 @@ import { GraphMetadata } from '@graphpolaris/shared/lib/data-access/statistics';
 import { SettingsContainer } from '@graphpolaris/shared/lib/vis/components/config';
 
 import { visualizationColors } from 'config/src/colors';
-import { VisualizationPropTypes, VISComponentType } from '../../common';
+import { VisualizationPropTypes, VISComponentType, VisualizationSettingsPropTypes } from '../../common';
 import { findConnectionsNodes, getRegionData, setExtension, filterArray, getUniqueValues } from './components/utils';
 
 import { Node } from '@graphpolaris/shared/lib/data-access/store/graphQueryResultSlice';
@@ -31,13 +31,13 @@ export type SemSubstrProps = {
   showColor: boolean;
 };
 
-const configuration: SemSubstrProps = {
+const settings: SemSubstrProps = {
   showColor: true,
 };
 
 const displayName = 'SemSubstrVis';
 
-export const VisSemanticSubstrates = ({ data, configuration }: VisualizationPropTypes) => {
+export const VisSemanticSubstrates = ({ data }: VisualizationPropTypes<SemSubstrProps>) => {
   const nodes = data.nodes;
   const edges = data.edges;
 
@@ -422,27 +422,19 @@ export const VisSemanticSubstrates = ({ data, configuration }: VisualizationProp
   );
 };
 
-const SemSubstrSettings = ({
-  configuration,
-  graph,
-  updateSettings,
-}: {
-  configuration: SemSubstrProps;
-  graph: GraphMetadata;
-  updateSettings: (val: any) => void;
-}) => {
+const SemSubstrSettings = ({ settings, updateSettings }: VisualizationSettingsPropTypes<SemSubstrProps>) => {
   return (
     <SettingsContainer>
-      <Input type="boolean" label="Show color" value={configuration.showColor} onChange={(val) => updateSettings({ showColor: val })} />
+      <Input type="boolean" label="Show color" value={settings.showColor} onChange={(val) => updateSettings({ showColor: val })} />
     </SettingsContainer>
   );
 };
 
-export const SemSubstrVisComponent: VISComponentType = {
+export const SemSubstrVisComponent: VISComponentType<SemSubstrProps> = {
   displayName: displayName,
   component: VisSemanticSubstrates,
-  settings: SemSubstrSettings,
-  configuration: configuration,
+  settingsComponent: SemSubstrSettings,
+  settings: settings,
 };
 
 export default SemSubstrVisComponent;
diff --git a/libs/shared/lib/vis/visualizations/tablevis/tablevis.stories.tsx b/libs/shared/lib/vis/visualizations/tablevis/tablevis.stories.tsx
index 26488d4a2..8b7f81534 100644
--- a/libs/shared/lib/vis/visualizations/tablevis/tablevis.stories.tsx
+++ b/libs/shared/lib/vis/visualizations/tablevis/tablevis.stories.tsx
@@ -45,7 +45,7 @@ export const TestWithAirport = {
   args: {
     data: bigMockQueryResults,
     schema: simpleSchemaAirportRaw,
-    configuration: TableComponent.configuration,
+    configuration: TableComponent.settings,
   },
 };
 
@@ -53,7 +53,7 @@ export const TestWithBig2ndChamber = {
   args: {
     data: big2ndChamberQueryResult,
     schema: big2ndChamberSchemaRaw,
-    configuration: TableComponent.configuration,
+    configuration: TableComponent.settings,
   },
 };
 
@@ -61,7 +61,7 @@ export const TestWithTypesMock = {
   args: {
     data: typesMockQueryResults,
     schema: typesMockSchemaRaw,
-    configuration: TableComponent.configuration,
+    configuration: TableComponent.settings,
   },
 };
 
diff --git a/libs/shared/lib/vis/visualizations/tablevis/tablevis.tsx b/libs/shared/lib/vis/visualizations/tablevis/tablevis.tsx
index d2070b3f0..f92d97beb 100644
--- a/libs/shared/lib/vis/visualizations/tablevis/tablevis.tsx
+++ b/libs/shared/lib/vis/visualizations/tablevis/tablevis.tsx
@@ -1,14 +1,15 @@
 import React, { useEffect, useMemo, useRef, useState } from 'react';
 import { Table, AugmentedNodeAttributes } from './components/Table';
 import { SchemaAttribute } from '../../../schema';
-import { VisualizationPropTypes, VISComponentType } from '../../common';
+import { VisualizationPropTypes, VISComponentType, VisualizationSettingsPropTypes } from '../../common';
 import { Input } from '@graphpolaris/shared/lib/components/inputs';
-import { GraphMetadata } from '@graphpolaris/shared/lib/data-access/statistics';
 import { SettingsContainer } from '@graphpolaris/shared/lib/vis/components/config';
 import { Button } from '@graphpolaris/shared/lib/components/buttons';
 import { ArrowDropDown } from '@mui/icons-material';
 
 export type TableProps = {
+  id: string;
+  name: string;
   showBarplot: boolean;
   itemsPerPage: number;
   displayAttributes: string[];
@@ -16,7 +17,9 @@ export type TableProps = {
   maxBarsCount: number;
 };
 
-const configuration: TableProps = {
+const settings: TableProps = {
+  id: 'TableVis',
+  name: 'TableVis',
   itemsPerPage: 10,
   showBarplot: true,
   displayAttributes: [],
@@ -24,19 +27,19 @@ const configuration: TableProps = {
   maxBarsCount: 10,
 };
 
-export const TableVis = ({ data, schema, configuration, updateSettings, graphMetadata }: VisualizationPropTypes) => {
+export const TableVis = ({ data, schema, settings, updateSettings, graphMetadata }: VisualizationPropTypes<TableProps>) => {
   const ref = useRef<HTMLDivElement>(null);
 
   useEffect(() => {
-    if (!graphMetadata.nodes.labels.includes(configuration.displayEntity)) {
+    if (!graphMetadata.nodes.labels.includes(settings.displayEntity)) {
       updateSettings({ displayEntity: graphMetadata.nodes.labels[0] });
     }
-  }, [graphMetadata.nodes.labels, data, configuration]);
+  }, [graphMetadata.nodes.labels, data, settings]);
 
   const attributesArray = useMemo<AugmentedNodeAttributes[]>(
     () =>
       data.nodes
-        .filter((node) => node.label === configuration.displayEntity)
+        .filter((node) => node.label === settings.displayEntity)
         .map((node) => {
           const types: SchemaAttribute[] =
             schema.nodes.find((n) => n.key === node.label)?.attributes?.attributes ??
@@ -48,7 +51,7 @@ export const TableVis = ({ data, schema, configuration, updateSettings, graphMet
             type: Object.fromEntries(types.map((t) => [t.name, t.type])),
           };
         }),
-    [data.nodes, configuration.displayEntity],
+    [data.nodes, settings.displayEntity],
   );
 
   return (
@@ -56,26 +59,18 @@ export const TableVis = ({ data, schema, configuration, updateSettings, graphMet
       {attributesArray.length > 0 && (
         <Table
           data={attributesArray}
-          itemsPerPage={configuration.itemsPerPage}
-          showBarPlot={configuration.showBarplot}
-          showAttributes={configuration.displayAttributes}
-          selectedEntity={configuration.displayEntity}
-          maxBarsCount={configuration.maxBarsCount}
+          itemsPerPage={settings.itemsPerPage}
+          showBarPlot={settings.showBarplot}
+          showAttributes={settings.displayAttributes}
+          selectedEntity={settings.displayEntity}
+          maxBarsCount={settings.maxBarsCount}
         />
       )}
     </div>
   );
 };
 
-const TableSettings = ({
-  configuration,
-  graphMetadata,
-  updateSettings,
-}: {
-  configuration: TableProps;
-  graphMetadata: GraphMetadata;
-  updateSettings: (val: any) => void;
-}) => {
+const TableSettings = ({ settings, graphMetadata, updateSettings }: VisualizationSettingsPropTypes<TableProps>) => {
   useEffect(() => {
     if (graphMetadata && graphMetadata.nodes && graphMetadata.nodes.labels.length > 0) {
       updateSettings({ displayEntity: graphMetadata.nodes.labels[0] });
@@ -87,14 +82,14 @@ const TableSettings = ({
     setAreCollapsedAttr(!areCollapsedAttr);
   };
   const selectedNodeAttributes = useMemo(() => {
-    if (configuration.displayEntity) {
-      const nodeType = graphMetadata.nodes.types[configuration.displayEntity];
+    if (settings.displayEntity) {
+      const nodeType = graphMetadata.nodes.types[settings.displayEntity];
       if (nodeType && nodeType.attributes) {
         return Object.keys(nodeType.attributes);
       }
     }
     return [];
-  }, [configuration.displayEntity, graphMetadata]);
+  }, [settings.displayEntity, graphMetadata]);
 
   useEffect(() => {
     if (graphMetadata && graphMetadata.nodes && graphMetadata.nodes.labels.length > 0) {
@@ -107,27 +102,22 @@ const TableSettings = ({
       <Input
         type="dropdown"
         label="Select entity"
-        value={configuration.displayEntity}
-        onChange={(val) => updateSettings({ displayEntity: val })}
+        value={settings.displayEntity}
+        onChange={(val) => updateSettings({ displayEntity: val as string })}
         options={graphMetadata.nodes.labels}
       />
-      <Input
-        type="boolean"
-        label="Show barplot"
-        value={configuration.showBarplot}
-        onChange={(val) => updateSettings({ showBarplot: val })}
-      />
+      <Input type="boolean" label="Show barplot" value={settings.showBarplot} onChange={(val) => updateSettings({ showBarplot: val })} />
       <Input
         type="dropdown"
         label="Items per page"
-        value={configuration.itemsPerPage}
-        onChange={(val) => updateSettings({ itemsPerPage: val })}
+        value={settings.itemsPerPage}
+        onChange={(val) => updateSettings({ itemsPerPage: val as number })}
         options={[10, 25, 50, 100]}
       />
       <Input
         type="number"
         label="Max Bars in Bar Plots"
-        value={configuration.maxBarsCount}
+        value={settings.maxBarsCount}
         onChange={(val) => updateSettings({ maxBarsCount: val })}
       />
       <div>
@@ -146,7 +136,7 @@ const TableSettings = ({
           {!areCollapsedAttr && (
             <Input
               type="checkbox"
-              value={configuration.displayAttributes}
+              value={settings.displayAttributes}
               options={selectedNodeAttributes}
               onChange={(val: string[] | string) => {
                 const updatedVal = Array.isArray(val) ? val : [val];
@@ -160,11 +150,11 @@ const TableSettings = ({
   );
 };
 
-export const TableComponent: VISComponentType = {
+export const TableComponent: VISComponentType<TableProps> = {
   displayName: 'TableVis',
   component: TableVis,
-  settings: TableSettings,
-  configuration: configuration,
+  settingsComponent: TableSettings,
+  settings: settings,
 };
 
 export default TableComponent;
-- 
GitLab