Appearance
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
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)
Essential Call Functions:
- Settings access
- Recording controls
- Screen capture
- Hand raising
- Remote control (host-only)
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 permissionUI 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
Settings Button:
- Cog icon
- White circular background
- "Settings" tooltip
Recording Button (conditional):
- Toggles between RecordCircle/Stop icons
- Red color when active
- Dynamic tooltip ("Start/Stop Recording")
Screen Capture Button (conditional):
- Camera icon
- "Capture Screen" tooltip
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)
Remote Control Button (host-only):
- ShieldUser icon
- "Remote Control" tooltip
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-iconfor icons@steeze-ui/heroicons(DotsHorizontal, Cog, Hand)@steeze-ui/remix-icons(RecordCircle, Camera, ShieldUser, Stop)- Custom tooltip action
- Svelte transitions