diff --git a/docs/modules/ROOT/pages/operations/on-canvas-operations.adoc b/docs/modules/ROOT/pages/operations/on-canvas-operations.adoc
index ac522c8c294..9beb9e72903 100644
--- a/docs/modules/ROOT/pages/operations/on-canvas-operations.adoc
+++ b/docs/modules/ROOT/pages/operations/on-canvas-operations.adoc
@@ -28,4 +28,4 @@ image:modifying-node-properties-example.png[width=600]
 
 Similary, we can modify node label:
 
-image:modifying-node-label-example.png[width=600]
\ No newline at end of file
+image:modifying-node-label-example.png[width=600]
diff --git a/src/browser/modules/Stream/CypherFrame/VisualizationView/PropertiesPanelContent/DetailsPane.test.tsx b/src/browser/modules/Stream/CypherFrame/VisualizationView/PropertiesPanelContent/DetailsPane.test.tsx
index 25317b7a6bf..11d8ad128e3 100644
--- a/src/browser/modules/Stream/CypherFrame/VisualizationView/PropertiesPanelContent/DetailsPane.test.tsx
+++ b/src/browser/modules/Stream/CypherFrame/VisualizationView/PropertiesPanelContent/DetailsPane.test.tsx
@@ -22,7 +22,11 @@ import React from 'react'
 
 import { DETAILS_PANE_STEP_SIZE, DetailsPane } from './DetailsPane'
 import { VizItemProperty } from 'neo4j-arc/common'
-import { GraphStyleModel, VizItem } from 'neo4j-arc/graph-visualization'
+import {
+  GraphStyleModel,
+  VizItem,
+  NodeModel
+} from 'neo4j-arc/graph-visualization'
 
 describe('<DetailsPane />', () => {
   const mockGraphStyle = new GraphStyleModel()
@@ -66,7 +70,9 @@ describe('<DetailsPane />', () => {
           item: {
             id: 'abc',
             type: 'abc2',
-            propertyList
+            propertyList,
+            source: new NodeModel('1', [], {}, {}),
+            target: new NodeModel('2', [], {}, {})
           }
         }
     }
diff --git a/src/browser/modules/Stream/CypherFrame/VisualizationView/PropertiesPanelContent/DetailsPane.tsx b/src/browser/modules/Stream/CypherFrame/VisualizationView/PropertiesPanelContent/DetailsPane.tsx
index 6b28348a9b9..c0431e241c8 100644
--- a/src/browser/modules/Stream/CypherFrame/VisualizationView/PropertiesPanelContent/DetailsPane.tsx
+++ b/src/browser/modules/Stream/CypherFrame/VisualizationView/PropertiesPanelContent/DetailsPane.tsx
@@ -71,6 +71,9 @@ export function DetailsPane({
               relType: vizItem.item.type
             }}
             graphStyle={graphStyle}
+            onGraphInteraction={onGraphInteraction}
+            sourceNodeId={vizItem.item.source.id}
+            targetNodeId={vizItem.item.target.id}
           />
         )}
         {vizItem.type === 'node' &&
diff --git a/src/browser/modules/Stream/CypherFrame/VisualizationView/PropertiesPanelContent/StyleableRelType.tsx b/src/browser/modules/Stream/CypherFrame/VisualizationView/PropertiesPanelContent/StyleableRelType.tsx
index e79bfdc0ba2..a5ac847a924 100644
--- a/src/browser/modules/Stream/CypherFrame/VisualizationView/PropertiesPanelContent/StyleableRelType.tsx
+++ b/src/browser/modules/Stream/CypherFrame/VisualizationView/PropertiesPanelContent/StyleableRelType.tsx
@@ -21,44 +21,67 @@ import React from 'react'
 import { Popup } from 'semantic-ui-react'
 
 import { StyledRelationshipChip } from 'neo4j-arc/common'
-import { GraphStyleModel } from 'neo4j-arc/graph-visualization'
+import {
+  GraphInteractionCallBack,
+  GraphStyleModel,
+  REL_TYPE_UPDATE
+} from 'neo4j-arc/graph-visualization'
 
 import { GrassEditor } from './GrassEditor'
 
 export type StyleableRelTypeProps = {
   graphStyle: GraphStyleModel
   selectedRelType: { relType: string; propertyKeys: string[]; count?: number }
+  onGraphInteraction?: GraphInteractionCallBack
+  sourceNodeId?: string
+  targetNodeId?: string
 }
 export function StyleableRelType({
   selectedRelType,
-  graphStyle
+  graphStyle,
+  onGraphInteraction = () => undefined,
+  sourceNodeId,
+  targetNodeId
 }: StyleableRelTypeProps): JSX.Element {
   const styleForRelType = graphStyle.forRelationship({
     type: selectedRelType.relType
   })
   return (
-    <Popup
-      on="click"
-      basic
-      key={selectedRelType.relType}
-      position="left center"
-      offset={[0, 0]}
-      trigger={
-        <StyledRelationshipChip
-          style={{
-            backgroundColor: styleForRelType.get('color'),
-            color: styleForRelType.get('text-color-internal')
-          }}
-          data-testid={`property-details-overview-relationship-type-${selectedRelType.relType}`}
-        >
-          {selectedRelType.count !== undefined
-            ? `${selectedRelType.relType} (${selectedRelType.count})`
-            : `${selectedRelType.relType}`}
-        </StyledRelationshipChip>
+    <div
+      suppressContentEditableWarning={true}
+      contentEditable="true"
+      onInput={e =>
+        onGraphInteraction(REL_TYPE_UPDATE, {
+          sourceNodeId: sourceNodeId,
+          targetNodeId: targetNodeId,
+          oldType: selectedRelType.relType,
+          newType: e.currentTarget.textContent
+        })
       }
-      wide
     >
-      <GrassEditor selectedRelType={selectedRelType} />
-    </Popup>
+      <Popup
+        on="click"
+        basic
+        key={selectedRelType.relType}
+        position="left center"
+        offset={[0, 0]}
+        trigger={
+          <StyledRelationshipChip
+            style={{
+              backgroundColor: styleForRelType.get('color'),
+              color: styleForRelType.get('text-color-internal')
+            }}
+            data-testid={`property-details-overview-relationship-type-${selectedRelType.relType}`}
+          >
+            {selectedRelType.count !== undefined
+              ? `${selectedRelType.relType} (${selectedRelType.count})`
+              : `${selectedRelType.relType}`}
+          </StyledRelationshipChip>
+        }
+        wide
+      >
+        <GrassEditor selectedRelType={selectedRelType} />
+      </Popup>
+    </div>
   )
 }
diff --git a/src/browser/modules/Stream/CypherFrame/VisualizationView/VisualizationView.tsx b/src/browser/modules/Stream/CypherFrame/VisualizationView/VisualizationView.tsx
index 18417afc061..bd22a3b71b3 100644
--- a/src/browser/modules/Stream/CypherFrame/VisualizationView/VisualizationView.tsx
+++ b/src/browser/modules/Stream/CypherFrame/VisualizationView/VisualizationView.tsx
@@ -28,9 +28,11 @@ import {
   GraphInteractionCallBack,
   GraphModel,
   GraphVisualizer,
+  REL_ON_CANVAS_CREATE,
   NODE_ON_CANVAS_CREATE,
   NODE_PROP_UPDATE,
-  NODE_LABEL_UPDATE
+  NODE_LABEL_UPDATE,
+  REL_TYPE_UPDATE
 } from 'neo4j-arc/graph-visualization'
 
 import { StyledVisContainer } from './VisualizationView.styled'
@@ -279,6 +281,37 @@ LIMIT ${maxNewNeighbours}`
   }
 
   onGraphInteraction: GraphInteractionCallBack = (event, properties) => {
+    if (event == REL_TYPE_UPDATE) {
+      if (properties == null) {
+        throw new Error(
+          'A property map with sourceNodeId, targetNodeId, oldType, and newType keys are required'
+        )
+      }
+
+      const sourceNodeId = properties['sourceNodeId']
+      const targetNodeId = properties['targetNodeId']
+      const oldType = properties['oldType']
+      const newType = properties['newType']
+
+      const type = `\`${oldType}\``
+
+      const query = `MATCH (source)-[rel:${type}]->(target) WHERE ID(source) = ${sourceNodeId} AND ID(target) = ${targetNodeId} CALL apoc.refactor.setType(rel, '${newType}') YIELD input, output RETURN input, output;`
+
+      this.props.bus.self(
+        CYPHER_REQUEST,
+        {
+          query,
+          params: { sourceNodeId, targetNodeId, oldType, newType },
+          queryType: NEO4J_BROWSER_USER_ACTION_QUERY
+        },
+        (response: any) => {
+          if (!response.success) {
+            throw new Error(response.error)
+          }
+        }
+      )
+    }
+
     if (event == NODE_LABEL_UPDATE) {
       if (properties == null) {
         throw new Error(
@@ -291,7 +324,7 @@ LIMIT ${maxNewNeighbours}`
       const newLabel = `\`${properties['newLabel']}\``
 
       const query = `MATCH(n) WHERE ID(n) = ${nodeId} REMOVE n:${oldLabel} SET n:${newLabel}`
-      console.log(query)
+
       this.props.bus.self(
         CYPHER_REQUEST,
         {
@@ -309,7 +342,9 @@ LIMIT ${maxNewNeighbours}`
 
     if (event == NODE_PROP_UPDATE) {
       if (properties == null) {
-        throw new Error('')
+        throw new Error(
+          'A property map with nodeId, propKey, and propVal keys are required'
+        )
       }
 
       const nodeId = properties['nodeId']
@@ -334,6 +369,34 @@ LIMIT ${maxNewNeighbours}`
       )
     }
 
+    if (event == REL_ON_CANVAS_CREATE) {
+      if (properties == null) {
+        throw new Error(
+          'A property map with sourceNodeId, targetNodeId, and type keys are required'
+        )
+      }
+
+      const sourceNodeId = properties['sourceNodeId']
+      const targetNodeId = properties['targetNodeId']
+      const type = properties['type']
+
+      const query = `MATCH (source), (target) WHERE ID(source) = ${sourceNodeId} AND ID(target) = ${targetNodeId} CREATE (source)-[r:\`${type}\` {name: "new link"}]->(target) RETURN type(r);`
+
+      this.props.bus.self(
+        CYPHER_REQUEST,
+        {
+          query,
+          params: { sourceNodeId, targetNodeId, type },
+          queryType: NEO4J_BROWSER_USER_ACTION_QUERY
+        },
+        (response: any) => {
+          if (!response.success) {
+            throw new Error(response.error)
+          }
+        }
+      )
+    }
+
     if (event == NODE_ON_CANVAS_CREATE) {
       if (properties == null) {
         throw new Error(
diff --git a/src/neo4j-arc/common/components/PropertiesTable/PropertiesTable.test.tsx b/src/neo4j-arc/common/components/PropertiesTable/PropertiesTable.test.tsx
index 4e08e0d0337..6ca69352c40 100644
--- a/src/neo4j-arc/common/components/PropertiesTable/PropertiesTable.test.tsx
+++ b/src/neo4j-arc/common/components/PropertiesTable/PropertiesTable.test.tsx
@@ -20,7 +20,7 @@
 import { render, screen, waitFor } from '@testing-library/react'
 import React from 'react'
 
-import { VizItem } from 'neo4j-arc/graph-visualization'
+import { VizItem, NodeModel } from 'neo4j-arc/graph-visualization'
 
 import {
   PropertiesTable,
@@ -62,7 +62,9 @@ describe('<DetailsPane />', () => {
           item: {
             id: 'abc',
             type: 'abc2',
-            propertyList
+            propertyList,
+            source: new NodeModel('1', [], {}, {}),
+            target: new NodeModel('2', [], {}, {})
           }
         }
     }
diff --git a/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/DefaultDetailsPane.test.tsx b/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/DefaultDetailsPane.test.tsx
index 29d3a31d729..8be6bf05a76 100644
--- a/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/DefaultDetailsPane.test.tsx
+++ b/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/DefaultDetailsPane.test.tsx
@@ -27,6 +27,7 @@ import {
 import { VizItemProperty } from 'neo4j-arc/common'
 import { GraphStyleModel } from '../../models/GraphStyle'
 import { VizItem } from '../../types'
+import { NodeModel } from 'neo4j-arc/graph-visualization'
 
 describe('<DetailsPane />', () => {
   const mockGraphStyle = new GraphStyleModel()
@@ -70,7 +71,9 @@ describe('<DetailsPane />', () => {
           item: {
             id: 'abc',
             type: 'abc2',
-            propertyList
+            propertyList,
+            source: new NodeModel('1', [], {}, {}),
+            target: new NodeModel('2', [], {}, {})
           }
         }
     }
diff --git a/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/DefaultDetailsPane.tsx b/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/DefaultDetailsPane.tsx
index a02a7c0cf86..02d10efb76b 100644
--- a/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/DefaultDetailsPane.tsx
+++ b/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/DefaultDetailsPane.tsx
@@ -79,6 +79,9 @@ export function DefaultDetailsPane({
               relType: vizItem.item.type
             }}
             graphStyle={graphStyle}
+            onGraphInteraction={onGraphInteraction}
+            sourceNodeId={vizItem.item.source.id}
+            targetNodeId={vizItem.item.target.id}
           />
         )}
         {vizItem.type === 'node' &&
diff --git a/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/RelType.tsx b/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/RelType.tsx
index 8b4cbd62969..662d4c6cac3 100644
--- a/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/RelType.tsx
+++ b/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/RelType.tsx
@@ -21,28 +21,54 @@ import React from 'react'
 
 import { GraphStyleModel } from '../../models/GraphStyle'
 import { NonClickableRelTypeChip } from './styled'
+import {
+  GraphInteractionCallBack,
+  REL_TYPE_UPDATE
+} from '../Graph/GraphEventHandlerModel'
 
 export type RelTypeProps = {
   graphStyle: GraphStyleModel
   selectedRelType: { relType: string; propertyKeys: string[]; count?: number }
+  onGraphInteraction?: GraphInteractionCallBack
+  sourceNodeId?: string
+  targetNodeId?: string
+}
+RelType.defaultProps = {
+  onGraphInteraction: () => undefined
 }
 export function RelType({
   selectedRelType,
-  graphStyle
+  graphStyle,
+  onGraphInteraction = () => undefined,
+  sourceNodeId,
+  targetNodeId
 }: RelTypeProps): JSX.Element {
   const styleForRelType = graphStyle.forRelationship({
     type: selectedRelType.relType
   })
   return (
-    <NonClickableRelTypeChip
-      style={{
-        backgroundColor: styleForRelType.get('color'),
-        color: styleForRelType.get('text-color-internal')
-      }}
+    <div
+      suppressContentEditableWarning={true}
+      contentEditable="true"
+      onInput={e =>
+        onGraphInteraction(REL_TYPE_UPDATE, {
+          sourceNodeId: sourceNodeId,
+          targetNodeId: targetNodeId,
+          oldType: selectedRelType.relType,
+          newType: e.currentTarget.textContent
+        })
+      }
     >
-      {selectedRelType.count !== undefined
-        ? `${selectedRelType.relType} (${selectedRelType.count})`
-        : `${selectedRelType.relType}`}
-    </NonClickableRelTypeChip>
+      <NonClickableRelTypeChip
+        style={{
+          backgroundColor: styleForRelType.get('color'),
+          color: styleForRelType.get('text-color-internal')
+        }}
+      >
+        {selectedRelType.count !== undefined
+          ? `${selectedRelType.relType} (${selectedRelType.count})`
+          : `${selectedRelType.relType}`}
+      </NonClickableRelTypeChip>
+    </div>
   )
 }
diff --git a/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/GraphEventHandlerModel.ts b/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/GraphEventHandlerModel.ts
index d64aba685ef..3ba4a6f935b 100644
--- a/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/GraphEventHandlerModel.ts
+++ b/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/GraphEventHandlerModel.ts
@@ -33,6 +33,8 @@ import { Visualization } from './visualization/Visualization'
 export const NODE_ON_CANVAS_CREATE = 'NODE_ON_CANVAS_CREATE'
 export const NODE_PROP_UPDATE = 'NODE_PROP_UPDATE'
 export const NODE_LABEL_UPDATE = 'NODE_LABEL_UPDATE'
+export const REL_ON_CANVAS_CREATE = 'REL_ON_CANVAS_CREATE'
+export const REL_TYPE_UPDATE = 'REL_TYPE_UPDATE'
 
 export type GraphInteraction =
   | 'NODE_EXPAND'
@@ -42,6 +44,8 @@ export type GraphInteraction =
   | typeof NODE_ON_CANVAS_CREATE
   | typeof NODE_PROP_UPDATE
   | typeof NODE_LABEL_UPDATE
+  | typeof REL_ON_CANVAS_CREATE
+  | typeof REL_TYPE_UPDATE
 
 export type GraphInteractionCallBack = (
   event: GraphInteraction,
@@ -58,6 +62,9 @@ export class GraphEventHandlerModel {
   onGraphInteraction: GraphInteractionCallBack
   selectedItem: NodeModel | RelationshipModel | null
 
+  private altCreatedRelSourceNode: any
+  private altCreatedRelTargetNode: any
+
   constructor(
     graph: GraphModel,
     visualization: Visualization,
@@ -76,6 +83,9 @@ export class GraphEventHandlerModel {
     this.onGraphInteraction = onGraphInteraction ?? (() => undefined)
 
     this.onGraphModelChange = onGraphModelChange
+
+    this.altCreatedRelSourceNode = null
+    this.altCreatedRelTargetNode = null
   }
 
   graphModelChanged(): void {
@@ -274,6 +284,56 @@ export class GraphEventHandlerModel {
     })
   }
 
+  nodeAltDown(node: NodeModel): void {
+    if (!node) {
+      return
+    }
+
+    if (
+      this.altCreatedRelSourceNode == null &&
+      this.altCreatedRelTargetNode == null
+    ) {
+      this.altCreatedRelSourceNode = node
+    } else if (
+      this.altCreatedRelSourceNode != null &&
+      this.altCreatedRelTargetNode == null
+    ) {
+      this.altCreatedRelTargetNode = node
+
+      const maxId: number = Math.max(
+        ...this.graph
+          .relationships()
+          .map(relationship => parseInt(relationship.id))
+      )
+      const newId = maxId + 1
+
+      const altCreatedRel: RelationshipModel = new RelationshipModel(
+        newId.toString(),
+        this.altCreatedRelSourceNode,
+        this.altCreatedRelTargetNode,
+        newId.toString(),
+        { name: 'new link' },
+        { name: 'string' }
+      )
+
+      this.graph.addRelationships([altCreatedRel])
+      this.visualization.update({
+        updateNodes: true,
+        updateRelationships: true
+      })
+      this.graphModelChanged()
+
+      this.onGraphInteraction(REL_ON_CANVAS_CREATE, {
+        type: newId,
+        sourceNodeId: this.altCreatedRelSourceNode.id,
+        targetNodeId: this.altCreatedRelTargetNode.id
+      })
+
+      this.altCreatedRelSourceNode = null
+      this.altCreatedRelTargetNode = null
+    }
+  }
+
   bindEventHandlers(): void {
     this.visualization
       .on('nodeMouseOver', this.onNodeMouseOver.bind(this))
@@ -289,6 +349,7 @@ export class GraphEventHandlerModel {
       .on('nodeClicked', this.nodeClicked.bind(this))
       .on('nodeDblClicked', this.nodeDblClicked.bind(this))
       .on('nodeUnlock', this.nodeUnlock.bind(this))
+      .on('nodeAltDown', this.nodeAltDown.bind(this))
     this.onItemMouseOut()
   }
 }
diff --git a/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/visualization/mouseEventHandlers.ts b/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/visualization/mouseEventHandlers.ts
index a65eb8e8f30..ffb28ae3689 100644
--- a/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/visualization/mouseEventHandlers.ts
+++ b/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/visualization/mouseEventHandlers.ts
@@ -66,6 +66,12 @@ export const nodeEventHandlers = (
     trigger('nodeMouseOut', node)
   }
 
+  const onNodeMouseDown = (_event: KeyboardEvent, node: NodeModel) => {
+    if (_event.altKey || _event.ctrlKey || _event.metaKey || _event.shiftKey) {
+      trigger('nodeAltDown', node)
+    }
+  }
+
   const dragstarted = (event: D3DragEvent<SVGGElement, NodeModel, any>) => {
     initialDragPosition = [event.x, event.y]
     restartedSimulation = false
@@ -115,6 +121,7 @@ export const nodeEventHandlers = (
     .on('mouseout', onNodeMouseOut)
     .on('click', onNodeClick)
     .on('dblclick', onNodeDblClick)
+    .on('mousedown', onNodeMouseDown)
 }
 
 export const relationshipEventHandlers = (
diff --git a/src/neo4j-arc/graph-visualization/index.ts b/src/neo4j-arc/graph-visualization/index.ts
index 145b62675a7..b683cc49442 100644
--- a/src/neo4j-arc/graph-visualization/index.ts
+++ b/src/neo4j-arc/graph-visualization/index.ts
@@ -18,6 +18,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+export { NodeModel } from './models/Node'
 export { GraphModel } from './models/Graph'
 export { GraphStyleModel, Selector } from './models/GraphStyle'
 
@@ -35,8 +36,10 @@ export type { DetailsPaneProps } from './GraphVisualizer/DefaultPanelContent/Def
 export type { OverviewPaneProps } from './GraphVisualizer/DefaultPanelContent/DefaultOverviewPane'
 
 export {
+  REL_ON_CANVAS_CREATE,
   NODE_ON_CANVAS_CREATE,
   NODE_PROP_UPDATE,
-  NODE_LABEL_UPDATE
+  NODE_LABEL_UPDATE,
+  REL_TYPE_UPDATE
 } from './GraphVisualizer/Graph/GraphEventHandlerModel'
 export type { GraphInteractionCallBack } from './GraphVisualizer/Graph/GraphEventHandlerModel'
diff --git a/src/neo4j-arc/graph-visualization/types.ts b/src/neo4j-arc/graph-visualization/types.ts
index cce0cc53526..e388f42bfeb 100644
--- a/src/neo4j-arc/graph-visualization/types.ts
+++ b/src/neo4j-arc/graph-visualization/types.ts
@@ -49,7 +49,10 @@ type StatusItem = {
 
 export type RelationshipItem = {
   type: 'relationship'
-  item: Pick<RelationshipModel, 'id' | 'type' | 'propertyList'>
+  item: Pick<
+    RelationshipModel,
+    'id' | 'type' | 'propertyList' | 'source' | 'target'
+  >
 }
 
 type CanvasItem = {