Skip to content

Commit

Permalink
React Native accessibility (bluesky-social#539)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
renahlee and pfrazee authored May 2, 2023
1 parent c75c888 commit 83959c5
Show file tree
Hide file tree
Showing 86 changed files with 2,479 additions and 1,827 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module.exports = {
root: true,
extends: '@react-native-community',
extends: ['@react-native-community', 'plugin:react-native-a11y/ios'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'detox'],
ignorePatterns: [
Expand Down
3 changes: 2 additions & 1 deletion bskyweb/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@
}
}*/

/* OLLIE: TODO -- this is not accessible */
/* Remove focus state on inputs */
*:focus {
input:focus {
outline: 0;
}
/* Remove default link styling */
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"await-lock": "^2.2.2",
"base64-js": "^1.5.1",
"email-validator": "^2.0.4",
"eslint-plugin-react-native-a11y": "^3.3.0",
"expo": "~48.0.15",
"expo-application": "~5.1.1",
"expo-build-properties": "~0.5.1",
Expand Down
2 changes: 1 addition & 1 deletion src/lib/strings/display-names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const CHECK_MARKS_RE = /[\u2705\u2713\u2714\u2611]/gu

export function sanitizeDisplayName(str: string): string {
if (typeof str === 'string') {
return str.replace(CHECK_MARKS_RE, '')
return str.replace(CHECK_MARKS_RE, '').trim()
}
return ''
}
2 changes: 2 additions & 0 deletions src/lib/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export const s = StyleSheet.create({
mr2: {marginRight: 2},
mr5: {marginRight: 5},
mr10: {marginRight: 10},
mr20: {marginRight: 20},
ml2: {marginLeft: 2},
ml5: {marginLeft: 5},
ml10: {marginLeft: 10},
Expand Down Expand Up @@ -149,6 +150,7 @@ export const s = StyleSheet.create({
pb5: {paddingBottom: 5},
pb10: {paddingBottom: 10},
pb20: {paddingBottom: 20},
px5: {paddingHorizontal: 5},

// flex
flexRow: {flexDirection: 'row'},
Expand Down
10 changes: 8 additions & 2 deletions src/view/com/auth/SplashScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,21 @@ export const SplashScreen = ({
<TouchableOpacity
testID="createAccountButton"
style={[styles.btn, {backgroundColor: colors.blue3}]}
onPress={onPressCreateAccount}>
onPress={onPressCreateAccount}
accessibilityRole="button"
accessibilityLabel="Create new account"
accessibilityHint="Opens flow to create a new Bluesky account">
<Text style={[s.white, styles.btnLabel]}>
Create a new account
</Text>
</TouchableOpacity>
<TouchableOpacity
testID="signInButton"
style={[styles.btn, pal.btn]}
onPress={onPressSignin}>
onPress={onPressSignin}
accessibilityRole="button"
accessibilityLabel="Sign in"
accessibilityHint="Opens flow to sign into your existing Bluesky account">
<Text style={[pal.text, styles.btnLabel]}>Sign in</Text>
</TouchableOpacity>
</View>
Expand Down
13 changes: 10 additions & 3 deletions src/view/com/auth/SplashScreen.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,19 @@ export const SplashScreen = ({
<TouchableOpacity
testID="createAccountButton"
style={[styles.btn, {backgroundColor: colors.blue3}]}
onPress={onPressCreateAccount}>
onPress={onPressCreateAccount}
// TODO: web accessibility
accessibilityRole="button">
<Text style={[s.white, styles.btnLabel]}>
Create a new account
</Text>
</TouchableOpacity>
<TouchableOpacity
testID="signInButton"
style={[styles.btn, pal.btn]}
onPress={onPressSignin}>
onPress={onPressSignin}
// TODO: web accessibility
accessibilityRole="button">
<Text style={[pal.text, styles.btnLabel]}>Sign in</Text>
</TouchableOpacity>
</View>
Expand All @@ -60,7 +64,10 @@ export const SplashScreen = ({
style={[styles.notice, pal.textLight]}
lineHeight={1.3}>
Bluesky will launch soon.{' '}
<TouchableOpacity onPress={onPressWaitlist}>
<TouchableOpacity
onPress={onPressWaitlist}
// TODO: web accessibility
accessibilityRole="button">
<Text type="xl" style={pal.link}>
Join the waitlist
</Text>
Expand Down
20 changes: 17 additions & 3 deletions src/view/com/auth/create/CreateAccount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,24 @@ export const CreateAccount = observer(
{model.step === 3 && <Step3 model={model} />}
</View>
<View style={[s.flexRow, s.pl20, s.pr20]}>
<TouchableOpacity onPress={onPressBackInner} testID="backBtn">
<TouchableOpacity
onPress={onPressBackInner}
testID="backBtn"
accessibilityRole="button"
accessibilityLabel="Go back"
accessibilityHint="Navigates to the previous screen">
<Text type="xl" style={pal.link}>
Back
</Text>
</TouchableOpacity>
<View style={s.flex1} />
{model.canNext ? (
<TouchableOpacity testID="nextBtn" onPress={onPressNext}>
<TouchableOpacity
testID="nextBtn"
onPress={onPressNext}
accessibilityRole="button"
accessibilityLabel="Go to next"
accessibilityHint="Navigates to the next screen">
{model.isProcessing ? (
<ActivityIndicator />
) : (
Expand All @@ -91,7 +101,11 @@ export const CreateAccount = observer(
) : model.didServiceDescriptionFetchFail ? (
<TouchableOpacity
testID="retryConnectBtn"
onPress={onPressRetryConnect}>
onPress={onPressRetryConnect}
accessibilityRole="button"
accessibilityLabel="Retry"
accessibilityHint="Retries account creation"
accessibilityLiveRegion="polite">
<Text type="xl-bold" style={[pal.link, s.pr5]}>
Retry
</Text>
Expand Down
14 changes: 11 additions & 3 deletions src/view/com/auth/create/Step1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const Step1 = observer(({model}: {model: CreateAccountModel}) => {
<View>
<StepHeader step="1" title="Your hosting provider" />
<Text style={[pal.text, s.mb10]}>
This is the company that keeps you online.
This is the service that keeps you online.
</Text>
<Option
testID="blueskyServerBtn"
Expand All @@ -72,7 +72,7 @@ export const Step1 = observer(({model}: {model: CreateAccountModel}) => {
label="Other"
onPress={onPressOther}>
<View style={styles.otherForm}>
<Text style={[pal.text, s.mb5]}>
<Text nativeID="addressProvider" style={[pal.text, s.mb5]}>
Enter the address of your provider:
</Text>
<TextInput
Expand All @@ -82,6 +82,9 @@ export const Step1 = observer(({model}: {model: CreateAccountModel}) => {
value={model.serviceUrl}
editable
onChange={onChangeServiceUrl}
accessibilityHint="Input hosting provider address"
accessibilityLabel="Hosting provider address"
accessibilityLabelledBy="addressProvider"
/>
{LOGIN_INCLUDE_DEV_SERVERS && (
<View style={[s.flexRow, s.mt10]}>
Expand Down Expand Up @@ -136,7 +139,12 @@ function Option({

return (
<View style={[styles.option, pal.border]}>
<TouchableWithoutFeedback onPress={onPress} testID={testID}>
<TouchableWithoutFeedback
onPress={onPress}
testID={testID}
accessibilityRole="button"
accessibilityLabel={label}
accessibilityHint={`Sets hosting provider to ${label}`}>
<View style={styles.optionHeading}>
<View style={[styles.circle, pal.border]}>
{isSelected ? (
Expand Down
33 changes: 28 additions & 5 deletions src/view/com/auth/create/Step2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,29 @@ export const Step2 = observer(({model}: {model: CreateAccountModel}) => {
value={model.inviteCode}
editable
onChange={model.setInviteCode}
accessibilityRole="button"
accessibilityLabel="Invite code"
accessibilityHint="Input invite code to proceed"
/>
</View>
)}

{!model.inviteCode && model.isInviteCodeRequired ? (
<Text style={[s.alignBaseline, pal.text]}>
Don't have an invite code?{' '}
<TouchableWithoutFeedback onPress={onPressWaitlist}>
<TouchableWithoutFeedback
onPress={onPressWaitlist}
accessibilityRole="button"
accessibilityLabel="Waitlist"
accessibilityHint="Opens Bluesky waitlist form">
<Text style={pal.link}>Join the waitlist</Text>
</TouchableWithoutFeedback>{' '}
to try the beta before it's publicly available.
</Text>
) : (
<>
<View style={s.pb20}>
<Text type="md-medium" style={[pal.text, s.mb2]}>
<Text type="md-medium" style={[pal.text, s.mb2]} nativeID="email">
Email address
</Text>
<TextInput
Expand All @@ -66,11 +73,17 @@ export const Step2 = observer(({model}: {model: CreateAccountModel}) => {
value={model.email}
editable
onChange={model.setEmail}
accessibilityLabel="Email"
accessibilityHint="Input email for Bluesky waitlist"
accessibilityLabelledBy="email"
/>
</View>

<View style={s.pb20}>
<Text type="md-medium" style={[pal.text, s.mb2]}>
<Text
type="md-medium"
style={[pal.text, s.mb2]}
nativeID="password">
Password
</Text>
<TextInput
Expand All @@ -81,17 +94,27 @@ export const Step2 = observer(({model}: {model: CreateAccountModel}) => {
editable
secureTextEntry
onChange={model.setPassword}
accessibilityLabel="Password"
accessibilityHint="Set password"
accessibilityLabelledBy="password"
/>
</View>

<View style={s.pb20}>
<Text type="md-medium" style={[pal.text, s.mb2]}>
<Text
type="md-medium"
style={[pal.text, s.mb2]}
nativeID="legalCheck">
Legal check
</Text>
<TouchableOpacity
testID="is13Input"
style={[styles.toggleBtn, pal.border]}
onPress={() => model.setIs13(!model.is13)}>
onPress={() => model.setIs13(!model.is13)}
accessibilityRole="checkbox"
accessibilityLabel="Verify age"
accessibilityHint="Verifies that I am at least 13 years of age"
accessibilityLabelledBy="legalCheck">
<View style={[pal.borderDark, styles.checkbox]}>
{model.is13 && (
<FontAwesomeIcon icon="check" style={s.blue3} size={16} />
Expand Down
3 changes: 3 additions & 0 deletions src/view/com/auth/create/Step3.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export const Step3 = observer(({model}: {model: CreateAccountModel}) => {
value={model.handle}
editable
onChange={model.setHandle}
// TODO: Add explicit text label
accessibilityLabel="User handle"
accessibilityHint="Input your user handle"
/>
<Text type="lg" style={[pal.text, s.pl5, s.pt10]}>
Your full handle will be{' '}
Expand Down
Loading

0 comments on commit 83959c5

Please sign in to comment.