Add Custom Controlbar
Last updated Oct 19, 2026 Prerequisite
This guide builds on top of the Build Your Own UI. It is recommended to read that guide first. Portions of the code will not be repeated here for brevity.
For a complete list of available UI Kit components, refer to the Component Library.
In this guide, we will learn how to add a custom controlbar for your RealtimeKit meeting experience.
WebMobile
ReactWeb ComponentsAngular
RealtimeKit UI Kit provides the RtkControlbar component for a default controlbar.
If you need additional controls, replace RtkControlbar with individual UI Kit components and custom elements.
Import the required components and React hook:
import { useRef } from "react";
import {
RtkFullscreenToggle,
RtkSettingsToggle,
RtkScreenShareToggle,
RtkMicToggle,
RtkCameraToggle,
RtkStageToggle,
RtkLeaveButton,
RtkMoreToggle,
RtkPipToggle,
RtkMuteAllButton,
RtkBreakoutRoomsToggle,
RtkRecordingToggle,
RtkChatToggle,
RtkPollsToggle,
RtkParticipantsToggle,
RtkPluginsToggle,
} from "@cloudflare/realtimekit-ui";
In your RtkUIProvider from Build Your Own UI, replace:
<RtkControlbar />
with:
<div
style={{
display: "flex",
width: "100%",
padding: "8px 12px",
color: "white",
justifyContent: "space-between",
}}
>
<div
id="controlbar-left"
style={{ display: "flex", alignItems: "center", justifyContent: "center" }}
>
<RtkFullscreenToggle targetElement={fullScreenRef.current} />
<RtkSettingsToggle />
<RtkScreenShareToggle />
</div>
<div
id="controlbar-center"
style={{ display: "flex", alignItems: "center", justifyContent: "center" }}
>
<RtkMicToggle />
<RtkCameraToggle />
<RtkStageToggle />
<RtkLeaveButton />
<RtkMoreToggle>
<div slot="more-elements">
<RtkPipToggle variant="horizontal" />
<RtkMuteAllButton variant="horizontal" />
<RtkBreakoutRoomsToggle variant="horizontal" />
<RtkRecordingToggle variant="horizontal" />
</div>
</RtkMoreToggle>
</div>
<div
id="controlbar-right"
style={{ display: "flex", alignItems: "center", justifyContent: "center" }}
>
<RtkChatToggle />
<RtkPollsToggle />
<RtkParticipantsToggle />
<RtkPluginsToggle />
</div>
</div>
Define a ref for the fullscreen target and attach it to your container element:
const fullScreenRef = useRef<HTMLDivElement>(null);
// In your RtkUIProvider, add the ref to the container
<RtkUIProvider
ref={fullScreenRef}
meeting={meeting}
showSetupScreen={false}
style={{
display: "flex",
flexDirection: "column",
height: "100vh",
margin: 0,
}}
>
{/* Your controlbar and other components */}
</RtkUIProvider>
// Pass the ref's current element to RtkFullscreenToggle
<RtkFullscreenToggle targetElement={fullScreenRef.current} />
A complete example to build your own UI with custom controlbar can be found here ↗︎ with the custom controlbar component here ↗︎.
RealtimeKit UI Kit provides the rtk-controlbar component for a default controlbar.
If you need additional controls, replace rtk-controlbar with individual UI Kit components and custom elements. In the renderJoinedScreen function from Build Your Own UI, replace:
<rtk-controlbar
style="display: flex; justify-content: space-between;"
></rtk-controlbar>
with:
<div
style="display: flex; width: 100%; padding: 8px 12px; color: white; justify-content: space-between;"
>
<div
id="controlbar-left"
style="display: flex; align-items: center; justify-content: center;"
>
<rtk-fullscreen-toggle id="fullscreen-toggle"></rtk-fullscreen-toggle>
<rtk-settings-toggle></rtk-settings-toggle>
<rtk-screen-share-toggle></rtk-screen-share-toggle>
</div>
<div
id="controlbar-center"
style="display: flex; align-items: center; justify-content: center;"
>
<rtk-mic-toggle></rtk-mic-toggle>
<rtk-camera-toggle></rtk-camera-toggle>
<rtk-stage-toggle></rtk-stage-toggle>
<rtk-leave-button></rtk-leave-button>
<rtk-more-toggle>
<div slot="more-elements">
<rtk-pip-toggle variant="horizontal"></rtk-pip-toggle>
<rtk-mute-all-button variant="horizontal"></rtk-mute-all-button>
<rtk-breakout-rooms-toggle
variant="horizontal"
></rtk-breakout-rooms-toggle>
<rtk-recording-toggle variant="horizontal"></rtk-recording-toggle>
</div>
</rtk-more-toggle>
</div>
<div
id="controlbar-right"
style="display: flex; align-items: center; justify-content: center;"
>
<rtk-chat-toggle></rtk-chat-toggle>
<rtk-polls-toggle></rtk-polls-toggle>
<rtk-participants-toggle></rtk-participants-toggle>
<rtk-plugins-toggle></rtk-plugins-toggle>
</div>
</div>
Register the fullscreen target after rendering:
const fullscreenToggle = document.querySelector("#fullscreen-toggle");
if (fullscreenToggle) {
const targetElement = document.querySelector("rtk-ui-provider");
if (targetElement) {
fullscreenToggle.targetElement = targetElement;
}
}
A complete example to build your own UI with custom controlbar can be found here ↗︎ with the custom controlbar component here ↗︎.
RealtimeKit UI Kit provides the rtk-controlbar component for a default controlbar.
If you need additional controls, replace rtk-controlbar with individual UI Kit components and custom elements. Create a custom controlbar component that uses the RealtimeKit angular components directly.
Create Custom Controlbar Component
custom-controlbar.component.tstypescript
import { Component, AfterViewInit, ElementRef, ViewChild } from "@angular/core";
@Component({
selector: "app-custom-controlbar",
template: `
<div class="custom-controlbar">
<div class="controlbar-left">
<rtk-fullscreen-toggle #fullscreenToggle></rtk-fullscreen-toggle>
<rtk-settings-toggle></rtk-settings-toggle>
<rtk-screen-share-toggle></rtk-screen-share-toggle>
</div>
<div class="controlbar-center">
<rtk-mic-toggle></rtk-mic-toggle>
<rtk-camera-toggle></rtk-camera-toggle>
<rtk-stage-toggle></rtk-stage-toggle>
<rtk-leave-button></rtk-leave-button>
<rtk-more-toggle>
<div slot="more-elements">
<rtk-pip-toggle variant="horizontal"></rtk-pip-toggle>
<rtk-mute-all-button variant="horizontal"></rtk-mute-all-button>
<rtk-breakout-rooms-toggle
variant="horizontal"
></rtk-breakout-rooms-toggle>
<rtk-recording-toggle variant="horizontal"></rtk-recording-toggle>
</div>
</rtk-more-toggle>
</div>
<div class="controlbar-right">
<rtk-chat-toggle></rtk-chat-toggle>
<rtk-polls-toggle></rtk-polls-toggle>
<rtk-participants-toggle></rtk-participants-toggle>
<rtk-plugins-toggle></rtk-plugins-toggle>
</div>
</div>
`,
styles: [
`
.custom-controlbar {
display: flex;
width: 100%;
padding: 8px 12px;
color: white;
justify-content: space-between;
background-color: rgba(0, 0, 0, 0.8);
border-radius: 8px;
}
.controlbar-left,
.controlbar-center,
.controlbar-right {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.controlbar-center {
flex: 1;
justify-content: center;
}
`,
],
})
export class CustomControlbarComponent implements AfterViewInit {
@ViewChild("fullscreenToggle", { static: true })
fullscreenToggle!: ElementRef;
ngAfterViewInit() {
// Register the fullscreen target after rendering
this.setupFullscreenToggle();
}
private setupFullscreenToggle() {
const fullscreenElement = this.fullscreenToggle?.nativeElement;
if (fullscreenElement) {
const targetElement = document.querySelector("rtk-ui-provider");
if (targetElement) {
fullscreenElement.targetElement = targetElement;
}
}
}
}
Use in Your Meeting Component
In your main meeting component template, replace:
<rtk-controlbar
style="display: flex; justify-content: space-between;"
></rtk-controlbar>
with:
<app-custom-controlbar></app-custom-controlbar>
Complete Meeting Component Example
meeting.component.tstypescript
import {
Component,
ElementRef,
OnInit,
OnDestroy,
ViewChild,
} from "@angular/core";
@Component({
selector: "app-meeting",
template: `
<rtk-meeting #meetingComponent id="meeting-component">
<!-- Other meeting UI components -->
<rtk-grid></rtk-grid>
<rtk-sidebar></rtk-sidebar>
<!-- Custom controlbar replaces rtk-controlbar -->
<app-custom-controlbar></app-custom-controlbar>
</rtk-meeting>
`,
})
export class MeetingComponent implements OnInit, OnDestroy {
@ViewChild("meetingComponent", { static: true }) meetingElement!: ElementRef;
meeting: any;
private authToken = "<participant_auth_token>";
async ngOnInit() {
const RealtimeKitClient = await import(
"https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit@latest/dist/index.es.js"
);
this.meeting = await RealtimeKitClient.default.init({
authToken: this.authToken,
});
const meetingComponent = this.meetingElement.nativeElement;
meetingComponent.showSetupScreen = true;
meetingComponent.meeting = this.meeting;
}
ngOnDestroy() {
// Cleanup logic
}
}
Module Configuration
Don't forget to declare your custom controlbar component in your Angular module:
app.module.tstypescript
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";
import { MeetingComponent } from "./meeting.component";
import { CustomControlbarComponent } from "./custom-controlbar.component";
@NgModule({
declarations: [AppComponent, MeetingComponent, CustomControlbarComponent],
imports: [BrowserModule],
providers: [],
bootstrap: [AppComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA], // Required for RTK web components
})
export class AppModule {}
Advanced Customization
You can further customize the controlbar by adding your own buttons or modifying the layout:
enhanced-controlbar.component.tstypescript
```typescript import { Component, AfterViewInit, ElementRef, ViewChild } from "@angular/core";
@Component({ selector: "app-enhanced-controlbar", template: ` <div class="custom-controlbar"> <div class="controlbar-left"> <rtk-fullscreen-toggle #fullscreenToggle></rtk-fullscreen-toggle> <rtk-settings-toggle></rtk-settings-toggle> <button class="custom-button" (click)="onCustomAction()"> Custom Action </button> </div>
<div class="controlbar-center"> <rtk-mic-toggle></rtk-mic-toggle> <rtk-camera-toggle></rtk-camera-toggle> <rtk-stage-toggle></rtk-stage-toggle> <rtk-leave-button></rtk-leave-button> </div>
<div class="controlbar-right">
<rtk-chat-toggle></rtk-chat-toggle>
<rtk-participants-toggle></rtk-participants-toggle>
</div>
</div>
,
styles: [
.custom-controlbar {
display: flex;
width: 100%;
padding: 8px 12px;
color: white;
justify-content: space-between;
background-color: rgba(0, 0, 0, 0.8);
border-radius: 8px;
}
.controlbar-left, .controlbar-center, .controlbar-right { display: flex; align-items: center; justify-content: center; gap: 8px; }
.custom-button { background: #0051c3; border: none; color: white; padding: 8px 12px; border-radius: 4px; cursor: pointer; font-size: 12px; }
.custom-button:hover { background: #003d99; } `, ], }) export class EnhancedControlbarComponent implements AfterViewInit { @ViewChild("fullscreenToggle", { static: true }) fullscreenToggle!: ElementRef;
ngAfterViewInit() { this.setupFullscreenToggle(); }
private setupFullscreenToggle() { const fullscreenElement = this.fullscreenToggle?.nativeElement; if (fullscreenElement) { const targetElement = document.querySelector("rtk-ui-provider"); if (targetElement) { fullscreenElement.targetElement = targetElement; } } }
