mirror of
https://github.com/mozilla/fxa.git
synced 2025-12-28 07:03:55 +00:00
fix(settings): make elements use proper focus colors
Because: * Front-page Settings elements focus use system default outlines. This commit: * makes elements use proper focus outline colors and adds rounded corners to focus outlines. Closes #FXA-5787
This commit is contained in:
parent
e1b04e933f
commit
97f88a087a
@ -17,6 +17,7 @@ export const Footer = () => {
|
||||
<LinkExternal
|
||||
href="https://www.mozilla.org/about/?utm_source=firefox-accounts&utm_medium=Referral"
|
||||
data-testid="link-mozilla"
|
||||
className="focus-visible-default rounded-sm outline-offset-2"
|
||||
>
|
||||
<img
|
||||
src={mozLogo}
|
||||
@ -33,7 +34,7 @@ export const Footer = () => {
|
||||
<LinkExternal
|
||||
data-testid="link-privacy"
|
||||
href="https://www.mozilla.org/privacy/websites/"
|
||||
className="transition-standard text-xs hover:text-grey-500 hover:underline mobileLandscape:self-end"
|
||||
className="transition-standard text-xs mobileLandscape:self-end hover:text-grey-500 hover:underline focus-visible-default rounded-sm"
|
||||
>
|
||||
Website Privacy Notice
|
||||
</LinkExternal>
|
||||
@ -44,7 +45,7 @@ export const Footer = () => {
|
||||
<LinkExternal
|
||||
data-testid="link-terms"
|
||||
href="https://www.mozilla.org/about/legal/terms/services/"
|
||||
className="transition-standard text-xs mobileLandscape:self-end hover:text-grey-500 hover:underline"
|
||||
className="transition-standard text-xs mobileLandscape:self-end hover:text-grey-500 hover:underline focus-visible-default rounded-sm"
|
||||
>
|
||||
Terms of Service
|
||||
</LinkExternal>
|
||||
|
||||
@ -15,12 +15,7 @@ export const LogoLockup = ({ children, className = '' }: LogoLockupProps) => {
|
||||
return (
|
||||
<>
|
||||
<Localized id="app-logo-alt-3">
|
||||
<img
|
||||
src={logo}
|
||||
data-testid="logo"
|
||||
className="ltr:mr-4 rtl:ml-4"
|
||||
alt="Mozilla m logo"
|
||||
/>
|
||||
<img src={logo} data-testid="logo" alt="Mozilla m logo" />
|
||||
</Localized>
|
||||
<h1
|
||||
data-testid="logo-text"
|
||||
|
||||
14
packages/fxa-react/styles/focus.css
Normal file
14
packages/fxa-react/styles/focus.css
Normal file
@ -0,0 +1,14 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* This class is a baseline styling for the "focus" interactive state shared
|
||||
* across components, with shape-specific styles (e.g., border-radius,
|
||||
* outline-offset, etc) applied elsewhere.
|
||||
* Design document for reference: https://www.figma.com/design/2ruSnPauajQGprFy6K333u
|
||||
* NOTE: Using focus-visible instead of focus here because focus-visible is only
|
||||
* triggered when navigating with keyboard, while focus is also triggered by
|
||||
* mouse press, which is not the desired behavior for button-like components. */
|
||||
.focus-visible-default:focus-visible {
|
||||
@apply outline outline-blue-500 outline-2;
|
||||
}
|
||||
@ -13,3 +13,4 @@
|
||||
@import './flows.css';
|
||||
@import './tooltips.css';
|
||||
@import './inputs.css';
|
||||
@import './focus.css';
|
||||
|
||||
@ -104,7 +104,7 @@ export const Banner = ({
|
||||
<button
|
||||
aria-label={`Close banner`}
|
||||
className={classNames(
|
||||
'shrink-0 self-start hover:backdrop-saturate-150 focus:backdrop-saturate-200',
|
||||
'shrink-0 self-start hover:backdrop-saturate-150 focus:backdrop-saturate-200 focus-visible-default rounded',
|
||||
type === 'error' && 'hover:bg-red-200 focus:bg-red-300',
|
||||
type === 'info' &&
|
||||
!isFancy &&
|
||||
|
||||
@ -154,7 +154,7 @@ export const BrandMessaging = ({
|
||||
attrs={{ ariaLabel: true }}
|
||||
>
|
||||
<button
|
||||
className="w-4 h-4"
|
||||
className="w-4 h-4 rounded-sm focus-visible-default outline-offset-2"
|
||||
data-testid="close-brand-messaging"
|
||||
type="button"
|
||||
aria-label="Close banner"
|
||||
|
||||
@ -34,7 +34,7 @@ const ButtonBack = ({
|
||||
data-testid={dataTestId}
|
||||
title={localizedButtonTitle}
|
||||
aria-label={localizedButtonAriaLabel}
|
||||
className="me-4 tablet:me-0 tablet:p-4 tablet:absolute tablet:-start-24"
|
||||
className="me-4 tablet:me-0 tablet:p-4 tablet:absolute tablet:-start-24 rounded focus-visible-default"
|
||||
>
|
||||
<BackArrow className="w-6 h-auto text-grey-400 rtl:transform rtl:-scale-x-100" />
|
||||
</button>
|
||||
|
||||
@ -89,7 +89,7 @@ export const InputPassword = ({
|
||||
<button
|
||||
type="button"
|
||||
data-testid={formatDataTestId('visibility-toggle')}
|
||||
className="absolute end-0 inset-y-0 my-auto mx-2 px-2 text-grey-500 box-content"
|
||||
className="absolute end-0 inset-y-0 my-auto mx-2 px-2 text-grey-500 box-content focus-visible-default rounded"
|
||||
onClick={changeVisibilityStatus}
|
||||
title={
|
||||
visible
|
||||
|
||||
@ -37,8 +37,8 @@ const ResetPasswordWarning = ({
|
||||
setExpanded((e.currentTarget as HTMLDetailsElement).open)
|
||||
}
|
||||
>
|
||||
{/* Arbitrary varaite [&::-webkit-details-marker]:hidden removes the list arrow on webkit based browsers */}
|
||||
<summary className="flex items-center cursor-pointer list-none [&::-webkit-details-marker]:hidden">
|
||||
{/* Arbitrary variant [&::-webkit-details-marker]:hidden removes the list arrow on webkit based browsers */}
|
||||
<summary className="flex items-center cursor-pointer list-none [&::-webkit-details-marker]:hidden rounded-sm focus-visible-default outline-offset-2">
|
||||
<WarnIcon
|
||||
role="img"
|
||||
className="me-4"
|
||||
|
||||
@ -110,7 +110,7 @@ export const AlertBar = () => {
|
||||
</p>
|
||||
<button
|
||||
className={classNames(
|
||||
'shrink-0 items-stretch justify-center py-2 px-3',
|
||||
'shrink-0 items-stretch justify-center py-2 px-3 focus-visible:rounded-sm focus-visible-default',
|
||||
{
|
||||
'hover:bg-red-200 focus:bg-red-300': alertType() === 'error',
|
||||
'hover:bg-blue-100 focus:bg-blue-200': alertType() === 'info',
|
||||
|
||||
@ -113,7 +113,7 @@ export const BentoMenu = () => {
|
||||
aria-label={bentoMenuTitle}
|
||||
aria-expanded={!!isRevealed}
|
||||
aria-haspopup="menu"
|
||||
className="rounded p-2 mx-2 border-transparent hover:bg-grey-100 transition-standard desktop:mx-8"
|
||||
className="rounded p-2 mx-2 border-transparent hover:bg-grey-100 transition-standard desktop:mx-8 focus-visible-default"
|
||||
>
|
||||
<BentoIcon className="w-5 text-violet-900" />
|
||||
</button>
|
||||
@ -128,12 +128,15 @@ export const BentoMenu = () => {
|
||||
>
|
||||
<div className="flex flex-wrap">
|
||||
<div className="flex w-full py-4 gap-2 items-center flex-col tablet:w-auto tablet:relative">
|
||||
<button onClick={closeFn} title="Close">
|
||||
<CloseIcon
|
||||
width="16"
|
||||
height="16"
|
||||
className="absolute top-5 end-5 mobileLandscape:hidden fill-current"
|
||||
/>
|
||||
<button
|
||||
onClick={closeFn}
|
||||
title="Close"
|
||||
/* Clicking the bento icon again closes the menu, so
|
||||
there is no need to display the close button for non-mobile
|
||||
devices, even for screen readers. */
|
||||
className="absolute top-5 end-5 mobileLandscape:hidden rounded-sm focus-visible-default outline-offset-2"
|
||||
>
|
||||
<CloseIcon width="16" height="16" className="fill-current" />
|
||||
</button>
|
||||
<div className="mt-12 px-8 text-center mobileLandscape:mt-0">
|
||||
<FtlMsg id="bento-menu-tagline">
|
||||
@ -146,7 +149,7 @@ export const BentoMenu = () => {
|
||||
<LinkExternal
|
||||
data-testid="desktop-link"
|
||||
href={desktopLink}
|
||||
className="block p-2 ps-6 hover:bg-grey-100"
|
||||
className="block p-2 ps-6 hover:bg-grey-100 focus-visible:rounded-sm focus-visible-default"
|
||||
onClick={() =>
|
||||
GleanMetrics.accountPref.bentoFirefoxDesktop()
|
||||
}
|
||||
@ -163,7 +166,7 @@ export const BentoMenu = () => {
|
||||
<LinkExternal
|
||||
data-testid="mobile-link"
|
||||
href={mobileLink}
|
||||
className="block p-2 ps-6 hover:bg-grey-100"
|
||||
className="block p-2 ps-6 hover:bg-grey-100 focus-visible:rounded-sm focus-visible-default"
|
||||
onClick={() =>
|
||||
GleanMetrics.accountPref.bentoFirefoxMobile()
|
||||
}
|
||||
@ -180,7 +183,7 @@ export const BentoMenu = () => {
|
||||
<LinkExternal
|
||||
data-testid="monitor-link"
|
||||
href={monitorLink}
|
||||
className="block p-2 ps-6 hover:bg-grey-100"
|
||||
className="block p-2 ps-6 hover:bg-grey-100 focus-visible:rounded-sm focus-visible-default"
|
||||
onClick={() => GleanMetrics.accountPref.bentoMonitor()}
|
||||
>
|
||||
<div className={iconClassNames}>
|
||||
@ -193,7 +196,7 @@ export const BentoMenu = () => {
|
||||
<LinkExternal
|
||||
data-testid="relay-link"
|
||||
href={relayLink}
|
||||
className="block p-2 ps-6 hover:bg-grey-100"
|
||||
className="block p-2 ps-6 hover:bg-grey-100 focus-visible:rounded-sm focus-visible-default"
|
||||
onClick={() => GleanMetrics.accountPref.bentoRelay()}
|
||||
>
|
||||
<div className={iconClassNames}>
|
||||
@ -208,7 +211,7 @@ export const BentoMenu = () => {
|
||||
<LinkExternal
|
||||
data-testid="vpn-link"
|
||||
href={vpnLink}
|
||||
className="block p-2 ps-6 hover:bg-grey-100"
|
||||
className="block p-2 ps-6 hover:bg-grey-100 focus-visible:rounded-sm focus-visible-default"
|
||||
onClick={() => GleanMetrics.accountPref.bentoVpn()}
|
||||
>
|
||||
<div className={iconClassNames}>
|
||||
@ -221,7 +224,7 @@ export const BentoMenu = () => {
|
||||
<LinkExternal
|
||||
data-testid="pocket-link"
|
||||
href="https://app.adjust.com/hr2n0yz?redirect_macos=https%3A%2F%2Fgetpocket.com%2Fpocket-and-firefox&redirect_windows=https%3A%2F%2Fgetpocket.com%2Fpocket-and-firefox&engagement_type=fallback_click&fallback=https%3A%2F%2Fgetpocket.com%2Ffirefox_learnmore%3Fsrc%3Dff_bento&fallback_lp=https%3A%2F%2Fapps.apple.com%2Fapp%2Fpocket-save-read-grow%2Fid309601447"
|
||||
className="block p-2 ps-6 hover:bg-grey-100"
|
||||
className="block p-2 ps-6 hover:bg-grey-100 focus-visible:rounded-sm focus-visible-default"
|
||||
onClick={() => GleanMetrics.accountPref.bentoPocket()}
|
||||
>
|
||||
<div className={iconClassNames}>
|
||||
|
||||
@ -37,7 +37,7 @@ export function ConnectAnotherDevicePromo() {
|
||||
</div>
|
||||
<div className="flex flex-2 justify-center mt-5 mobileLandscape:mt-0 mobileLandscape:justify-end mobileLandscape:rtl:justify-start">
|
||||
<LinkExternal
|
||||
className="self-center"
|
||||
className="self-center rounded focus-visible-default outline-offset-2"
|
||||
data-testid="play-store-link"
|
||||
href="https://app.adjust.com/2uo1qc?redirect=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dorg.mozilla.firefox"
|
||||
onClick={() => GleanMetrics.accountPref.googlePlaySubmit()}
|
||||
@ -53,7 +53,7 @@ export function ConnectAnotherDevicePromo() {
|
||||
</Localized>
|
||||
</LinkExternal>
|
||||
<LinkExternal
|
||||
className="self-center p-2"
|
||||
className="self-center m-2 rounded focus-visible-default outline-offset-2"
|
||||
data-testid="app-store-link"
|
||||
href="https://app.adjust.com/2uo1qc?redirect=https%3A%2F%2Fitunes.apple.com%2Fus%2Fapp%2Ffirefox-private-safe-browser%2Fid989804926"
|
||||
onClick={() => GleanMetrics.accountPref.appleSubmit()}
|
||||
|
||||
@ -64,7 +64,7 @@ export const DropDownAvatarMenu = () => {
|
||||
aria-label={dropDownMenuTitle}
|
||||
aria-expanded={!!isRevealed}
|
||||
aria-haspopup="menu"
|
||||
className="rounded-full border border-transparent hover:border-purple-500 focus:border-purple-500 focus:outline-none active:border-purple-700 transition-standard"
|
||||
className="rounded-full border border-transparent hover:border-purple-500 active:border-purple-700 transition-standard focus-visible-default focus-visible:border-transparent"
|
||||
>
|
||||
<Avatar className="w-10 rounded-full" {...{ avatar }} />
|
||||
</button>
|
||||
@ -96,7 +96,7 @@ export const DropDownAvatarMenu = () => {
|
||||
<div className="bg-gradient-to-r from-blue-500 via-pink-700 to-yellow-500 h-px" />
|
||||
<div className="px-4 py-5">
|
||||
<button
|
||||
className="pl-3 group"
|
||||
className="ml-3 group rounded-sm focus-visible-default outline-offset-2"
|
||||
onClick={signOut}
|
||||
data-testid="avatar-menu-sign-out"
|
||||
>
|
||||
|
||||
@ -30,7 +30,7 @@ export const HeaderLockup = () => {
|
||||
const left = (
|
||||
<>
|
||||
<button
|
||||
className="desktop:hidden me-6 p-2 self-center -m-2 z-[1] rounded hover:bg-grey-100"
|
||||
className="desktop:hidden me-6 p-2 self-center -m-2 z-[1] rounded hover:bg-grey-100 focus-visible-default"
|
||||
data-testid="header-menu"
|
||||
aria-label={localizedMenuText}
|
||||
title={localizedMenuText}
|
||||
@ -50,15 +50,15 @@ export const HeaderLockup = () => {
|
||||
<a
|
||||
href="#"
|
||||
title="Back to top"
|
||||
className="flex"
|
||||
// use gap instead of margin to make the focus outline look right
|
||||
// when the header title is invisible
|
||||
className="flex gap-4 rounded-sm focus-visible:outline focus-visible:outline-blue-500 focus:outline-2 outline-offset-4"
|
||||
data-testid="back-to-top"
|
||||
>
|
||||
<LogoLockup>
|
||||
<>
|
||||
<Localized id="header-title-2">
|
||||
<span className="font-bold ltr:mr-2 rtl:ml-2">
|
||||
Mozilla account
|
||||
</span>
|
||||
<span className="font-bold">Mozilla account</span>
|
||||
</Localized>
|
||||
</>
|
||||
</LogoLockup>
|
||||
@ -71,7 +71,7 @@ export const HeaderLockup = () => {
|
||||
<LinkExternal
|
||||
href="https://support.mozilla.org/products/mozilla-account"
|
||||
title={localizedHelpText}
|
||||
className="inline-block relative p-2 -m-2 z-[1] rounded hover:bg-grey-100"
|
||||
className="inline-block relative p-2 -m-2 z-[1] rounded hover:bg-grey-100 focus-visible-default"
|
||||
onClick={handleHelpLinkClick}
|
||||
>
|
||||
<Help
|
||||
|
||||
@ -82,6 +82,7 @@ export const Modal = ({
|
||||
data-testid="modal-dismiss"
|
||||
onClick={(event) => onDismiss()}
|
||||
title={ftlMsgResolver.getMsg('modal-close-title', 'Close')}
|
||||
className="rounded focus-visible-default"
|
||||
>
|
||||
<CloseIcon className="w-4 h-4 m-3 fill-current" />
|
||||
</button>
|
||||
|
||||
@ -18,6 +18,8 @@ export interface NavRefProps {
|
||||
}
|
||||
|
||||
const navActiveClass = 'nav-active';
|
||||
const navItemClasses =
|
||||
'inline-block py-1 px-2 hover:bg-grey-100 rounded-sm focus-visible-default';
|
||||
|
||||
// Update the active nav class when this percentage of a section is shown on screen
|
||||
const STANDARD_SECTION_THRESHOLD = 0.8;
|
||||
@ -151,10 +153,7 @@ export const Nav = ({
|
||||
data-testid="nav-link-profile"
|
||||
href="#profile"
|
||||
ref={profileLinkRef}
|
||||
className={classNames(
|
||||
navActiveClass,
|
||||
'inline-block py-1 px-2 hover:bg-grey-100'
|
||||
)}
|
||||
className={classNames(navActiveClass, navItemClasses)}
|
||||
>
|
||||
Profile
|
||||
</a>
|
||||
@ -165,7 +164,7 @@ export const Nav = ({
|
||||
<a
|
||||
href="#security"
|
||||
data-testid="nav-link-security"
|
||||
className="inline-block py-1 px-2 hover:bg-grey-100"
|
||||
className={navItemClasses}
|
||||
ref={securityLinkRef}
|
||||
>
|
||||
Security
|
||||
@ -177,7 +176,7 @@ export const Nav = ({
|
||||
<a
|
||||
href="#connected-services"
|
||||
data-testid="nav-link-connected-services"
|
||||
className="inline-block py-1 px-2 hover:bg-grey-100"
|
||||
className={navItemClasses}
|
||||
ref={connectedServicesLinkRef}
|
||||
>
|
||||
Connected Services
|
||||
@ -190,7 +189,7 @@ export const Nav = ({
|
||||
<a
|
||||
href="#linked-accounts"
|
||||
data-testid="nav-link-linked-accounts"
|
||||
className="inline-block py-1 px-2 hover:bg-grey-100"
|
||||
className={navItemClasses}
|
||||
ref={linkedAccountsLinkRef}
|
||||
>
|
||||
Linked Accounts
|
||||
@ -203,7 +202,7 @@ export const Nav = ({
|
||||
<a
|
||||
href="#data-collection"
|
||||
data-testid="nav-link-data-collection"
|
||||
className="inline-block py-1 px-2 hover:bg-grey-100"
|
||||
className={navItemClasses}
|
||||
ref={dataCollectionLinkRef}
|
||||
>
|
||||
Data Collection and Use
|
||||
@ -216,7 +215,7 @@ export const Nav = ({
|
||||
{hasSubscription && (
|
||||
<li className="mb-5">
|
||||
<LinkExternal
|
||||
className="font-bold"
|
||||
className="font-bold focus-visible-default rounded-sm outline-offset-2"
|
||||
data-testid="nav-link-subscriptions"
|
||||
href="/subscriptions"
|
||||
>
|
||||
@ -232,7 +231,7 @@ export const Nav = ({
|
||||
{marketingCommPrefLink && (
|
||||
<li>
|
||||
<LinkExternal
|
||||
className="font-bold"
|
||||
className="font-bold focus-visible-default rounded-sm outline-offset-2"
|
||||
data-testid="nav-link-newsletters"
|
||||
href={marketingCommPrefLink}
|
||||
>
|
||||
|
||||
@ -198,7 +198,7 @@ const ThirdPartySignInForm = ({
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full px-2 mt-2 justify-center text-black bg-transparent border-grey-300 border hover:border-black rounded-lg text-md text-center inline-flex items-center"
|
||||
className="w-full px-2 mt-2 justify-center text-black bg-transparent border-grey-300 border hover:border-black rounded-lg text-md text-center inline-flex items-center focus-visible-default outline-offset-2"
|
||||
onClick={onClick}
|
||||
>
|
||||
{buttonText}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.switch {
|
||||
@apply relative min-w-16 align-top border bg-transparent rounded-full overflow-hidden;
|
||||
@apply relative min-w-16 align-top border bg-transparent rounded-full overflow-hidden focus-visible-default;
|
||||
height: calc(1.5rem + 2px); /* 2px increase accounts for the border */
|
||||
|
||||
.slider {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user