UI Kit Addons·续
// Participant Tab Actions const rightTickSVG = "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24'><path d='M4 12l6 6 10-14' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>";
const participantMenuItem = new ParticipantMenuItem({ label: "Custom Menu Item", icon: rightTickSVG, styles: "rtk-icon { color: green !important; }", onClick: () => { alert("Participant Menu Item clicked"); }, });
const participantsTabAction = new ParticipantsTabAction({ onClick: () => { alert("Clicked!"); }, label: "Click me", position: "start", });
const participantsTabToggle = new ParticipantsTabToggle({ onEnabled: () => { alert("toggled true!"); }, onDisabled: () => { alert("toggled false!"); }, label: "Click me", initialValue: () => true, position: "start", });
// Video Background (Effects) const videoBackground = await RealtimeKitVideoBackground.init({ modes: ["blur", "virtual", "random"], blurStrength: 30, // 0 - 100 for opacity meeting, images: [ "https://images.unsplash.com/photo-1487088678257-3a541e6e3922?q=80&w=2874&auto=format&fit=crop&ixlib=rb-4.0.3", "https://images.unsplash.com/photo-1496715976403-7e36dc43f17b?q=80&w=2848&auto=format&fit=crop&ixlib=rb-4.0.3", "https://images.unsplash.com/photo-1600431521340-491eca880813?q=80&w=2938&auto=format&fit=crop&ixlib=rb-4.0.3", ], randomCount: 10, onVideoBackgroundUpdate: ({ backgroundMode, backgroundURL }) => { console.log("videoBackgroundUpdated => ", { backgroundMode, backgroundURL, }); }, });
// Control Bar const customControlBarButton = new CustomControlbarButton({ position: "left", icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M12 17.75a1.25 1.25 0 1 1 0 2.5a1.25 1.25 0 0 1 0-2.5zM12 14c0-2.5 4-2.5 4-6a4 4 0 1 0-8 0" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /></svg>', label: "Click Me!", onClick: () => alert("Custom Control Bar Button Clicked"), });
// Register addons const newConfig = registerAddons( [ cameraHostControl, micHostControl, chatHostControl, handRaise, reactionsAddon, participantTileMenu, participantMenuItem, participantsTabAction, participantsTabToggle, videoBackground, customControlBarButton, ], meeting, );
// Apply config to meeting component document.querySelector("rtk-meeting").showSetupScreen = true; document.querySelector("rtk-meeting").meeting = meeting; document.querySelector("rtk-meeting").config = newConfig; </script>
Note
If you are using `rtk-ui-provider` instead of the `rtk-meeting`, pass the `meeting` and `config` objects to the provider:
```html
<rtk-ui-provider id="provider" meeting="{meeting}" config="{newConfig}">
<!-- Your custom UI components here -->
</rtk-ui-provider>
In your component template, add the meeting component:
<rtk-meeting [meeting]="meeting" [config]="config"></rtk-meeting>
In your component TypeScript file:
import { Component, OnInit } from "@angular/core";
import RealtimeKitClient from "@cloudflare/realtimekit";
import { registerAddons, defaultConfig } from "@cloudflare/realtimekit-ui";
// Import addons
import CameraHostControl from "@cloudflare/realtimekit-ui-addons/camera-host-control";
import MicHostControl from "@cloudflare/realtimekit-ui-addons/mic-host-control";
import ChatHostControl from "@cloudflare/realtimekit-ui-addons/chat-host-control";
import HandRaise from "@cloudflare/realtimekit-ui-addons/hand-raise";
import ReactionsManagerAddon from "@cloudflare/realtimekit-ui-addons/reactions-manager";
import ParticipantTileMenu from "@cloudflare/realtimekit-ui-addons/participant-tile-menu";
import ParticipantMenuItem from "@cloudflare/realtimekit-ui-addons/participant-menu-item";
import ParticipantsTabAction from "@cloudflare/realtimekit-ui-addons/participants-tab-action";
import ParticipantsTabToggle from "@cloudflare/realtimekit-ui-addons/participants-tab-toggle";
import RealtimeKitVideoBackground from "@cloudflare/realtimekit-ui-addons/video-background";
import CustomControlbarButton from "@cloudflare/realtimekit-ui-addons/custom-controlbar-button";
@Component({
selector: "app-meeting",
templateUrl: "./meeting.component.html",
})
export class MeetingComponent implements OnInit {
meeting: any;
config: any = defaultConfig;
async ngOnInit() {
// Initialize meeting
this.meeting = await RealtimeKitClient.init({
authToken: "<participant_auth_token>",
});
// Initialize addons
const cameraHostControl = await CameraHostControl.init({
meeting: this.meeting,
hostPresets: ["webinar_presenter"],
targetPresets: ["webinar_viewer"],
addActionInParticipantMenu: true,
});
const micHostControl = await MicHostControl.init({
meeting: this.meeting,
hostPresets: ["webinar_presenter"],
targetPresets: ["webinar_viewer"],
addActionInParticipantMenu: true,
});
const chatHostControl = await ChatHostControl.init({
meeting: this.meeting,
hostPresets: ["webinar_presenter"],
targetPresets: ["webinar_viewer"],
addActionInParticipantMenu: true,
});
const handRaise = await HandRaise.init({
meeting: this.meeting,
canRaiseHand: true,
canManageRaisedHand: true,
handRaiseIcon:
'<svg fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M4 12.02c0 1.06.2 2.1.6 3.08l.6 1.42c.22.55.64 1.01 1.17 1.29.27.14.56.21.86.21h2.55c.77 0 1.49-.41 1.87-1.08.5-.87 1.02-1.7 1.72-2.43l1.32-1.39c.44-.46.97-.84 1.49-1.23l.59-.45a.6.6 0 0 0 .23-.47c0-.75-.54-1.57-1.22-1.79a3.34 3.34 0 0 0-2.78.29V4.5a1.5 1.5 0 0 0-2.05-1.4 1.5 1.5 0 0 0-2.9 0A1.5 1.5 0 0 0 6 4.5v.09A1.5 1.5 0 0 0 4 6v6.02ZM8 4.5v4a.5.5 0 0 0 1 0v-5a.5.5 0 0 1 1 0v5a.5.5 0 0 0 1 0v-4a.5.5 0 0 1 1 0v6a.5.5 0 0 0 .85.37h.01c.22-.22.44-.44.72-.58.7-.35 2.22-.57 2.4.5l-.53.4c-.52.4-1.04.78-1.48 1.24l-1.33 1.38c-.75.79-1.31 1.7-1.85 2.63-.21.36-.6.58-1.01.58H7.23a.87.87 0 0 1-.4-.1 1.55 1.55 0 0 1-.71-.78l-.59-1.42a7.09 7.09 0 0 1-.53-2.7V6a.5.5 0 0 1 1 0v3.5a.5.5 0 0 0 1 0v-5a.5.5 0 0 1 1 0Z" fill="#ff0000"></path></svg>',
});
const CUSTOM_REACTIONS = [
{ emoji: "🔥", label: "fire" },
{ emoji: "😢", label: "sad" },
{ emoji: "👍", label: "thumbs up" },
{ emoji: "👎", label: "thumbs down" },
{ emoji: "❤️", label: "heart" },
{ emoji: "😂", label: "laugh" },
{ emoji: "👏", label: "clap" },
{ emoji: "🎉", label: "celebrate" },
];
const reactionsAddon = await ReactionsManagerAddon.init({
meeting: this.meeting,
reactions: CUSTOM_REACTIONS,
canSendReactions: true,
});
const participantTileMenu = new ParticipantTileMenu(
[
{
label: "Custom Toggle",
onClick: (participantId: string) => {
console.log("Clicked on custom toggle for ", participantId);
},
},
],
"top-right",
);
const rightTickSVG =
"<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24'><path d='M4 12l6 6 10-14' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>";
const participantMenuItem = new ParticipantMenuItem({
label: "Custom Menu Item",
icon: rightTickSVG,
styles: "rtk-icon { color: green !important; }",
onClick: () => {
alert("Participant Menu Item clicked");
},
});
const participantsTabAction = new ParticipantsTabAction({
onClick: () => {
alert("Clicked!");
},
label: "Click me",
position: "start",
});
const participantsTabToggle = new ParticipantsTabToggle({
onEnabled: () => {
alert("toggled true!");
},
onDisabled: () => {
alert("toggled false!");
},
label: "Click me",
initialValue: () => true,
position: "start",
});
const videoBackground = await RealtimeKitVideoBackground.init({
modes: ["blur", "virtual", "random"],
blurStrength: 30,
meeting: this.meeting,
images: [
"https://images.unsplash.com/photo-1487088678257-3a541e6e3922?q=80&w=2874&auto=format&fit=crop&ixlib=rb-4.0.3",
"https://images.unsplash.com/photo-1496715976403-7e36dc43f17b?q=80&w=2848&auto=format&fit=crop&ixlib=rb-4.0.3",
"https://images.unsplash.com/photo-1600431521340-491eca880813?q=80&w=2938&auto=format&fit=crop&ixlib=rb-4.0.3",
],
randomCount: 10,
onVideoBackgroundUpdate: ({ backgroundMode, backgroundURL }: any) => {
console.log("videoBackgroundUpdated => ", {
backgroundMode,
backgroundURL,
});
},
});
const customControlBarButton = new CustomControlbarButton({
position: "left",
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M12 17.75a1.25 1.25 0 1 1 0 2.5a1.25 1.25 0 0 1 0-2.5zM12 14c0-2.5 4-2.5 4-6a4 4 0 1 0-8 0" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /></svg>',
label: "Click Me!",
onClick: () => alert("Custom Control Bar Button Clicked"),
});
// Register addons
this.config = registerAddons(
[
cameraHostControl,
micHostControl,
chatHostControl,
handRaise,
reactionsAddon,
participantTileMenu,
participantMenuItem,
participantsTabAction,
participantsTabToggle,
videoBackground,
customControlBarButton,
],
this.meeting,
);
}
}
Note
If you are using rtk-ui-provider instead of the rtk-meeting component, pass the meeting and config objects to the provider:
<rtk-ui-provider [meeting]="meeting" [config]="config">
<!-- Your custom UI components here -->
</rtk-ui-provider>
Programmatic Control
Some addons support programmatic control for dynamic changes during a meeting.
Video Background
You can apply, replace, or remove video backgrounds programmatically:
// Apply a virtual background
await videoBackground.applyVirtualBackground(
"https://images.unsplash.com/photo-1600431521340-491eca880813?q=80&w=2938&auto=format&fit=crop&ixlib=rb-4.0.3",
);
// Apply a blur background
await videoBackground.applyBlurBackground();
// Remove background (return to normal video)
await videoBackground.removeBackground();
Some addons support programmatic control for dynamic changes during a meeting.
Video Background
You can apply, replace, or remove video backgrounds programmatically:
// Apply a virtual background
await videoBackground.applyVirtualBackground(
"https://images.unsplash.com/photo-1600431521340-491eca880813?q=80&w=2938&auto=format&fit=crop&ixlib=rb-4.0.3",
);
// Apply a blur background
await videoBackground.applyBlurBackground();
// Remove background (return to normal video)
await videoBackground.removeBackground();
Some addons support programmatic control for dynamic changes during a meeting.
Video Background
You can apply, replace, or remove video backgrounds programmatically:
// Apply a virtual background
await videoBackground.applyVirtualBackground(
"https://images.unsplash.com/photo-1600431521340-491eca880813?q=80&w=2938&auto=format&fit=crop&ixlib=rb-4.0.3",
);
// Apply a blur background
await videoBackground.applyBlurBackground();
// Remove background (return to normal video)
await videoBackground.removeBackground();
Was this helpful?
YesNo
On this page
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/realtime/realtimekit/humans/ui-kit/addons/#page","headline":"UI Kit Addons","description":"Extend RealtimeKit UI Kit with addon components for host controls, reactions, and more.","url":"https://developers.cloudflare.com/realtime/realtimekit/humans/ui-kit/addons/","inLanguage":"en","image":"https://developers.cloudflare.com/realtime/realtimekit/humans/ui-kit/addons/og.png?v=d71272fad64cafad","dateModified":"2026-10-19","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
description: API reference for RealtimeKit UI Kit components, props, and configuration options. title: Component Reference image: https://developers.cloudflare.com/realtime/realtimekit/humans/ui-kit/api-reference/og.png?v=45595a996412b87d
Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/realtime/llms.txt
Use this file to discover all available pages before exploring further.
Docs