Skip to content

Mobile Speed Dial Component Documentation

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

Overview

This component provides a compact, mobile-friendly speed dial interface for video conferencing controls. It appears as a floating action button that expands to reveal additional call functions when interacted with.

Key Features

  1. Space-efficient Design:

    • Collapses to a single floating button
    • Expands vertically to show all available controls
    • Only visible on mobile devices (hidden on larger screens)
  2. Essential Call Functions:

    • Settings access
    • Recording controls
    • Screen capture
    • Hand raising
    • Remote control (host-only)
  3. Visual Indicators:

    • Badge counter for raised hands
    • Color-coded active states
    • Consistent iconography

Component Structure

Props

typescript
// Event handlers
export let endCall: () => void;                // Call termination function
export let toggleAudio: () => void;            // Audio toggle function
export let toggleVideo: () => void;            // Video toggle function
export let openSettings: () => void;           // Settings opener
export let toggleRecord: () => void;           // Recording toggle
export let captureScreen: () => void;          // Screen capture
export let toggleScreenShare: () => void;      // Screen share toggle
export let toggleRaiseHand: () => void;        // Hand raise toggle
export let openParticipantsView: () => void;   // Participants panel
export let openControlsView: () => void;       // Remote controls panel

// State properties
export let audioOn: boolean;                   // Microphone state
export let videoOn: boolean;                   // Camera state
export let noAudio: boolean;                   // Audio disabled flag
export let isHost: boolean;                    // Host status
export let isRecording: boolean;               // Recording state
export let isPresenting: boolean;              // Screen sharing state
export let handsRaised: number;                // Raised hands count
export let me: any;                            // Current user data
export let buzzTime: boolean;                  // Hand raised state
export let grayRaisedHand: boolean;            // Visual hand state
export let canRecord: boolean;                 // Recording permission
export let canTakePhoto: boolean;              // Screenshot permission
export let enableScreenShare: boolean;         // Screen share permission

UI Components

svelte
<div class="block sm:hidden fixed right-6 bottom-6 group">
  <!-- Expanded controls (shown on hover) -->
  <div transition:fade class="hidden group-hover:flex flex-col items-center mb-4 space-y-2">
    
    <!-- Settings Button -->
    <button
      type="button"
      class="flex justify-center w-8 h-8 p-1 items-center bg-white text-gray-700 rounded-full"
      on:click={openSettings}
      use:tip={{ content: "Settings", placement: "left" }}
    >
      <Icon src={Cog} size="20" />
    </button>

    <!-- Recording Button (conditional) -->
    {#if canRecord}
      <button
        type="button"
        class="flex justify-center w-8 h-8 p-1 items-center bg-white text-gray-700 rounded-full"
        on:click={toggleRecord}
        class:text-red-600={isRecording}
        class:bg-slate-400={isRecording}
        use:tip={{
          content: isRecording ? "Stop Recording" : "Start Recording",
          placement: "left",
        }}
      >
        <Icon
          src={isRecording ? Stop : RecordCircle}
          size="20"
          theme={isRecording ? "solid" : ""}
        />
      </button>
    {/if}

    <!-- Screen Capture Button (conditional) -->
    {#if canTakePhoto}
      <button
        type="button"
        class="flex justify-center w-8 h-8 p-1 items-center bg-white text-gray-700 rounded-full"
        on:click={captureScreen}
        use:tip={{ content: "Capture Screen", placement: "left" }}
      >
        <Icon src={Camera} size="20" />
      </button>
    {/if}

    <!-- Raise Hand Button with Badge -->
    <div class="indicator">
      <span
        class="indicator-item badge badge-secondary"
        class:hidden={handsRaised == 0 || (handsRaised === 1 && buzzTime)}
      >
        {handsRaised}
      </span>
      <button
        on:click={toggleRaiseHand}
        use:tip={{
          content: buzzTime ? "Lower Hand" : "Raise Hand",
          placement: "left",
        }}
        class="rounded-full bg-white text-gray-700 w-8 h-8 p-1.5 cursor-pointer"
        class:bg-slate-400={grayRaisedHand}
      >
        <Icon src={Hand} size="20" />
      </button>
    </div>

    <!-- Remote Control Button (host-only) -->
    {#if isHost}
      <button
        type="button"
        class="flex justify-center w-8 h-8 p-1 items-center bg-white text-gray-700 rounded-full"
        on:click={openControlsView}
        use:tip={{ content: "Remote Control", placement: "left" }}
      >
        <Icon src={ShieldUser} size="20" />
      </button>
    {/if}
  </div>

  <!-- Main Speed Dial Button -->
  <button
    type="button"
    class="flex items-center justify-center w-8 h-8 text-white bg-blue-700 rounded-full hover:bg-blue-800 dark:bg-blue-600 dark:hover:bg-blue-700 focus:ring-4 focus:ring-blue-300 focus:outline-none dark:focus:ring-blue-800"
  >
    <Icon
      src={DotsHorizontal}
      size="23"
      class="w-5 h-5 transition-transform group-hover:rotate-90"
    />
    <span class="sr-only">Open actions menu</span>
  </button>
</div>

Button Components

  1. Settings Button:

    • Cog icon
    • White circular background
    • "Settings" tooltip
  2. Recording Button (conditional):

    • Toggles between RecordCircle/Stop icons
    • Red color when active
    • Dynamic tooltip ("Start/Stop Recording")
  3. Screen Capture Button (conditional):

    • Camera icon
    • "Capture Screen" tooltip
  4. Raise Hand Button:

    • Hand icon with badge counter
    • Gray background when active
    • Dynamic tooltip ("Raise/Lower Hand")
    • Shows count of raised hands (excluding current user)
  5. Remote Control Button (host-only):

    • ShieldUser icon
    • "Remote Control" tooltip
  6. Main Speed Dial Button:

    • Blue circular button with dots icon
    • Rotates on hover
    • Fixed position at bottom-right

Technical Implementation

Responsive Design

  • Only visible on mobile (block sm:hidden)
  • Fixed positioning at bottom-right corner
  • Vertical flex layout for expanded controls

Interactions

  • Hover-triggered expansion
  • Smooth fade transition for controls
  • Rotating animation on main button

Accessibility

  • Screen reader text for main button
  • Tooltips for all interactive elements
  • Clear visual states for active controls

Styling

  • Consistent circular button design
  • White background for secondary buttons
  • Color indicators for active states
  • Badge for raised hand count
  • Dark mode support

Dependencies

  • @steeze-ui/svelte-icon for icons
  • @steeze-ui/heroicons (DotsHorizontal, Cog, Hand)
  • @steeze-ui/remix-icons (RecordCircle, Camera, ShieldUser, Stop)
  • Custom tooltip action
  • Svelte transitions

Released under the MIT License.