Appearance
Virtual properties 
This example show how to use the Virtual Properties transformation to add virtual properties to the nodes and edges of the graph.
ts
import Ogma, { VirtualProperties } from '@linkurious/ogma';
type NodeData = {
  type: 'person';
  firstName: string;
  lastName: string;
};
type EdgeData = {};
const ogma = new Ogma<NodeData, EdgeData>({
  container: 'graph-container',
  options: {
    backgroundColor: '#f6f6f6'
  },
  graph: {
    nodes: [
      {
        id: 0,
        data: { type: 'person', firstName: 'John', lastName: 'Smith' },
        attributes: { x: 0, y: 0 }
      },
      {
        id: 1,
        data: { type: 'person', firstName: 'James', lastName: 'Brown' },
        attributes: { x: 30, y: 0 }
      }
    ]
  }
});
ogma.styles.addRule({
  nodeAttributes: {
    text: node => {
      const data = node.getData();
      return Object.keys(data)
        .map(key => {
          const value = data[key as keyof NodeData];
          return key + ': ' + value;
        })
        .join('\n');
    },
    color: 'orange',
    icon: {
      content: '\uf007',
      font: 'Font Awesome 5 Free'
    }
  }
});
const button = document.getElementById('btn') as HTMLButtonElement;
let transformation: VirtualProperties<NodeData, EdgeData> | null;
const enableButton = () => {
  button.disabled = false;
  button.textContent = button.textContent === 'Apply' ? 'Undo' : 'Apply';
};
document.getElementById('btn')!.addEventListener('click', async () => {
  if (transformation) {
    await transformation.destroy(500);
    enableButton();
    button.disabled = true;
    transformation = null;
  } else {
    transformation = ogma.transformations.addVirtualProperties({
      nodeSelector: node => node.getData('type') === 'person',
      nodeDataFunction: node => ({
        fullName: node.getData('firstName') + ' ' + node.getData('lastName')
      })
    });
    button.disabled = true;
    await transformation.whenApplied();
    enableButton();
  }
});html
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <link
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/solid.min.css"
      rel="stylesheet"
    />
    <link type="text/css" rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <div id="graph-container"></div>
    <div class="panel">
      <button id="btn">Apply</button>
    </div>
    <script type="module" src="index.ts"></script>
  </body>
</html>css
html,
body {
  font-family: 'Inter', sans-serif;
}
:root {
  --base-color: #4999f7;
  --active-color: var(--base-color);
  --gray: #d9d9d9;
  --white: #ffffff;
  --lighter-gray: #f4f4f4;
  --light-gray: #e6e6e6;
  --inactive-color: #cee5ff;
  --group-color: #525fe1;
  --group-inactive-color: #c2c8ff;
  --selection-color: #04ddcb;
  --darker-gray: #b6b6b6;
  --dark-gray: #555;
  --dark-color: #3a3535;
  --edge-color: var(--dark-color);
  --border-radius: 5px;
  --button-border-radius: var(--border-radius);
  --edge-inactive-color: var(--light-gray);
  --button-background-color: #ffffff;
  --shadow-color: rgba(0, 0, 0, 0.25);
  --shadow-hover-color: rgba(0, 0, 0, 0.5);
  --button-shadow: 0 0 4px var(--shadow-color);
  --button-shadow-hover: 0 0 4px var(--shadow-hover-color);
  --button-icon-color: #000000;
  --button-icon-hover-color: var(--active-color);
}
#graph-container {
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  position: absolute;
  margin: 0;
  overflow: hidden;
}
.ui {
  position: absolute;
  display: flex;
  flex-direction: column;
  gap: 0.5em;
}
#custom-group-btn {
  top: 40px;
}
.panel {
  background: var(--button-background-color);
  border-radius: var(--button-border-radius);
  box-shadow: var(--button-shadow);
  padding: 10px;
}
.panel {
  position: absolute;
  top: 20px;
  left: 20px;
}
.panel h2 {
  text-transform: uppercase;
  font-weight: 400;
  font-size: 14px;
  margin: 0;
}
.panel {
  margin-top: 1px;
  padding: 5px 10px;
  text-align: center;
}
.panel button {
  background: var(--button-background-color);
  border: none;
  border-radius: var(--button-border-radius);
  border-color: var(--shadow-color);
  padding: 5px 10px;
  cursor: pointer;
  width: 100%;
  color: var(--dark-gray);
  border: 1px solid var(--light-gray);
}
.panel button:hover {
  background: var(--lighter-gray);
  border: 1px solid var(--darker-gray);
}
.panel button[disabled] {
  color: var(--light-gray);
  border: 1px solid var(--light-gray);
  background-color: var(--lighter-gray);
}