mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2025-12-23 22:18:36 -05:00
416 eslint a11y (#420)
* Add eslint-plugin-react-native-a11y dependency * Do not fix warnings on eslint run * Change all a11y error rules to warnings for now * Add a11y hint to Tabs * Add a11y prop to UserIcon * Update strings.ftl * Update strings * Update README.md * Update a11y props for InlineUser * Update a11y label * Add explanation for strings
This commit is contained in:
73
.eslintrc.js
73
.eslintrc.js
@@ -10,7 +10,8 @@ module.exports = {
|
||||
extends: [
|
||||
"airbnb",
|
||||
"plugin:i18next/recommended",
|
||||
"plugin:@tanstack/eslint-plugin-query/recommended"
|
||||
"plugin:@tanstack/eslint-plugin-query/recommended",
|
||||
"plugin:react-native-a11y/ios"
|
||||
],
|
||||
plugins: [
|
||||
"module-resolver",
|
||||
@@ -28,12 +29,15 @@ module.exports = {
|
||||
"consistent-return": [2, { treatUndefinedAsUnspecified: true }],
|
||||
"func-names": 0,
|
||||
"global-require": 0,
|
||||
"i18next/no-literal-string": [2, {
|
||||
words: {
|
||||
// Minor change to the default to disallow all-caps string literals as well
|
||||
exclude: ["[0-9!-/:-@[-`{-~]+"]
|
||||
"i18next/no-literal-string": [
|
||||
2,
|
||||
{
|
||||
words: {
|
||||
// Minor change to the default to disallow all-caps string literals as well
|
||||
exclude: ["[0-9!-/:-@[-`{-~]+"]
|
||||
}
|
||||
}
|
||||
}],
|
||||
],
|
||||
// The AirBNB approach at
|
||||
// https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/rules/imports.js#L71
|
||||
// is quite particular and forbids imports of devDependencies anywhere
|
||||
@@ -45,22 +49,30 @@ module.exports = {
|
||||
// raise alarms when you try to import things not declared in
|
||||
// package.json.
|
||||
"import/no-extraneous-dependencies": ["error", {}],
|
||||
"max-len": ["error", 100, 2, {
|
||||
ignoreUrls: true,
|
||||
ignoreComments: false,
|
||||
ignoreRegExpLiterals: true,
|
||||
ignoreStrings: false,
|
||||
ignoreTemplateLiterals: false
|
||||
}],
|
||||
"max-len": [
|
||||
"error",
|
||||
100,
|
||||
2,
|
||||
{
|
||||
ignoreUrls: true,
|
||||
ignoreComments: false,
|
||||
ignoreRegExpLiterals: true,
|
||||
ignoreStrings: false,
|
||||
ignoreTemplateLiterals: false
|
||||
}
|
||||
],
|
||||
"no-alert": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-unused-vars": ["error", {
|
||||
vars: "all",
|
||||
args: "after-used",
|
||||
// Overriding airbnb to allow leading underscore to indicate unused var
|
||||
argsIgnorePattern: "^_",
|
||||
ignoreRestSiblings: true
|
||||
}],
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
vars: "all",
|
||||
args: "after-used",
|
||||
// Overriding airbnb to allow leading underscore to indicate unused var
|
||||
argsIgnorePattern: "^_",
|
||||
ignoreRestSiblings: true
|
||||
}
|
||||
],
|
||||
"no-void": 0,
|
||||
"prefer-destructuring": [2, { object: true, array: false }],
|
||||
quotes: [2, "double"],
|
||||
@@ -76,7 +88,10 @@ module.exports = {
|
||||
"react/prop-types": 0,
|
||||
"react/destructuring-assignment": 0,
|
||||
"react/jsx-filename-extension": 0,
|
||||
"react/function-component-definition": [2, { namedComponents: "arrow-function" }],
|
||||
"react/function-component-definition": [
|
||||
2,
|
||||
{ namedComponents: "arrow-function" }
|
||||
],
|
||||
"react/require-default-props": 0,
|
||||
|
||||
// React-Hooks Plugin
|
||||
@@ -87,7 +102,21 @@ module.exports = {
|
||||
"react-native/no-inline-styles": "error",
|
||||
|
||||
"simple-import-sort/imports": "error",
|
||||
"simple-import-sort/exports": "error"
|
||||
"simple-import-sort/exports": "error",
|
||||
"react-native-a11y/has-accessibility-hint": 1,
|
||||
"react-native-a11y/has-accessibility-props": 1,
|
||||
"react-native-a11y/has-valid-accessibility-actions": 1,
|
||||
"react-native-a11y/has-valid-accessibility-role": 1,
|
||||
"react-native-a11y/has-valid-accessibility-state": 1,
|
||||
"react-native-a11y/has-valid-accessibility-states": 1,
|
||||
"react-native-a11y/has-valid-accessibility-component-type": 1,
|
||||
"react-native-a11y/has-valid-accessibility-traits": 1,
|
||||
"react-native-a11y/has-valid-accessibility-value": 1,
|
||||
"react-native-a11y/no-nested-touchables": 1,
|
||||
"react-native-a11y/has-valid-accessibility-descriptors": 1,
|
||||
"react-native-a11y/has-valid-accessibility-ignores-invert-colors": 1,
|
||||
"react-native-a11y/has-valid-accessibility-live-region": 1,
|
||||
"react-native-a11y/has-valid-important-for-accessibility": 1
|
||||
},
|
||||
// need this so jest doesn't show as undefined in jest.setup.js
|
||||
env: {
|
||||
|
||||
@@ -127,7 +127,7 @@ We're using Nativewind, a styling system for React Native based on Tailwind CSS.
|
||||
|
||||
1. Download custom icon from Figma as an SVG file.
|
||||
2. Add new icon to the iNaturalist icon set in Fontastic. Select all relevant iNaturalist icons, tap the Publish tab, and download the zip of icons.
|
||||
3. Create a glpyh file from the CSS file you just downloaded, using the following command (be sure to replace /path/to/styles with your path):
|
||||
3. Create a glyph file from the CSS file you just downloaded, using the following command (be sure to replace /path/to/styles with your path):
|
||||
|
||||
```
|
||||
./node_modules/.bin/generate-icon '/path/to/styles.css' --componentName=INatIcon --fontFamily=inaturalisticons > 'src/components/INatIcon.js'
|
||||
|
||||
29
package-lock.json
generated
29
package-lock.json
generated
@@ -110,6 +110,7 @@
|
||||
"eslint-plugin-react": "^7.29.4",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-native": "^4.0.0",
|
||||
"eslint-plugin-react-native-a11y": "^3.3.0",
|
||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||
"eslint-plugin-testing-library": "^5.10.0",
|
||||
"factoria": "^3.2.2",
|
||||
@@ -9235,6 +9236,23 @@
|
||||
"eslint": "^3.17.0 || ^4 || ^5 || ^6 || ^7 || ^8"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react-native-a11y": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-native-a11y/-/eslint-plugin-react-native-a11y-3.3.0.tgz",
|
||||
"integrity": "sha512-21bIs/0yROcMq7KtAG+OVNDWAh8M+6scII0iXcO3i9NYHe2xZ443yPs5KSUMSvQJeRLLjuKB7V5saqNjoMWDHA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.15.4",
|
||||
"ast-types-flow": "^0.0.7",
|
||||
"jsx-ast-utils": "^3.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react-native-globals": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz",
|
||||
@@ -29175,6 +29193,17 @@
|
||||
"eslint-plugin-react-native-globals": "^0.1.1"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-react-native-a11y": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-native-a11y/-/eslint-plugin-react-native-a11y-3.3.0.tgz",
|
||||
"integrity": "sha512-21bIs/0yROcMq7KtAG+OVNDWAh8M+6scII0iXcO3i9NYHe2xZ443yPs5KSUMSvQJeRLLjuKB7V5saqNjoMWDHA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.15.4",
|
||||
"ast-types-flow": "^0.0.7",
|
||||
"jsx-ast-utils": "^3.2.1"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-react-native-globals": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"clean-start": "npx react-native clean-project-auto && npx pod-install && npm start",
|
||||
"test": "jest",
|
||||
"lint": "npm run lint:eslint && npm run lint:flow",
|
||||
"lint:eslint": "eslint . --fix",
|
||||
"lint:eslint": "eslint . --fix --quiet",
|
||||
"lint:flow": "flow check",
|
||||
"postinstall": "husky install",
|
||||
"translate": "node src/i18n/i18ncli.js build",
|
||||
@@ -121,6 +121,7 @@
|
||||
"eslint-plugin-react": "^7.29.4",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-native": "^4.0.0",
|
||||
"eslint-plugin-react-native-a11y": "^3.3.0",
|
||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||
"eslint-plugin-testing-library": "^5.10.0",
|
||||
"factoria": "^3.2.2",
|
||||
|
||||
@@ -53,15 +53,13 @@ const InlineUser = ( { user }: Props ): Node => {
|
||||
testID="InlineUser"
|
||||
className="flex flex-row items-center"
|
||||
accessibilityRole="link"
|
||||
accessibilityLabel={t( "Navigate-to-user-profile" )}
|
||||
accessibilityValue={{ text: userHandle }}
|
||||
accessibilityLabel={t( "User", { userHandle } )}
|
||||
accessibilityHint={t( "Navigates-to-user-profile" )}
|
||||
onPress={() => {
|
||||
navigation.navigate( "UserProfile", { userId: user.id } );
|
||||
}}
|
||||
>
|
||||
<View className="mr-[7px]">
|
||||
{renderUserIcon()}
|
||||
</View>
|
||||
<View className="mr-[7px]">{renderUserIcon()}</View>
|
||||
<Text>{userHandle}</Text>
|
||||
</Pressable>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import { Text, View } from "components/styledComponents";
|
||||
import { t } from "i18next";
|
||||
import type { Node } from "react";
|
||||
import React from "react";
|
||||
import { TouchableOpacity } from "react-native";
|
||||
@@ -39,8 +40,9 @@ const Tabs = ( { tabs = DEFAULT_TABS, activeId }: Props ): Node => (
|
||||
}
|
||||
}}
|
||||
testID={testID || `${id}-tab`}
|
||||
accessibilityLabel={text}
|
||||
accessibilityRole="tab"
|
||||
accessibilityLabel={text}
|
||||
accessibilityHint={t( "Switch-to-tab", { tab: text } )}
|
||||
accessibilityState={{
|
||||
selected: active,
|
||||
expanded: active
|
||||
|
||||
@@ -17,6 +17,7 @@ const UserIcon = ( { uri, small }: Props ): React.Node => {
|
||||
testID="UserIcon.photo"
|
||||
className={className}
|
||||
source={uri}
|
||||
accessibilityIgnoresInvertColors
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -687,7 +687,15 @@ No = No
|
||||
Discard-Comment = Discard Comment
|
||||
Are-you-sure-discard-comment = Are you sure you want to discard this comment?
|
||||
|
||||
## Accessibility labels: these are used by screen readers to describe actionable elements
|
||||
## Accessibility labels: these are used by screen readers to label actionable elements iOS: https://developer.apple.com/documentation/uikit/uiaccessibilityelement/1619577-accessibilitylabel
|
||||
## iOS Guidelines "A string that succinctly identifies the accessibility element." Starts with capital letter, no ending punctuation.
|
||||
User = User { $userHandle }
|
||||
|
||||
## Accessibility hints: these are used by screen readers to describe what happens when the user interacts with an element iOS: https://developer.apple.com/documentation/uikit/uiaccessibilityelement/1619585-accessibilityhint
|
||||
## iOS Guidelines "A string that briefly describes the result of performing an action on the accessibility element." Third person singular ending with a period.
|
||||
Navigates-to-user-profile = Navigates to user profile.
|
||||
|
||||
## The following are actually more like "accessibility hints" than labels we should probably refactor
|
||||
Add-this-ID = Add this identification
|
||||
# Accessible label for the camera button
|
||||
Camera-button-label-switch-camera = Use the device's other camera.
|
||||
@@ -712,12 +720,12 @@ Navigate-to-login-screen = Navigate to login screen
|
||||
Navigate-to-observation-details = Navigate to observation details screen
|
||||
Navigate-to-project-details = Navigate to project details
|
||||
Navigate-to-taxon-details = Navigate to taxon details
|
||||
Navigate-to-user-profile = Navigate to user profile
|
||||
Number-of-comments = Number of comments
|
||||
Number-of-identifications = Number of identifications
|
||||
Observation-has-no-photos-and-no-sounds = This observation has no photos and no sounds.
|
||||
Take-photo = Take photo
|
||||
Photo-taken-at = Photo taken at { $date }
|
||||
Switch-to-tab = Switch to { $tab } tab
|
||||
Take-photo = Take photo
|
||||
# Accessibility labels for no internet state in ObsDetails
|
||||
Location-map-unavailable-without-internet = Location map unavailable without internet
|
||||
Observation-photos-unavailable-without-internet = Observation photos unavailable without internet
|
||||
|
||||
@@ -390,7 +390,7 @@
|
||||
"comment": "Shows the number of observations a user is currently uploading on my observations page",
|
||||
"val": "Uploading { $count ->\n [one] 1 Observation\n *[other] { $count } Observations\n}"
|
||||
},
|
||||
"User": "User",
|
||||
"User": "User { $userHandle }",
|
||||
"Username": "Username",
|
||||
"Username-or-Email": {
|
||||
"comment": "Appears above the text fields",
|
||||
@@ -490,6 +490,7 @@
|
||||
},
|
||||
"Discard-Comment": "Discard Comment",
|
||||
"Are-you-sure-discard-comment": "Are you sure you want to discard this comment?",
|
||||
"Navigates-to-user-profile": "Navigates to user profile.",
|
||||
"Add-this-ID": "Add this identification",
|
||||
"Camera-button-label-switch-camera": {
|
||||
"comment": "Accessible label for the camera button",
|
||||
@@ -524,12 +525,12 @@
|
||||
"Navigate-to-observation-details": "Navigate to observation details screen",
|
||||
"Navigate-to-project-details": "Navigate to project details",
|
||||
"Navigate-to-taxon-details": "Navigate to taxon details",
|
||||
"Navigate-to-user-profile": "Navigate to user profile",
|
||||
"Number-of-comments": "Number of comments",
|
||||
"Number-of-identifications": "Number of identifications",
|
||||
"Observation-has-no-photos-and-no-sounds": "This observation has no photos and no sounds.",
|
||||
"Take-photo": "Take photo",
|
||||
"Photo-taken-at": "Photo taken at { $date }",
|
||||
"Switch-to-tab": "Switch to { $tab } tab",
|
||||
"Take-photo": "Take photo",
|
||||
"Location-map-unavailable-without-internet": {
|
||||
"comment": "Accessibility labels for no internet state in ObsDetails",
|
||||
"val": "Location map unavailable without internet"
|
||||
|
||||
@@ -687,7 +687,15 @@ No = No
|
||||
Discard-Comment = Discard Comment
|
||||
Are-you-sure-discard-comment = Are you sure you want to discard this comment?
|
||||
|
||||
## Accessibility labels: these are used by screen readers to describe actionable elements
|
||||
## Accessibility labels: these are used by screen readers to label actionable elements iOS: https://developer.apple.com/documentation/uikit/uiaccessibilityelement/1619577-accessibilitylabel
|
||||
## iOS Guidelines "A string that succinctly identifies the accessibility element." Starts with capital letter, no ending punctuation.
|
||||
User = User { $userHandle }
|
||||
|
||||
## Accessibility hints: these are used by screen readers to describe what happens when the user interacts with an element iOS: https://developer.apple.com/documentation/uikit/uiaccessibilityelement/1619585-accessibilityhint
|
||||
## iOS Guidelines "A string that briefly describes the result of performing an action on the accessibility element." Third person singular ending with a period.
|
||||
Navigates-to-user-profile = Navigates to user profile.
|
||||
|
||||
## The following are actually more like "accessibility hints" than labels we should probably refactor
|
||||
Add-this-ID = Add this identification
|
||||
# Accessible label for the camera button
|
||||
Camera-button-label-switch-camera = Use the device's other camera.
|
||||
@@ -712,12 +720,12 @@ Navigate-to-login-screen = Navigate to login screen
|
||||
Navigate-to-observation-details = Navigate to observation details screen
|
||||
Navigate-to-project-details = Navigate to project details
|
||||
Navigate-to-taxon-details = Navigate to taxon details
|
||||
Navigate-to-user-profile = Navigate to user profile
|
||||
Number-of-comments = Number of comments
|
||||
Number-of-identifications = Number of identifications
|
||||
Observation-has-no-photos-and-no-sounds = This observation has no photos and no sounds.
|
||||
Take-photo = Take photo
|
||||
Photo-taken-at = Photo taken at { $date }
|
||||
Switch-to-tab = Switch to { $tab } tab
|
||||
Take-photo = Take photo
|
||||
# Accessibility labels for no internet state in ObsDetails
|
||||
Location-map-unavailable-without-internet = Location map unavailable without internet
|
||||
Observation-photos-unavailable-without-internet = Observation photos unavailable without internet
|
||||
|
||||
Reference in New Issue
Block a user