Vue 3 Integration (Composition API)
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>
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
.vuesingle-file components work without modification. - Clean Destruction: Removing panels from Strelit triggers standard Vue lifecycle cleanup.