From beeb432e79bae071f2f0e36a9c99ddcfeb428e88 Mon Sep 17 00:00:00 2001 From: Shawn Jackson Date: Mon, 19 Jan 2026 18:06:10 -0800 Subject: [PATCH 1/3] RD-T39 Bug fixes --- src/app/call/[id]/edit.web.tsx | 55 ++++++++-------- src/app/call/new/index.web.tsx | 111 +++++++++++++++++---------------- 2 files changed, 88 insertions(+), 78 deletions(-) diff --git a/src/app/call/[id]/edit.web.tsx b/src/app/call/[id]/edit.web.tsx index b7f636c..c21f230 100644 --- a/src/app/call/[id]/edit.web.tsx +++ b/src/app/call/[id]/edit.web.tsx @@ -83,10 +83,10 @@ const WebInput: React.FC = ({ label, placeholder, value, onChange const isDark = colorScheme === 'dark'; const inputStyles = StyleSheet.flatten([ - styles.webInput, + webStyles.webInput as any, isDark ? styles.webInputDark : styles.webInputLight, error ? styles.webInputError : {}, - disabled ? styles.webInputDisabled : {}, + disabled ? webStyles.webInputDisabled as any : {}, multiline ? { minHeight: rows * 24 + 16 } : {}, ]); @@ -152,7 +152,7 @@ const WebSelect: React.FC = ({ label, placeholder, value, onChan {required ? * : null} onChange(e.target.value)} > @@ -279,33 +279,7 @@ export default function NewCallWeb() { }); }, [trackEvent, callPriorities.length, callTypes.length]); - // Keyboard shortcuts - useEffect(() => { - const handleKeyDown = (e: KeyboardEvent) => { - // Ctrl/Cmd + Enter to submit - if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { - e.preventDefault(); - handleSubmit(onSubmit)(); - } - // Escape to cancel - if (e.key === 'Escape') { - if (showLocationPicker) { - setShowLocationPicker(false); - } else if (showAddressSelection) { - setShowAddressSelection(false); - } else if (showDispatchModal) { - setShowDispatchModal(false); - } else { - router.back(); - } - } - }; - - window.addEventListener('keydown', handleKeyDown); - return () => window.removeEventListener('keydown', handleKeyDown); - }, [showLocationPicker, showAddressSelection, showDispatchModal, handleSubmit, onSubmit, router]); - - const onSubmit = async (data: FormValues) => { + const onSubmit = useCallback(async (data: FormValues) => { try { setIsSubmitting(true); @@ -353,7 +327,34 @@ export default function NewCallWeb() { } finally { setIsSubmitting(false); } - }; + }, [selectedLocation, callPriorities, callTypes, toast, t, router]); + + // Keyboard shortcuts + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + // Ctrl/Cmd + Enter to submit + if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { + e.preventDefault(); + handleSubmit(onSubmit)(); + } + // Escape to cancel + if (e.key === 'Escape') { + if (showLocationPicker) { + setShowLocationPicker(false); + } else if (showAddressSelection) { + setShowAddressSelection(false); + } else if (showDispatchModal) { + setShowDispatchModal(false); + } else { + router.back(); + } + } + }; + + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [showLocationPicker, showAddressSelection, showDispatchModal, handleSubmit, onSubmit]); const handleLocationSelected = useCallback( (location: { latitude: number; longitude: number; address?: string }) => { @@ -1019,15 +1020,6 @@ const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', }, - webInput: { - width: '100%', - padding: 10, - paddingRight: 40, - fontSize: 14, - borderRadius: 8, - borderWidth: 1, - outline: 'none', - } as const, webInputDark: { backgroundColor: '#262626', borderColor: '#404040', @@ -1041,23 +1033,10 @@ const styles = StyleSheet.create({ webInputError: { borderColor: '#ef4444', }, - webInputDisabled: { - opacity: 0.6, - cursor: 'not-allowed', - }, rightElement: { position: 'absolute', right: 8, }, - webSelect: { - width: '100%', - padding: 10, - fontSize: 14, - borderRadius: 8, - borderWidth: 1, - outline: 'none', - cursor: 'pointer', - }, webSelectDark: { backgroundColor: '#262626', borderColor: '#404040', @@ -1311,3 +1290,29 @@ const styles = StyleSheet.create({ color: '#374151', }, }); + +// Web-specific styles that use CSS-only properties +const webStyles: { [key: string]: React.CSSProperties } = { + webInput: { + width: '100%', + padding: 10, + paddingRight: 40, + fontSize: 14, + borderRadius: 8, + borderWidth: 1, + outline: 'none', + }, + webInputDisabled: { + opacity: 0.6, + cursor: 'not-allowed', + }, + webSelect: { + width: '100%', + padding: 10, + fontSize: 14, + borderRadius: 8, + borderWidth: 1, + outline: 'none', + cursor: 'pointer', + }, +}; From 029e51eb1286ae269efde87857fa5b76aad7fa08 Mon Sep 17 00:00:00 2001 From: Shawn Jackson Date: Mon, 19 Jan 2026 18:26:46 -0800 Subject: [PATCH 2/3] RD-T39 PR#75 fixes --- global.css | 7 ++ src/app/call/[id]/edit.web.tsx | 2 +- src/app/call/new/index.web.tsx | 123 ++++++++++++++++++--------------- 3 files changed, 77 insertions(+), 55 deletions(-) diff --git a/global.css b/global.css index b5c61c9..8e5cbbc 100644 --- a/global.css +++ b/global.css @@ -1,3 +1,10 @@ @tailwind base; @tailwind components; @tailwind utilities; + +/* Accessible focus styles for keyboard navigation */ +.web-input-accessible:focus-visible { + outline: 2px solid #3b82f6; + outline-offset: 2px; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} diff --git a/src/app/call/[id]/edit.web.tsx b/src/app/call/[id]/edit.web.tsx index c21f230..4d30874 100644 --- a/src/app/call/[id]/edit.web.tsx +++ b/src/app/call/[id]/edit.web.tsx @@ -86,7 +86,7 @@ const WebInput: React.FC = ({ label, placeholder, value, onChange webStyles.webInput as any, isDark ? styles.webInputDark : styles.webInputLight, error ? styles.webInputError : {}, - disabled ? webStyles.webInputDisabled as any : {}, + disabled ? (webStyles.webInputDisabled as any) : {}, multiline ? { minHeight: rows * 24 + 16 } : {}, ]); diff --git a/src/app/call/new/index.web.tsx b/src/app/call/new/index.web.tsx index 41597c4..00e9e92 100644 --- a/src/app/call/new/index.web.tsx +++ b/src/app/call/new/index.web.tsx @@ -112,10 +112,18 @@ const WebInput: React.FC = ({ label, placeholder, value, onChange webStyles.webInput as any, isDark ? styles.webInputDark : styles.webInputLight, error ? styles.webInputError : {}, - disabled ? webStyles.webInputDisabled as any : {}, + disabled ? (webStyles.webInputDisabled as any) : {}, multiline ? { minHeight: rows * 24 + 16 } : {}, ]); + // Add accessible focus styles for keyboard navigation + const accessibleInputStyles = { + ...inputStyles, + outline: 'none', + } as React.CSSProperties & { + '&:focus-visible'?: React.CSSProperties; + }; + return ( @@ -125,7 +133,8 @@ const WebInput: React.FC = ({ label, placeholder, value, onChange {multiline ? (