Repository: Automattic/wp-calypso
Pull request #101256: /me: Improve profile upload button
Author: login: gabrielcaires
Created: 2025-03-12T17:13:13Z | Merged: 2025-03-17T17:22:20Z

Related to  [#100239](https://github.com/Automattic/wp-calypso/issues/100239)

## Proposed Changes
* Layout + Animation suggestion to make the "button" + uploading more visible.
* Improve the verify email state


## Layout + Animation
https://github.com/user-attachments/assets/fa949def-dcbf-42f9-9800-1e0f7848a213

## Email verification pending
![CleanShot 2025-03-12 at 17 12 24@2x](https://github.com/user-attachments/assets/27ece73b-12a5-4c93-80df-67f5bb7b9353)


## Testing Instructions

* Go to /me
* Upload a photo
* Check if the animation looks like the video


@matt-west  Could you please review the layout and animation If is ok, just for this iteration




> [!IMPORTANT]  
> This PR does not aim to fix any accessibility issue on the same component; the existent implementation was not concerned about it. 
> If we merge this layout, I can open another one focused on it. 


<!--
Complete applicable items on this checklist **before** merging into trunk. Inapplicable items can be left unchecked.

Both the PR author and reviewer are responsible for ensuring the checklist is completed.
-->

- [ ] Has the general commit checklist been followed? (PCYsg-hS-p2)
- [ ] [Have you written new tests](https://wpcalypso.wordpress.com/devdocs/docs/testing/index.md) for your changes?
- [ ] Have you tested the feature in Simple (P9HQHe-k8-p2), Atomic (P9HQHe-jW-p2), and self-hosted Jetpack sites (PCYsg-g6b-p2)?
- [ ] Have you checked for TypeScript, React or other console errors?
- [ ] Have you used memoizing on expensive computations? More info in [Memoizing with create-selector](https://github.com/Automattic/wp-calypso/blob/trunk/packages/state-utils/src/create-selector/README.md) and [Using memoizing selectors](https://react-redux.js.org/api/hooks#using-memoizing-selectors) and [Our Approach to Data](https://github.com/Automattic/wp-calypso/blob/trunk/docs/our-approach-to-data.md)
- [ ] Have we added the "[Status] String Freeze" label as soon as any new strings were ready for translation (p4TIVU-5Jq-p2)?
    - [ ] For UI changes, have we tested the change in various languages (for example, ES, PT, FR, or DE)? The length of text and words vary significantly between languages. 
- [ ] For changes affecting Jetpack: Have we added the "[Status] Needs Privacy Updates" label if this pull request changes what data or activity we track or use (p4TIVU-aUh-p2)?



Diff:
diff --git a/client/blocks/edit-gravatar/index.jsx b/client/blocks/edit-gravatar/index.jsx
index 03701c01982a..803e7825b10c 100644
--- a/client/blocks/edit-gravatar/index.jsx
+++ b/client/blocks/edit-gravatar/index.jsx
@@ -1,5 +1,7 @@
 import path from 'path';
-import { Dialog, Gridicon, Spinner, ExternalLink } from '@automattic/components';
+import { Dialog, Gridicon, ExternalLink } from '@automattic/components';
+import { Spinner } from '@wordpress/components';
+import { Icon, upload, caution } from '@wordpress/icons';
 import clsx from 'clsx';
 import i18n, { localize } from 'i18n-calypso';
 import PropTypes from 'prop-types';
@@ -225,10 +227,6 @@ export class EditGravatar extends Component {
 			return this.renderGravatarProfileHidden( { gravatarLink, translate } );
 		}
 
-		const icon = user.email_verified ? 'cloud-upload' : 'notice';
-		const buttonText = user.email_verified
-			? translate( 'Click to change photo' )
-			: translate( 'Verify your email' );
 		/* eslint-disable jsx-a11y/click-events-have-key-events */
 		/* eslint-disable jsx-a11y/no-static-element-interactions */
 		return (
@@ -254,13 +252,27 @@ export class EditGravatar extends Component {
 								/>
 							) }
 							<Gravatar imgSize={ GRAVATAR_IMG_SIZE } size={ 150 } user={ user } />
-							{ ! isUploading && (
-								<div className="edit-gravatar__label-container">
-									<Gridicon icon={ icon } size={ 36 } />
-									<span className="edit-gravatar__label">{ buttonText }</span>
+							<div className="edit-gravatar__label-container">
+								<div className="edit-gravatar__label-container-icon">
+									{ ! user.email_verified && (
+										<Icon className="gridicon" icon={ caution } fill="#fff" size={ 24 } />
+									) }
+
+									{ user.email_verified && ! isUploading && (
+										<Icon className="gridicon" icon={ upload } fill="#fff" size={ 24 } />
+									) }
+
+									{ user.email_verified && isUploading && (
+										<Spinner
+											style={ {
+												width: 24,
+												height: 24,
+											} }
+											className="edit-gravatar__label-container-icon-spinner"
+										/>
+									) }
 								</div>
-							) }
-							{ isUploading && <Spinner className="edit-gravatar__spinner" /> }
+							</div>
 						</div>
 					</FilePicker>
 				</div>
diff --git a/client/blocks/edit-gravatar/style.scss b/client/blocks/edit-gravatar/style.scss
index d6b6810d5bd8..6f53d2dd42e3 100644
--- a/client/blocks/edit-gravatar/style.scss
+++ b/client/blocks/edit-gravatar/style.scss
@@ -87,21 +87,59 @@
 
 .edit-gravatar__label-container {
 	position: absolute;
-	left: 0;
 	top: 0;
-	width: 150px;
-	height: 150px;
-	border-radius: 50%;
-	background: rgba(var(--color-neutral-70-rgb), 0.5);
-	color: #fff;
+	left: 0;
+	width: 100%;
+	height: 100%;
+
+	// transform: translate(180%, 180%);
 	text-align: center;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	color: #fff;
+	transition: all 0.3s ease;
+	.edit-gravatar__label-container-icon {
+		padding: 10px;
+		border-radius: 50%;
+		background-color: var(--color-accent-60);
+		width: 24px;
+		height: 24px;
+		transform: translate(100%, 100%);
+		border: solid 2px transparent;
+		transition: all 0.3s ease;
+	}
 
-	.gridicon {
-		display: block;
-		margin: 2em auto 0;
+}
+
+.edit-gravatar__image-container:hover, .is-uploading .edit-gravatar__image-container {
+	.gravatar{
+		filter: brightness(0.7);
+	}
+}
+
+.edit-gravatar__image-container .edit-gravatar__label-container-icon {
+	background-color: var(--color-accent-70);
+	border-color: #fff;
+}
+
+.is-uploading .edit-gravatar__image-container {
+	.edit-gravatar__label-container-icon {
+		background-color: #fff;
 	}
 }
 
+.is-unverified .edit-gravatar__label-container-icon {
+	background-color: var(--studio-red-60);
+	border-color: #fff;
+}
+
+.edit-gravatar .edit-gravatar__label-container-icon-spinner{
+	margin: 0;
+	width: 24px;
+	height: 24px;
+}
+
 .edit-gravatar__gravatar-is-hidden .gridicon {
 	margin: 0;
 	position: absolute;


Reviews:
user: login: daledupreez
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T08:22:55Z
user: login: gabrielcaires
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T18:51:22Z
user: login: daledupreez
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T12:13:05Z
user: login: markbiek
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T14:26:30Z
user: login: daledupreez
body: @markbiek, it may make sense to leave the accessibility work for a follow-up PR, given that we're trying to focus on the UX for this component in this PR.

As far as I can tell, the `FilePicker` component is extremely inaccessible, and likely needs a non-trivial refactor.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T11:25:07Z
user: login: matt-west
body: Looks good. Thanks @markbiek 👍 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T17:17:34Z

Review comments:
diff_hunk: @@ -254,13 +252,27 @@ export class EditGravatar extends Component {
 								/>
 							) }
 							<Gravatar imgSize={ GRAVATAR_IMG_SIZE } size={ 150 } user={ user } />
-							{ ! isUploading && (
-								<div className="edit-gravatar__label-container">
-									<Gridicon icon={ icon } size={ 36 } />
-									<span className="edit-gravatar__label">{ buttonText }</span>
+							<div className="edit-gravatar__label-container">
+								<div className="edit-gravatar__label-container-icon">
+									{ ! user.email_verified && (
+										<Icon className="gridicon" icon={ caution } fill="#fff" size={ 24 } />
+									) }
+
+									{ user.email_verified && ! isUploading && (
+										<Icon className="gridicon" icon={ upload } fill="#fff" size={ 24 } />
+									) }
+
+									{ user.email_verified && isUploading && (
+										<Spinner
+											style={ {
+												width: 24,
+												height: 24,
+											} }
+											className="edit-gravatar__label-container-icon-spinner"
+										/>
+									) }
path: client/blocks/edit-gravatar/index.jsx
user: login: daledupreez
body: We should add some text to ensure there is some non-visual/accessible context.

It also looks like the `FilePicker` component (and the way it is used in this context) is not very accessible -- it's only `div` and `span` elements before the user clicks on the wrapper div, and we then show an unlabelled `input` field. But that may be something we can tackle in a follow-up.
created_at: 2025-03-13T08:22:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -254,13 +252,27 @@ export class EditGravatar extends Component {
 								/>
 							) }
 							<Gravatar imgSize={ GRAVATAR_IMG_SIZE } size={ 150 } user={ user } />
-							{ ! isUploading && (
-								<div className="edit-gravatar__label-container">
-									<Gridicon icon={ icon } size={ 36 } />
-									<span className="edit-gravatar__label">{ buttonText }</span>
+							<div className="edit-gravatar__label-container">
+								<div className="edit-gravatar__label-container-icon">
+									{ ! user.email_verified && (
+										<Icon className="gridicon" icon={ caution } fill="#fff" size={ 24 } />
+									) }
+
+									{ user.email_verified && ! isUploading && (
+										<Icon className="gridicon" icon={ upload } fill="#fff" size={ 24 } />
+									) }
+
+									{ user.email_verified && isUploading && (
+										<Spinner
+											style={ {
+												width: 24,
+												height: 24,
+											} }
+											className="edit-gravatar__label-container-icon-spinner"
+										/>
+									) }
path: client/blocks/edit-gravatar/index.jsx
user: login: gabrielcaires
body: I am happy to iterate over the implementation in futher PRs to make it more accessible.

Adopting correct element roles and adding the proper aria-attributes can make way better.

We don't need to exactly to have the words visible.(Comparing with the previous version)
created_at: 2025-03-13T18:51:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -238,29 +236,62 @@ export class EditGravatar extends Component {
 					{ 'is-unverified': ! user.email_verified },
 					{ 'is-uploading': isUploading }
 				) }
+				role="region"
+				aria-label={ translate( 'Profile photo editor' ) }
 			>
 				<div onClick={ this.handleUnverifiedUserClick }>
-					<FilePicker accept="image/*" onPick={ this.onReceiveFile }>
+					<FilePicker
+						accept="image/*"
+						onPick={ this.onReceiveFile }
+						aria-describedby="gravatar-description gravatar-instructions"
+					>
 						<div
 							data-tip-target="edit-gravatar"
 							className={ clsx( 'edit-gravatar__image-container', {
 								'is-uploading': isUploading,
 							} ) }
+							role="button"
path: client/blocks/edit-gravatar/index.jsx
user: login: daledupreez
body: Isn't the wrapper `FilePicker` div the actual button? It feels like we might need to push some of the accessibility items into that component rather than trying to add them all here.
created_at: 2025-03-14T12:13:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -238,29 +236,62 @@ export class EditGravatar extends Component {
 					{ 'is-unverified': ! user.email_verified },
 					{ 'is-uploading': isUploading }
 				) }
+				role="region"
+				aria-label={ translate( 'Profile photo editor' ) }
 			>
 				<div onClick={ this.handleUnverifiedUserClick }>
-					<FilePicker accept="image/*" onPick={ this.onReceiveFile }>
+					<FilePicker
+						accept="image/*"
+						onPick={ this.onReceiveFile }
+						aria-describedby="gravatar-description gravatar-instructions"
+					>
 						<div
 							data-tip-target="edit-gravatar"
 							className={ clsx( 'edit-gravatar__image-container', {
 								'is-uploading': isUploading,
 							} ) }
+							role="button"
path: client/blocks/edit-gravatar/index.jsx
user: login: markbiek
body: Ah yes, you're correct. I misunderstood where the click was happening. I'll move those attributes.
created_at: 2025-03-14T14:26:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -238,29 +236,62 @@ export class EditGravatar extends Component {
 					{ 'is-unverified': ! user.email_verified },
 					{ 'is-uploading': isUploading }
 				) }
+				role="region"
+				aria-label={ translate( 'Profile photo editor' ) }
 			>
 				<div onClick={ this.handleUnverifiedUserClick }>
-					<FilePicker accept="image/*" onPick={ this.onReceiveFile }>
+					<FilePicker
+						accept="image/*"
+						onPick={ this.onReceiveFile }
+						aria-describedby="gravatar-description gravatar-instructions"
+						role="button"
+						aria-label={ translate( 'Change profile photo' ) }
+						aria-busy={ isUploading }
+					>
path: client/blocks/edit-gravatar/index.jsx
user: login: daledupreez
body: This approach isn't valid. 😬 The `FilePicker` component ignores all these additional props:
https://github.com/Automattic/wp-calypso/blob/cdccf6ac192283acb68dc06c4bce1d00f17c6296/client/components/file-picker/index.jsx#L18-L25
created_at: 2025-03-17T11:20:27Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-03-12T17:13:25Z
body: <details>
<summary>Calypso Live <a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137247">(direct link)</a></summary>
<table>
<tr>
<td>
<img src="https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https%3A%2F%2Fcalypso.live%3Fimage%3Dregistry.a8c.com%2Fcalypso%2Fapp%3Abuild-137247%26flags%3Doauth&choe=UTF-8" />
</td>
<td>
<a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137247">https://calypso.live?image=registry.a8c.com/calypso/app:build-137247</a>
</td>
</tr>
</table>
</details>
<details>
<summary>Jetpack Cloud live <a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137247&env=jetpack">(direct link)</a></summary>
<table>
<tr>
<td>
<img src="https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https%3A%2F%2Fcalypso.live%3Fimage%3Dregistry.a8c.com%2Fcalypso%2Fapp%3Abuild-137247%26env%3Djetpack%26flags%3Doauth&choe=UTF-8" />
</td>
<td>
<a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137247&env=jetpack">https://calypso.live?image=registry.a8c.com/calypso/app:build-137247&env=jetpack</a>
</td>
</tr>
</table>
</details>
<details>
<summary>Automattic for Agencies live <a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137247&env=a8c-for-agencies">(direct link)</a></summary>
<table>
<tr>
<td>
<img src="https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https%3A%2F%2Fcalypso.live%3Fimage%3Dregistry.a8c.com%2Fcalypso%2Fapp%3Abuild-137247%26env%3Da8c-for-agencies%26flags%3Doauth&choe=UTF-8" />
</td>
<td>
<a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137247&env=a8c-for-agencies">https://calypso.live?image=registry.a8c.com/calypso/app:build-137247&env=a8c-for-agencies</a>
</td>
</tr>
</table>
</details>
<!--calypso-live-watermark:apr@v1-->
author_association: NONE
user: login: matticbot
created_at: 2025-03-12T17:15:40Z
body: <!-- icfy-watermark: c52822 -->
Here is how your PR affects size of JS and CSS bundles shipped to the user's browser:

**App Entrypoints** (~52 bytes added 📈 [gzipped])
<details>

```
name                 parsed_size           gzip_size
entry-main                +540 B  (+0.0%)      +60 B  (+0.0%)
entry-subscriptions       -103 B  (-0.0%)      +21 B  (+0.0%)
```

Common code that is always downloaded and parsed every time the app is loaded, no matter which route is used.
</details>

**Sections** (~1169 bytes removed 📉 [gzipped])
<details>

```
name                             parsed_size           gzip_size
account-close                        +3038 B  (+0.5%)    +1194 B  (+0.7%)
site-blocks                          +2832 B  (+0.5%)    +1157 B  (+0.6%)
security                             +2832 B  (+0.3%)    +1221 B  (+0.5%)
me                                   +2832 B  (+0.5%)    +1138 B  (+0.7%)
help                                 +2832 B  (+0.5%)    +1146 B  (+0.6%)
privacy                              +2739 B  (+0.5%)     +407 B  (+0.2%)
developer                            +2739 B  (+0.5%)     +434 B  (+0.2%)
account                              +1479 B  (+0.2%)      +70 B  (+0.0%)
notification-settings                +1140 B  (+0.2%)     -174 B  (-0.1%)
purchases                            +1033 B  (+0.0%)      +47 B  (+0.0%)
reader                                +320 B  (+0.0%)      -46 B  (-0.0%)
a8c-for-agencies-sites                +320 B  (+0.0%)      -74 B  (-0.0%)
a8c-for-agencies-woopayments          +307 B  (+0.0%)       -6 B  (-0.0%)
a8c-for-agencies-team                 +307 B  (+0.0%)      -12 B  (-0.0%)
a8c-for-agencies-referrals            +307 B  (+0.0%)       -2 B  (-0.0%)
a8c-for-agencies-overview             +307 B  (+0.0%)      +10 B  (+0.0%)
a8c-for-agencies-migrations           +307 B  (+0.0%)       +4 B  (+0.0%)
a8c-for-agencies-client               +307 B  (+0.0%)     -118 B  (-0.0%)
subscribers                           +294 B  (+0.0%)      -49 B  (-0.0%)
staging-site                          +294 B  (+0.0%)      -49 B  (-0.0%)
sites-dashboard                       +294 B  (+0.0%)      -49 B  (-0.0%)
site-settings                         +294 B  (+0.0%)      -49 B  (-0.0%)
site-purchases                        +294 B  (+0.0%)      -49 B  (-0.0%)
site-performance                      +294 B  (+0.0%)      -49 B  (-0.0%)
site-monitoring                       +294 B  (+0.0%)      -49 B  (-0.0%)
site-logs                             +294 B  (+0.0%)      -49 B  (-0.0%)
plugins                               +294 B  (+0.0%)      -49 B  (-0.0%)
plans                                 +294 B  (+0.0%)      -49 B  (-0.0%)
patterns                              +294 B  (+0.0%)      +11 B  (+0.0%)
overview                              +294 B  (+0.0%)      -49 B  (-0.0%)
jetpack-cloud-plugin-management       +294 B  (+0.0%)      -49 B  (-0.0%)
hosting                               +294 B  (+0.0%)      -49 B  (-0.0%)
github-deployments                    +294 B  (+0.0%)      -49 B  (-0.0%)
domains                               +294 B  (+0.0%)      -49 B  (-0.0%)
a8c-for-agencies-plugins              +294 B  (+0.0%)      -49 B  (-0.0%)
a8c-for-agencies-marketplace          +294 B  (+0.0%)      +11 B  (+0.0%)
devdocs                               +118 B  (+0.1%)      +12 B  (+0.0%)
jetpack-cloud-agency-dashboard         +26 B  (+0.0%)      -58 B  (-0.0%)
jetpack-cloud-partner-portal           +13 B  (+0.0%)      -66 B  (-0.0%)
a8c-for-agencies-purchases             +13 B  (+0.0%)     -125 B  (-0.1%)
```

Sections contain code specific for a given set of routes. Is downloaded and parsed only when a particular route is navigated to.
</details>

**Async-loaded Components** (~1938 bytes added 📈 [gzipped])
<details>

```
name                                                                         parsed_size           gzip_size
async-load-signup-steps-p2-complete-profile                                      +2844 B  (+1.6%)     +711 B  (+1.2%)
async-load-comment-block-editor                                                   +294 B  (+0.0%)      +11 B  (+0.0%)
async-load-automattic-global-styles-src-components-global-styles-variations       +294 B  (+0.0%)      +11 B  (+0.0%)
async-load-design-playground                                                      -208 B  (-0.0%)      -19 B  (-0.0%)
async-load-design                                                                 -208 B  (-0.0%)      -19 B  (-0.0%)
async-load-signup-steps-site-picker                                                +26 B  (+0.0%)      -40 B  (-0.1%)
async-load-signup-steps-difm-site-picker                                           +26 B  (+0.0%)      -35 B  (-0.0%)
async-load-design-blocks                                                           +26 B  (+0.0%)      -57 B  (-0.0%)
async-load-signup-steps-domains                                                    -13 B  (-0.0%)     +101 B  (+0.1%)
```

React components that are loaded lazily, when a certain part of UI is displayed for the first time.
</details>

**Legend**
<details>
<summary>What is parsed and gzip size?</summary>

**Parsed Size:** Uncompressed size of the JS and CSS files. This much code needs to be parsed and stored in memory.
**Gzip Size:** Compressed size of the JS and CSS files. This much data needs to be downloaded over network.
</details>

Generated by performance advisor bot at [iscalypsofastyet.com](http://iscalypsofastyet.com).
author_association: CONTRIBUTOR
user: login: matticbot
created_at: 2025-03-12T17:33:49Z
body: **This PR modifies the release build for the following Calypso Apps:**

_For info about this notification, see here: PCYsg-OT6-p2_

* notifications
* wpcom-block-editor

To test WordPress.com changes, run `install-plugin.sh $pluginSlug update/improve-uploading-buton` on your sandbox.
<!--calypso-app-artifacts-watermark:apr@v1-->
author_association: CONTRIBUTOR
user: login: markbiek
created_at: 2025-03-13T21:40:32Z
body: With help from Cursor, I took a stab at adding some accessibility improvements. They seemed to score well on Google Lighthouse but please let me know if anything is wrong or could be done better.
author_association: CONTRIBUTOR
user: login: matt-west
created_at: 2025-03-14T12:32:17Z
body: Thanks for working on this!

Let’s always show the white border around the icon, rather than only having it on hover. It helps differentiate from the avatar image.

<img width="196" alt="Screenshot 2025-03-14 at 12 24 27" src="https://github.com/user-attachments/assets/9a28900a-e098-465a-a62c-6dabb4fc56e3" />

For the loading state, let’s drop the dotted border around the avatar. That doesn’t really ft with our visual design language.

<img width="213" alt="Screenshot 2025-03-14 at 12 25 12" src="https://github.com/user-attachments/assets/0325f1fa-f678-4c43-9100-6e73fd170f22" />

The loading spinner is quite difficult to see again the blue background. Let’s try making the background white in the loading state instead.

I wasn’t able to test the email verification state. This is what I see after changing my email:

<img width="1563" alt="Screenshot 2025-03-14 at 12 30 01" src="https://github.com/user-attachments/assets/fe79b876-e205-4eed-9a42-f9365f4a7b44" />

I’m not sure the email verification state is needed. I don’t see one with what we have live at the moment, but please correct me if I’m wrong.
author_association: CONTRIBUTOR
user: login: markbiek
created_at: 2025-03-14T14:55:25Z
body: @matt-west What do you think about this for the loading state?

<img width="338" alt="CleanShot 2025-03-14 at 10 54 38@2x" src="https://github.com/user-attachments/assets/b8c34af4-943b-4ca7-9c40-5dc4efb30839" />

I'll defer to your judgement but it seemed a little washed out to me when it doesn't have a border:

<img width="307" alt="CleanShot 2025-03-14 at 10 55 05@2x" src="https://github.com/user-attachments/assets/df95c7ff-1c1f-410b-b736-44fa50ab5187" />


author_association: CONTRIBUTOR
user: login: markbiek
created_at: 2025-03-14T15:04:23Z
body: I've made the other UI tweaks. Let me know if you want me to get rid of the blue border on the loading spinner.
author_association: CONTRIBUTOR
user: login: markbiek
created_at: 2025-03-17T14:05:22Z
body: > @markbiek, it may make sense to leave the accessibility work for a follow-up PR, given that we're trying to focus on the UX for this component in this PR.
> 
> As far as I can tell, the `FilePicker` component is extremely inaccessible, and likely needs a non-trivial refactor.

That's totally fair. I thought it would be a quicker addition 😁 .

I'll remove that part for now.
author_association: CONTRIBUTOR
user: login: markbiek
created_at: 2025-03-17T14:10:13Z
body: @daledupreez The a11y stuff is gone now.

@matt-west Let me know if you have any other UI tweaks or if my latest changes look OK.
author_association: CONTRIBUTOR
user: login: matt-west
created_at: 2025-03-17T16:42:04Z
body: Thanks @markbiek. Let's go without the blue border in the loading state. 
author_association: CONTRIBUTOR
user: login: markbiek
created_at: 2025-03-17T16:51:23Z
body: > Thanks @markbiek. Let's go without the blue border in the loading state.

Done!
author_association: CONTRIBUTOR
user: login: gabrielcaires
created_at: 2025-03-18T14:06:43Z
body: Hello @markbiek 
I just noticed the latest animation used the wrong blue tone and was missing a hover animation.

I fixed it here https://github.com/Automattic/wp-calypso/pull/101522
author_association: CONTRIBUTOR
user: login: gabrielcaires
created_at: 2025-03-18T14:20:22Z
body: The accessibility requirements will be fixed in this [issue](https://github.com/Automattic/wp-calypso/issues/101523) 
author_association: CONTRIBUTOR
user: login: markbiek
created_at: 2025-03-18T14:22:28Z
body: > Hello @markbiek I just noticed the latest animation used the wrong blue tone and was missing a hover animation.
> 
> I fixed it here #101522

Just reviewed and approved. Thanks for catching that.
author_association: CONTRIBUTOR