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
&lt;rtk-ui-provider id="provider" meeting="{meeting}" config="{newConfig}">
    &lt;!-- Your custom UI components here -->
&lt;/rtk-ui-provider>

In your component template, add the meeting component:

&lt;rtk-meeting [meeting]="meeting" [config]="config">&lt;/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: "&lt;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:
                '&lt;svg fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">&lt;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">&lt;/path>&lt;/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 =
            "&lt;svg xmlns='http://www.w3.org/2000/svg' width='24' height='24'>&lt;path d='M4 12l6 6 10-14' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/>&lt;/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: '&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">&lt;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" />&lt;/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:

&lt;rtk-ui-provider [meeting]="meeting" [config]="config">
    &lt;!-- Your custom UI components here -->
&lt;/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

UI Kit Addons·续 - 图1Docs

{"@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


Skip to content

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.