diff --git a/jam-ui/src/components/client/JKSessionChatButton.js b/jam-ui/src/components/client/JKSessionChatButton.js index 62f4f1507..adbcf01ec 100644 --- a/jam-ui/src/components/client/JKSessionChatButton.js +++ b/jam-ui/src/components/client/JKSessionChatButton.js @@ -42,6 +42,10 @@ const JKSessionChatButton = ({ sessionId }) => { src={chatIcon} alt="Chat" onClick={handleClick} + role="button" + tabIndex={0} + aria-label={`Open chat${unreadCount > 0 ? ` (${unreadCount} unread)` : ''}`} + aria-pressed={isWindowOpen} style={{ cursor: 'pointer', width: '24px', diff --git a/jam-ui/src/components/client/JKSessionChatWindow.js b/jam-ui/src/components/client/JKSessionChatWindow.js index 667ce3178..7520d78fc 100644 --- a/jam-ui/src/components/client/JKSessionChatWindow.js +++ b/jam-ui/src/components/client/JKSessionChatWindow.js @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useEffect, useRef } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import WindowPortal from '../common/WindowPortal.js'; import JKChatHeader from './chat/JKChatHeader.js'; @@ -32,6 +32,7 @@ import { useJamServerContext } from '../../context/JamServerContext'; */ const JKSessionChatWindow = () => { const dispatch = useDispatch(); + const textareaRef = useRef(null); // Redux selectors const isWindowOpen = useSelector(selectIsChatWindowOpen); @@ -54,6 +55,29 @@ const JKSessionChatWindow = () => { return 'Session Chat'; }, [activeChannel]); + // Keyboard shortcut: Escape to close window + useEffect(() => { + const handleKeyDown = (e) => { + if (e.key === 'Escape') { + dispatch(closeChatWindow()); + } + }; + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [dispatch]); + + // Focus management: Auto-focus textarea when window opens + useEffect(() => { + if (isWindowOpen && textareaRef.current) { + // Delay focus to ensure DOM is ready + setTimeout(() => { + if (textareaRef.current) { + textareaRef.current.focus(); + } + }, 100); + } + }, [isWindowOpen]); + // Conditional render: only show if window is open if (!isWindowOpen) return null; @@ -64,7 +88,12 @@ const JKSessionChatWindow = () => { onClose={handleClose} windowId="jamkazam-chat" > -