From 83959c595d52ceb7aa4e3f68441c5ac41c389ebc Mon Sep 17 00:00:00 2001
From: Ollie H <renahlee@outlook.com>
Date: Mon, 1 May 2023 18:38:47 -0700
Subject: React Native accessibility (#539)

* React Native accessibility

* First round of changes

* Latest update

* Checkpoint

* Wrap up

* Lint

* Remove unhelpful image hints

* Fix navigation

* Fix rebase and lint

* Mitigate an known issue with the password entry in login

* Fix composer dismiss

* Remove focus on input elements for web

* Remove i and npm

* pls work

* Remove stray declaration

* Regenerate yarn.lock

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>
---
 src/view/shell/Drawer.tsx | 67 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 55 insertions(+), 12 deletions(-)

(limited to 'src/view/shell/Drawer.tsx')

diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx
index 81ee005c8..404374b95 100644
--- a/src/view/shell/Drawer.tsx
+++ b/src/view/shell/Drawer.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import React, {ComponentProps} from 'react'
 import {
   Linking,
   SafeAreaView,
@@ -50,6 +50,8 @@ export const DrawerContent = observer(() => {
   const {isAtHome, isAtSearch, isAtNotifications, isAtMyProfile} =
     useNavigationTabState()
 
+  const {notifications} = store.me
+
   // events
   // =
 
@@ -120,7 +122,11 @@ export const DrawerContent = observer(() => {
       ]}>
       <SafeAreaView style={s.flex1}>
         <View style={styles.main}>
-          <TouchableOpacity testID="profileCardButton" onPress={onPressProfile}>
+          <TouchableOpacity
+            testID="profileCardButton"
+            accessibilityLabel="Profile"
+            accessibilityHint="Navigates to your profile"
+            onPress={onPressProfile}>
             <UserAvatar size={80} avatar={store.me.avatar} />
             <Text
               type="title-lg"
@@ -164,6 +170,8 @@ export const DrawerContent = observer(() => {
               )
             }
             label="Search"
+            accessibilityLabel="Search"
+            accessibilityHint="Search through users and posts"
             bold={isAtSearch}
             onPress={onPressSearch}
           />
@@ -184,6 +192,8 @@ export const DrawerContent = observer(() => {
               )
             }
             label="Home"
+            accessibilityLabel="Home"
+            accessibilityHint="Navigates to default feed"
             bold={isAtHome}
             onPress={onPressHome}
           />
@@ -204,7 +214,13 @@ export const DrawerContent = observer(() => {
               )
             }
             label="Notifications"
-            count={store.me.notifications.unreadCountLabel}
+            accessibilityLabel={
+              notifications.unreadCountLabel === '1'
+                ? 'Notifications: 1 unread notification'
+                : `Notifications: ${notifications.unreadCountLabel} unread notifications`
+            }
+            accessibilityHint="Opens notification feed"
+            count={notifications.unreadCountLabel}
             bold={isAtNotifications}
             onPress={onPressNotifications}
           />
@@ -225,6 +241,8 @@ export const DrawerContent = observer(() => {
               )
             }
             label="Profile"
+            accessibilityLabel="Profile"
+            accessibilityHint="See profile display name, avatar, description, and other profile items"
             onPress={onPressProfile}
           />
           <MenuItem
@@ -236,6 +254,8 @@ export const DrawerContent = observer(() => {
               />
             }
             label="Settings"
+            accessibilityLabel="Settings"
+            accessibilityHint="Manage settings for your account, like handle, content moderation, and app passwords"
             onPress={onPressSettings}
           />
         </View>
@@ -243,6 +263,13 @@ export const DrawerContent = observer(() => {
         <View style={styles.footer}>
           {!isWeb && (
             <TouchableOpacity
+              accessibilityRole="button"
+              accessibilityLabel="Toggle dark mode"
+              accessibilityHint={
+                theme.colorScheme === 'dark'
+                  ? 'Sets display to light mode'
+                  : 'Sets display to dark mode'
+              }
               onPress={onDarkmodePress}
               style={[
                 styles.footerBtn,
@@ -258,6 +285,9 @@ export const DrawerContent = observer(() => {
             </TouchableOpacity>
           )}
           <TouchableOpacity
+            accessibilityRole="link"
+            accessibilityLabel="Send feedback"
+            accessibilityHint="Opens Google Forms feedback link"
             onPress={onPressFeedback}
             style={[
               styles.footerBtn,
@@ -281,25 +311,30 @@ export const DrawerContent = observer(() => {
   )
 })
 
+interface MenuItemProps extends ComponentProps<typeof TouchableOpacity> {
+  icon: JSX.Element
+  label: string
+  count?: string
+  bold?: boolean
+}
+
 function MenuItem({
   icon,
   label,
+  accessibilityLabel,
   count,
   bold,
   onPress,
-}: {
-  icon: JSX.Element
-  label: string
-  count?: string
-  bold?: boolean
-  onPress: () => void
-}) {
+}: MenuItemProps) {
   const pal = usePalette('default')
   return (
     <TouchableOpacity
       testID={`menuItemButton-${label}`}
       style={styles.menuItem}
-      onPress={onPress}>
+      onPress={onPress}
+      accessibilityRole="menuitem"
+      accessibilityLabel={accessibilityLabel}
+      accessibilityHint="">
       <View style={[styles.menuItemIconWrapper]}>
         {icon}
         {count ? (
@@ -332,6 +367,7 @@ const InviteCodes = observer(() => {
   const {track} = useAnalytics()
   const store = useStores()
   const pal = usePalette('default')
+  const {invitesAvailable} = store.me
   const onPress = React.useCallback(() => {
     track('Menu:ItemClicked', {url: '#invite-codes'})
     store.shell.closeDrawer()
@@ -341,7 +377,14 @@ const InviteCodes = observer(() => {
     <TouchableOpacity
       testID="menuItemInviteCodes"
       style={[styles.inviteCodes]}
-      onPress={onPress}>
+      onPress={onPress}
+      accessibilityRole="button"
+      accessibilityLabel={
+        invitesAvailable === 1
+          ? 'Invite codes: 1 available'
+          : `Invite codes: ${invitesAvailable} available`
+      }
+      accessibilityHint="Opens list of invite codes">
       <FontAwesomeIcon
         icon="ticket"
         style={[
-- 
cgit 1.4.1

