Explicitly set tabIndex for log in buttons, since Safari does not interpret them as "interactive elements" in the same way it does input fields; clean up, test (#37019)

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #36735 (see
https://fleetdm.slack.com/archives/C019WG4GH0A/p1765304390750399?thread_ts=1765303643.855049&cid=C019WG4GH0A)

Safari now has same tab order without having to hold option button while
tabbing:

![ezgif-758724f23b5b7550](https://github.com/user-attachments/assets/9ba83634-9211-4c61-9798-d84a1ebb9a15)

- Confirmed order is maintained on Firefox and Chrome
- Cleaned up inaccurate emptiness checks and unnecessary wrappers
- Test

- [x] QA'd all new/changed functionality manually
- [x] Added tests 
- [x] Confirmed that the fix is not expected to adversely impact load
test results
This commit is contained in:
jacobshandling
2025-12-09 14:10:23 -08:00
committed by GitHub
parent ffcf314a3c
commit c5cac90df0
2 changed files with 33 additions and 6 deletions
@@ -140,4 +140,29 @@ describe("LoginForm - component", () => {
password,
});
});
it("tabs in the expected order", async () => {
const { user } = renderWithSetup(
<LoginForm
handleSubmit={submitSpy}
isSubmitting={false}
pendingEmail={false}
ssoSettings={{
sso_enabled: true,
idp_name: "Test IdP",
}}
/>
);
expect(screen.getByPlaceholderText("Email")).toHaveFocus();
await user.tab();
expect(screen.getByPlaceholderText("Password")).toHaveFocus();
await user.tab();
expect(screen.getByText("Log in").parentElement).toHaveFocus();
await user.tab();
expect(
screen.getByText("Sign in with Test IdP").parentElement
).toHaveFocus();
await user.tab();
expect(screen.getByText("Forgot password?")).toHaveFocus();
});
});
@@ -84,28 +84,28 @@ const LoginForm = ({
const showLegendWithImage = () => {
let legend = "Single sign-on";
if (idpName !== "") {
if (idpName) {
legend = `Sign in with ${idpName}`;
}
return (
<div>
<>
<img
src={imageURL}
alt={idpName}
className={`${baseClass}__sso-image`}
/>
<span className={`${baseClass}__sso-legend`}>{legend}</span>
</div>
</>
);
};
const renderSingleSignOnButton = () => {
let legend: string | JSX.Element = "Single sign-on";
if (idpName !== "") {
if (idpName) {
legend = `Sign in with ${idpName}`;
}
if (imageURL !== "") {
if (imageURL) {
legend = showLegendWithImage();
}
@@ -116,8 +116,9 @@ const LoginForm = ({
title="Single sign-on"
variant="inverse"
onClick={handleSSOSignOn}
tabIndex={0}
>
<div>{legend}</div>
{legend}
</Button>
);
};
@@ -183,6 +184,7 @@ const LoginForm = ({
className={`${baseClass}__login-btn`}
isLoading={isSubmitting}
type="submit"
tabIndex={0}
>
Log in
</Button>