forked from jsnbuchanan/crowd-funder-for-time-pwa
feat(accessibility): enhance AccountViewView and document test suite
- Add ARIA annotations and roles to AccountViewView for better screen reader support - Add role="tooltip" to API server description - Improve input control accessibility with proper ARIA attributes - Add descriptive labels and aria-labels for interactive elements - Create comprehensive README.md for Playwright test suite - Document test structure and organization - Add setup instructions and prerequisites - Include troubleshooting guide and contribution guidelines - Link to related documentation This change improves accessibility compliance and makes the test suite more maintainable for contributors.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<TopMessage />
|
||||
|
||||
<!-- CONTENT -->
|
||||
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
|
||||
<main id="Content" class="p-6 pb-24 max-w-3xl mx-auto" role="main" aria-label="Account Profile">
|
||||
<!-- Heading -->
|
||||
<h1 id="ViewHeading" class="text-4xl text-center font-light">
|
||||
Your Identity
|
||||
@@ -14,6 +14,8 @@
|
||||
v-if="!activeDid"
|
||||
id="noticeBeforeShare"
|
||||
class="bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 mt-4"
|
||||
role="alert"
|
||||
aria-live="polite"
|
||||
>
|
||||
<p class="mb-4">
|
||||
<b>Note:</b> Before you can share with others or take any action, you
|
||||
@@ -28,10 +30,12 @@
|
||||
</div>
|
||||
|
||||
<!-- Identity Details -->
|
||||
<div
|
||||
<section
|
||||
id="sectionIdentityDetails"
|
||||
class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mt-4"
|
||||
aria-labelledby="identityDetailsHeading"
|
||||
>
|
||||
<h2 id="identityDetailsHeading" class="sr-only">Identity Details</h2>
|
||||
<div v-if="givenName">
|
||||
<h2 class="text-xl font-semibold mb-2">
|
||||
<span class="whitespace-nowrap">
|
||||
@@ -75,11 +79,17 @@
|
||||
:profile-image-url="profileImageUrl"
|
||||
class="inline-block align-text-bottom border border-slate-300 rounded"
|
||||
@click="showLargeIdenticonUrl = profileImageUrl"
|
||||
role="button"
|
||||
aria-label="View profile image in large size"
|
||||
tabindex="0"
|
||||
/>
|
||||
<font-awesome
|
||||
icon="trash-can"
|
||||
class="text-red-500 fa-fw ml-8 mt-8 w-12 h-12"
|
||||
@click="confirmDeleteImage"
|
||||
role="button"
|
||||
aria-label="Delete profile image"
|
||||
tabindex="0"
|
||||
/>
|
||||
</span>
|
||||
<div v-else class="text-center">
|
||||
@@ -140,17 +150,20 @@
|
||||
<div
|
||||
class="text-sm text-slate-500 flex justify-start items-center mb-1"
|
||||
data-testId="didWrapper"
|
||||
role="region"
|
||||
aria-label="Your Identifier"
|
||||
>
|
||||
<code class="truncate">{{ activeDid }}</code>
|
||||
<code class="truncate" aria-label="Your DID">{{ activeDid }}</code>
|
||||
<button
|
||||
class="ml-2"
|
||||
@click="
|
||||
doCopyTwoSecRedo(activeDid, () => (showDidCopy = !showDidCopy))
|
||||
"
|
||||
aria-label="Copy DID to clipboard"
|
||||
>
|
||||
<font-awesome icon="copy" class="text-slate-400 fa-fw"></font-awesome>
|
||||
<font-awesome icon="copy" class="text-slate-400 fa-fw" aria-hidden="true"></font-awesome>
|
||||
</button>
|
||||
<span v-show="showDidCopy">Copied</span>
|
||||
<span v-show="showDidCopy" role="status" aria-live="polite">Copied</span>
|
||||
</div>
|
||||
|
||||
<div class="text-blue-500 text-sm font-bold">
|
||||
@@ -158,7 +171,7 @@
|
||||
Your Activity
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Registration notice -->
|
||||
<!--
|
||||
@@ -169,6 +182,8 @@
|
||||
v-if="!isRegistered"
|
||||
id="noticeBeforeAnnounce"
|
||||
class="bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 mt-4"
|
||||
role="alert"
|
||||
aria-live="polite"
|
||||
>
|
||||
<p class="mb-4">
|
||||
<b>Note:</b> Before you can publicly announce a new project or time
|
||||
@@ -182,27 +197,31 @@
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<div
|
||||
<section
|
||||
v-if="isRegistered"
|
||||
id="sectionNotifications"
|
||||
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
|
||||
aria-labelledby="notificationsHeading"
|
||||
>
|
||||
<!-- label -->
|
||||
<div class="mb-2 font-bold">Notifications</div>
|
||||
<h2 id="notificationsHeading" class="mb-2 font-bold">Notifications</h2>
|
||||
<div class="flex items-center justify-between">
|
||||
<!-- label -->
|
||||
<div>
|
||||
Reminder Notification
|
||||
<font-awesome
|
||||
icon="question-circle"
|
||||
<button
|
||||
class="text-slate-400 fa-fw ml-2 cursor-pointer"
|
||||
@click.stop="showReminderNotificationInfo"
|
||||
/>
|
||||
aria-label="Learn more about reminder notifications"
|
||||
>
|
||||
<font-awesome icon="question-circle" aria-hidden="true"></font-awesome>
|
||||
</button>
|
||||
</div>
|
||||
<!-- toggle -->
|
||||
<div
|
||||
class="relative ml-2 cursor-pointer"
|
||||
@click="showReminderNotificationChoice()"
|
||||
role="switch"
|
||||
:aria-checked="notifyingReminder"
|
||||
aria-label="Toggle reminder notifications"
|
||||
tabindex="0"
|
||||
>
|
||||
<!-- input -->
|
||||
<input v-model="notifyingReminder" type="checkbox" class="sr-only" />
|
||||
@@ -253,49 +272,47 @@
|
||||
<router-link class="pl-4 text-sm text-blue-500" to="/help-notifications">
|
||||
Troubleshoot your notifications.
|
||||
</router-link>
|
||||
</div>
|
||||
</section>
|
||||
<PushNotificationPermission ref="pushNotificationPermission" />
|
||||
|
||||
<div
|
||||
<section
|
||||
id="sectionSearchLocation"
|
||||
class="flex justify-between bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
|
||||
aria-labelledby="searchLocationHeading"
|
||||
>
|
||||
<!-- label -->
|
||||
<span class="mb-2 font-bold">Location for Searches</span>
|
||||
<h2 id="searchLocationHeading" class="mb-2 font-bold">Location for Searches</h2>
|
||||
<router-link
|
||||
:to="{ name: 'search-area' }"
|
||||
class="text-m bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md mb-2"
|
||||
>
|
||||
{{ isSearchAreasSet ? "Change" : "Set" }} Search Area…
|
||||
</router-link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- User Profile -->
|
||||
<div
|
||||
<section
|
||||
v-if="isRegistered"
|
||||
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
|
||||
aria-labelledby="userProfileHeading"
|
||||
>
|
||||
<div v-if="loadingProfile" class="text-center mb-2">
|
||||
<font-awesome
|
||||
icon="spinner"
|
||||
class="fa-spin text-slate-400"
|
||||
></font-awesome>
|
||||
Loading profile...
|
||||
</div>
|
||||
<div v-else class="flex items-center mb-2">
|
||||
<h2 id="userProfileHeading" class="flex items-center mb-2">
|
||||
<span class="font-bold">Public Profile</span>
|
||||
<font-awesome
|
||||
icon="circle-info"
|
||||
<button
|
||||
class="text-slate-400 fa-fw ml-2 cursor-pointer"
|
||||
@click="showProfileInfo"
|
||||
/>
|
||||
</div>
|
||||
aria-label="Learn more about public profile"
|
||||
>
|
||||
<font-awesome icon="circle-info" aria-hidden="true"></font-awesome>
|
||||
</button>
|
||||
</h2>
|
||||
<textarea
|
||||
v-model="userProfileDesc"
|
||||
class="w-full h-32 p-2 border border-slate-300 rounded-md"
|
||||
placeholder="Write something about yourself for the public..."
|
||||
:readonly="loadingProfile || savingProfile"
|
||||
:class="{ 'bg-slate-100': loadingProfile || savingProfile }"
|
||||
aria-label="Public profile description"
|
||||
:aria-busy="loadingProfile || savingProfile"
|
||||
></textarea>
|
||||
|
||||
<div class="flex items-center mb-4" @click="toggleUserProfileLocation">
|
||||
@@ -364,18 +381,19 @@
|
||||
</div>
|
||||
<div v-else-if="loadingProfile">Loading...</div>
|
||||
<div v-else>Saving...</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div
|
||||
<section
|
||||
v-if="activeDid"
|
||||
id="sectionUsageLimits"
|
||||
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
|
||||
aria-labelledby="usageLimitsHeading"
|
||||
>
|
||||
<div class="mb-2 font-bold">Usage Limits</div>
|
||||
<h2 id="usageLimitsHeading" class="mb-2 font-bold">Usage Limits</h2>
|
||||
<!-- show spinner if loading limits -->
|
||||
<div v-if="loadingLimits" class="text-center">
|
||||
<div v-if="loadingLimits" class="text-center" role="status" aria-live="polite">
|
||||
Checking…
|
||||
<font-awesome icon="spinner" class="fa-spin"></font-awesome>
|
||||
<font-awesome icon="spinner" class="fa-spin" aria-hidden="true"></font-awesome>
|
||||
</div>
|
||||
<div class="mb-4 text-center">
|
||||
{{ limitsMessage }}
|
||||
@@ -423,7 +441,7 @@
|
||||
>
|
||||
Recheck Limits
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<DataExportSection :active-did="activeDid" />
|
||||
|
||||
@@ -435,7 +453,8 @@
|
||||
>
|
||||
Advanced
|
||||
</h3>
|
||||
<div v-if="showAdvanced || showGeneralAdvanced" id="sectionAdvanced">
|
||||
<section v-if="showAdvanced || showGeneralAdvanced" id="sectionAdvanced" aria-labelledby="advancedHeading">
|
||||
<h2 id="advancedHeading" class="text-blue-500 text-sm font-semibold mb-3">Advanced</h2>
|
||||
<p class="text-rose-600 mb-8">
|
||||
Beware: the features here can be confusing and even change data in ways
|
||||
you do not expect. But we support your freedom!
|
||||
@@ -606,41 +625,60 @@
|
||||
|
||||
<div id="sectionClaimServer">
|
||||
<h2 class="text-slate-500 text-sm font-bold mt-4">Claim Server</h2>
|
||||
<div class="px-4 py-4">
|
||||
<div class="px-4 py-4" role="group" aria-labelledby="claimServerHeading">
|
||||
<h3 id="claimServerHeading" class="sr-only">Claim Server Configuration</h3>
|
||||
<label for="apiServerInput" class="sr-only">API Server URL</label>
|
||||
<input
|
||||
id="apiServerInput"
|
||||
v-model="apiServerInput"
|
||||
type="text"
|
||||
class="block w-full rounded border border-slate-400 px-4 py-2"
|
||||
aria-describedby="apiServerDescription"
|
||||
placeholder="Enter API server URL"
|
||||
/>
|
||||
<div
|
||||
id="apiServerDescription"
|
||||
class="sr-only"
|
||||
role="tooltip"
|
||||
>
|
||||
Enter the URL for the claim server. You can use the buttons below to quickly set common server URLs.
|
||||
</div>
|
||||
<button
|
||||
v-if="apiServerInput != apiServer"
|
||||
class="w-full px-4 rounded bg-yellow-500 border border-slate-400"
|
||||
@click="onClickSaveApiServer()"
|
||||
aria-label="Save API server URL"
|
||||
>
|
||||
<font-awesome
|
||||
icon="floppy-disk"
|
||||
class="fa-fw"
|
||||
color="white"
|
||||
aria-hidden="true"
|
||||
></font-awesome>
|
||||
</button>
|
||||
<button
|
||||
class="px-3 rounded bg-slate-200 border border-slate-400"
|
||||
@click="apiServerInput = AppConstants.PROD_ENDORSER_API_SERVER"
|
||||
>
|
||||
Use Prod
|
||||
</button>
|
||||
<button
|
||||
class="px-3 rounded bg-slate-200 border border-slate-400"
|
||||
@click="apiServerInput = AppConstants.TEST_ENDORSER_API_SERVER"
|
||||
>
|
||||
Use Test
|
||||
</button>
|
||||
<button
|
||||
class="px-3 rounded bg-slate-200 border border-slate-400"
|
||||
@click="apiServerInput = AppConstants.LOCAL_ENDORSER_API_SERVER"
|
||||
>
|
||||
Use Local
|
||||
</button>
|
||||
<div class="mt-2" role="group" aria-label="Quick server selection">
|
||||
<button
|
||||
class="px-3 rounded bg-slate-200 border border-slate-400"
|
||||
@click="apiServerInput = AppConstants.PROD_ENDORSER_API_SERVER"
|
||||
aria-label="Use production server URL"
|
||||
>
|
||||
Use Prod
|
||||
</button>
|
||||
<button
|
||||
class="px-3 rounded bg-slate-200 border border-slate-400"
|
||||
@click="apiServerInput = AppConstants.TEST_ENDORSER_API_SERVER"
|
||||
aria-label="Use test server URL"
|
||||
>
|
||||
Use Test
|
||||
</button>
|
||||
<button
|
||||
class="px-3 rounded bg-slate-200 border border-slate-400"
|
||||
@click="apiServerInput = AppConstants.LOCAL_ENDORSER_API_SERVER"
|
||||
aria-label="Use local server URL"
|
||||
>
|
||||
Use Local
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label
|
||||
@@ -878,8 +916,8 @@
|
||||
>
|
||||
View Logs
|
||||
</router-link>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
Reference in New Issue
Block a user