Skip to content

Participants Panel Component Documentation

File: src/components/app/call/participants.svelte

Overview

This comprehensive component manages participant interactions in a video conferencing application, combining participant management, chat functionality, and device control in a single panel. It serves as the central hub for all participant-related actions during a call.

Key Features

  1. Participant Management:

    • View all call participants with profile information
    • Mute/unmute audio and video
    • Pin/unpin participants
    • Raise/lower hands
    • Set host/guest roles
    • Remove participants
  2. Integrated Chat System:

    • Group chat with all participants
    • Private messaging
    • Unread message indicators
  3. Device & Participant Addition:

    • Add participants by name or email
    • Connect Headet device to the call
    • Rapid Connect functionality
  4. Detailed Views:

    • Participant details modal
    • User selection for Headset device authentication
    • Collapsible sections for better mobile experience

Component Structure

Module Context (Utility Functions)

typescript
// Participant spotlight controls
export function pin(pexip: PexipClient, participant)
export function unpin(pexip: PexipClient, participant)
export function toggleSpotlight(pexip: PexipClient, participant: IParticipant)

// Hand raising controls
export function lowerHand(pexip: PexipClient, participant)
export function raiseHand(pexip: PexipClient, participant)
export function toggleHand(pexip: PexipClient, participant: IParticipant)

// Audio controls
export function mute(pexip: PexipClient, participant)
export function unmute(pexip: PexipClient, participant)
export function toggleAudio(pexip: PexipClient, participant)

// Video controls
export function muteVideo(pexip: PexipClient, participant)
export function unmuteVideo(pexip: PexipClient, participant)
export function toggleVideo(pexip: PexipClient, participant)

// Participant management
export function remove(pexip: PexipClient, participant: IParticipant)
export function setAsGuest(pexip: PexipClient, participant: IParticipant)
export function setAsHost(pexip: PexipClient, participant: IParticipant)

// Search functions
export async function getContactSearch(filter: string)
export async function getDeviceSearch()

// Call addition functions
export async function summonDevice(eventId, tenantDeviceId, userId?)
export async function addToCall(eventId, contactId?, email?, joinCode?)
export async function addDeviceToCall(eventId, deviceId?, joinCode?, userId?)

Props

typescript
export let data = [];                      // Participant data array
export let contacts = [];                  // User contacts list
export let event;                         // Current event data
export let me: IParticipant;               // Current user participant data
export let pexip: PexipClient;             // Pexip client instance
export let cnt;                            // Participant count
export let canAddParticipants = true;      // Add participants permission
export let rapidUser: any = null;          // Rapid user data
export let readonly = false;               // Read-only mode flag

State Management

typescript
// UI state
let showParticipants = false;
let hideContactDetails = false;
let showChatView = false;
let showSearchBox = false;
let showSubMenu = false;
let showSelectUser = false;

// Data state
let inputValue;
let unreadMessageCount = 0;
let participants = [];
let activeContact;
let chatContactList = [];
let addContactFilter = "";
let addDeviceFilter = "";
let searchContacts = [];
let contactSearchError = "";
let deviceItems = [];
let summondData = {
  eventId: null,
  userId: null,
  tenantDeviceId: null,
  deviceName: ""
};

// Computed properties
$: nonStreamingParticipants = participants.filter(x => !x.is_streaming_conference);
$: user = rapidUser ? rapidUser : $userInfo;
$: activeGroup = { id: event?.id, kind: "event" };

UI Components

Main Panel Structure

svelte
<div class="h-full flex flex-col bg-white border-l border-gray-200">
  <!-- Header section -->
  <div class="flex justify-between border-b p-2">
    <span class="text-lg">Participants</span>
    <div class="flex gap-2 text-gray-600">
      <button on:click={() => dispatch("close")}>
        <Icon src={Close} size="20" />
      </button>
    </div>
  </div>

  <!-- Participants section -->
  <div>
    <div class="flex justify-between px-2">
      <span>Participants ({data.length})</span>
      <div class="flex gap-2">
        <button on:click={() => (showSearchBox = !showSearchBox)}>
          <Icon src={Search} size="15" />
        </button>
        <button on:click={() => (showParticipants = !showParticipants)}>
          <Icon src={showParticipants ? ArrowUpS : ArrowDownS} size="18" />
        </button>
      </div>
    </div>
  </div>

  <!-- Participant list and controls -->
  {#if showParticipants}
    <div class="m-2 flex flex-col">
      <!-- Add participant/device forms -->
      <Form>
        <SelectInput name="participants" ... />
        <SelectInput name="devices" ... />
      </Form>

      <!-- Participant list -->
      <ul class="max-h-full rounded-md border-t mt-1 divide-y divide-gray-200">
        {#each participants as participant}
          <!-- Participant item with controls -->
        {/each}
      </ul>
    </div>
  {/if}

  <!-- Chat section -->
  <div class="flex flex-col flex-grow overflow-y-hidden">
    <div class="flex justify-between border-b p-2">
      <span>Chat {#if unreadMessageCount}({unreadMessageCount}){/if}</span>
      <button on:click={toggleChatView}>
        <Icon src={showChatView ? ArrowUpS : ArrowDownS} size="17" />
      </button>
    </div>
    {#if showChatView}
      <MessageList ... />
    {/if}
  </div>
</div>

Participant Item Controls

Each participant item includes:

  • Profile image/initials
  • Name and specialty
  • Interactive controls:
    • Pin/unpin
    • Raise/lower hand
    • Mute/unmute audio
    • Mute/unmute video
    • Admin indicators
    • Overflow menu with additional actions

Modals

  1. Contact Details Modal:

    • Shows detailed participant information
    • Triggered by clicking "View Details"
  2. User Selection Modal:

    • Appears when device requires user authentication
    • Allows selecting a user to authorize device connection

Technical Implementation

Data Flow

  1. Participant Data Processing:

    • Filters and maps raw participant data
    • Enriches with contact information
    • Computes display properties (initials, status)
  2. Search Functionality:

    • Debounced contact search
    • Device search with online status
    • Custom filtering for emails and join codes

Event Handling

  1. Participant Actions:

    • Wrapped in pexec helper for error handling
    • Dispatched to Pexip client
    • Visual feedback via toast notifications
  2. Chat Integration:

    • Toggle between chat and participant views
    • Unread message tracking
    • Contact selection for private chats

Responsive Design

  • Collapsible sections for mobile
  • Fixed panel width
  • Scrollable lists with hidden scrollbars
  • Conditional rendering of controls based on permissions

Usage Example

svelte
<script>
  import Participants from "./participants.svelte";
  
  let participants = [];
  let event = {};
  let me = {};
  let pexip = new PexipClient();
  
  function handleClose() {
    // Close panel logic
  }
</script>

<Participants
  data={participants}
  {event}
  {me}
  {pexip}
  on:close={handleClose}
/>

Dependencies

  • @steeze-ui/svelte-icon for icons
  • @steeze-ui/remix-icons (Pushpin2, Voiceprint, Camera, etc.)
  • @steeze-ui/iconic-free (VideoCamera, MicrophoneMute)
  • @steeze-ui/heroicons (DotsVertical, Search, Hand)
  • Svelte transitions (fly, fade, slide, scale)
  • Custom actions (clickOutside, tip for tooltips)
  • Lodash debounce
  • Svelte French Toast for notifications
  • Custom form components (SelectInput, Form)
  • Pexip client integration

Styling Notes

  • White background with gray borders
  • Blue accent colors for active elements
  • Compact participant items with hover states
  • Hidden scrollbars for cleaner appearance
  • Responsive spacing and padding
  • Consistent icon sizing

Accessibility Features

  • Clear visual hierarchy
  • Interactive elements have hover/focus states
  • Tooltips for icon buttons
  • Screen reader text for main action button
  • Semantic HTML structure

Released under the MIT License.