📖Browse Tutorials▼

Vue 3 (Composition API)

Vue 3

Integrating Strelit UI Kit with Vue 3 is clean and natural using

<script setup>

and Vue’s built-in

<Teleport>

or programmatic createApp() mounting.

1. Installation

Install the Strelit UI Kit package in your Vue 3 project:

npm install strelit-ui-kit

2. Docking Workspace Component (DockingWorkspace.vue)

In Vue 3, we can use <Teleport> to project reactive Vue components directly into the DOM containers created by Strelit Layout:

<script setup lang="ts">
import { ref, onMounted, onUnmounted, reactive } from 'vue';
import { StrelitLayout, LayoutConfig, ComponentContainer } from 'strelit-ui-kit';
import 'strelit-ui-kit/dist/css/strelit-base.css';
import 'strelit-ui-kit/dist/css/themes/strelit-dark-theme.css';

import TelemetryViewer from './TelemetryViewer.vue';
import LogStreamViewer from './LogStreamViewer.vue';

interface PortalSlot {
  id: string;
  target: HTMLElement;
  type: 'telemetry' | 'logs';
}

const layoutContainer = ref<HTMLElement | null>(null);
let layoutInstance: StrelitLayout | null = null;
const activeSlots = reactive<PortalSlot[]>([]);

onMounted(() => {
  if (!layoutContainer.value) return;

  const config: LayoutConfig = {
    root: {
      type: 'row',
      content: [
        {
          type: 'component',
          componentType: 'vuePortal',
          title: 'Live Telemetry',
          componentState: { slotType: 'telemetry', id: 'slot-telemetry' }
        },
        {
          type: 'component',
          componentType: 'vuePortal',
          title: 'Event Stream',
          componentState: { slotType: 'logs', id: 'slot-logs' }
        }
      ]
    }
  };

  // 1. Instantiate layout on container element
  layoutInstance = new StrelitLayout(layoutContainer.value);

  // 2. Register Vue component factory function
  layoutInstance.registerComponentFactoryFunction('vuePortal', (container: ComponentContainer, itemConfig) => {
    const el = container.element;
    const state = (itemConfig.componentState as { slotType: 'telemetry' | 'logs'; id: string }) || { slotType: 'telemetry', id: 'slot-default' };

    activeSlots.push({
      id: state.id,
      target: el,
      type: state.slotType
    });

    container.on('destroy', () => {
      const idx = activeSlots.findIndex(s => s.id === state.id);
      if (idx !== -1) activeSlots.splice(idx, 1);
    });
  });

  // 3. Load layout configuration
  layoutInstance.loadLayout(config);

  const handleResize = () => layoutInstance?.updateRootSize();
  window.addEventListener('resize', handleResize);
});

onUnmounted(() => {
  layoutInstance?.destroy();
});
</script>

<template>
  <div class="workspace-viewport">
    <div ref="layoutContainer" class="layout-target"></div>

    <!-- Teleport reactive Vue components into Strelit containers -->
    <Teleport v-for="slot in activeSlots" :key="slot.id" :to="slot.target">
      <TelemetryViewer v-if="slot.type === 'telemetry'" />
      <LogStreamViewer v-else-if="slot.type === 'logs'" />
    </Teleport>
  </div>
</template>

<style scoped>
.workspace-viewport {
  width: 100vw;
  height: 100vh;
  position: relative;
  overflow: hidden;
}
.layout-target {
  width: 100%;
  height: 100%;
}
</style>

3. Benefits of Vue 3 Teleport Pattern

  • Preserved Reactivity: Pinia stores, Vue 3 ref, and computed properties continue updating without re-initialization.

  • Scoped CSS: Scoped styles in your .vue single-file components work without modification.

  • Clean Destruction: Removing panels from Strelit triggers standard Vue lifecycle cleanup.

Whether you are building complex multi-screen trading terminals, enterprise data workspaces, or migrating from legacy layout engines, our team and community are here to help.

Open an Issue on GitHub →