diff --git a/src/frontend/src/features/rooms/livekit/components/controls/ChatToggle.tsx b/src/frontend/src/features/rooms/livekit/components/controls/ChatToggle.tsx
index 37f8f360..130151f7 100644
--- a/src/frontend/src/features/rooms/livekit/components/controls/ChatToggle.tsx
+++ b/src/frontend/src/features/rooms/livekit/components/controls/ChatToggle.tsx
@@ -6,6 +6,7 @@ import { ToggleButton } from '@/primitives'
import { chatStore } from '@/stores/chat'
import { useSidePanel } from '../../hooks/useSidePanel'
import { ToggleButtonProps } from '@/primitives/ToggleButton'
+import { useRegisterKeyboardShortcut } from '@/features/shortcuts/useRegisterKeyboardShortcut'
export const ChatToggle = ({
onPress,
@@ -18,6 +19,11 @@ export const ChatToggle = ({
const { isChatOpen, toggleChat } = useSidePanel()
const tooltipLabel = isChatOpen ? 'open' : 'closed'
+ useRegisterKeyboardShortcut({
+ id: 'toggle-chat',
+ handler: toggleChat,
+ })
+
return (
{
closeLowerHandToasts()
}, [isHandRaised])
+ const handleToggle = () => {
+ toggleRaisedHand()
+ resetToastState()
+ }
+
+ useRegisterKeyboardShortcut({
+ id: 'raise-hand',
+ handler: handleToggle,
+ })
+
useEffect(() => {
const shouldShowToast = isSpeaking && isHandRaised && !hasShownToast
@@ -68,10 +79,7 @@ export const HandToggle = () => {
aria-label={t(tooltipLabel)}
tooltip={t(tooltipLabel)}
isSelected={isHandRaised}
- onPress={() => {
- toggleRaisedHand()
- resetToastState()
- }}
+ onPress={handleToggle}
data-attr={`controls-hand-${tooltipLabel}`}
>
diff --git a/src/frontend/src/features/rooms/livekit/components/controls/ReactionsToggle.tsx b/src/frontend/src/features/rooms/livekit/components/controls/ReactionsToggle.tsx
index e400f6c4..57e47fc3 100644
--- a/src/frontend/src/features/rooms/livekit/components/controls/ReactionsToggle.tsx
+++ b/src/frontend/src/features/rooms/livekit/components/controls/ReactionsToggle.tsx
@@ -11,6 +11,7 @@ import {
ReactionPortals,
} from '@/features/rooms/livekit/components/ReactionPortal'
import { getEmojiLabel } from '@/features/rooms/livekit/utils/reactionUtils'
+import { useRegisterKeyboardShortcut } from '@/features/shortcuts/useRegisterKeyboardShortcut'
import { Toolbar as RACToolbar } from 'react-aria-components'
import { Participant } from 'livekit-client'
import useRateLimiter from '@/hooks/useRateLimiter'
@@ -41,6 +42,11 @@ export const ReactionsToggle = () => {
const [isVisible, setIsVisible] = useState(false)
+ useRegisterKeyboardShortcut({
+ id: 'reaction',
+ handler: () => setIsVisible((prev) => !prev),
+ })
+
const sendReaction = async (emoji: string) => {
const encoder = new TextEncoder()
const payload: NotificationPayload = {
diff --git a/src/frontend/src/features/shortcuts/catalog.ts b/src/frontend/src/features/shortcuts/catalog.ts
index ff85de56..9be21492 100644
--- a/src/frontend/src/features/shortcuts/catalog.ts
+++ b/src/frontend/src/features/shortcuts/catalog.ts
@@ -9,6 +9,12 @@ export type ShortcutId =
| 'toggle-microphone'
| 'toggle-camera'
| 'push-to-talk'
+ | 'toggle-chat'
+ | 'toggle-participants'
+ | 'raise-hand'
+ | 'recording'
+ | 'reaction'
+ | 'fullscreen'
export const getShortcutDescriptorById = (id: ShortcutId) =>
shortcutCatalog.find((item) => item.id === id)
@@ -44,4 +50,34 @@ export const shortcutCatalog: ShortcutDescriptor[] = [
kind: 'longPress',
code: 'KeyV',
},
+ {
+ id: 'reaction',
+ category: 'interaction',
+ shortcut: { key: 'E', ctrlKey: true, shiftKey: true },
+ },
+ {
+ id: 'fullscreen',
+ category: 'interaction',
+ shortcut: { key: 'F', ctrlKey: true, shiftKey: true },
+ },
+ {
+ id: 'recording',
+ category: 'interaction',
+ shortcut: { key: 'L', ctrlKey: true, shiftKey: true },
+ },
+ {
+ id: 'raise-hand',
+ category: 'interaction',
+ shortcut: { key: 'H', ctrlKey: true, shiftKey: true },
+ },
+ {
+ id: 'toggle-chat',
+ category: 'interaction',
+ shortcut: { key: 'M', ctrlKey: true, shiftKey: true },
+ },
+ {
+ id: 'toggle-participants',
+ category: 'interaction',
+ shortcut: { key: 'P', ctrlKey: true, shiftKey: true },
+ },
]