-
Notifications
You must be signed in to change notification settings - Fork 163
Configure Identity Providers in the UI #523
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 33 commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
4328635
Add user creation with password copy
braginini 153c795
Add initial identity provider view
braginini 2131c06
Add IdP logos
braginini 205573f
Add IdP id to user
braginini 0761955
Add IdP logo to user obj
braginini 9271f6d
Fix okta icon
braginini f14ef91
Return callback URL when creating an IdP
braginini 876f803
Create user for self-hosted
braginini a38d364
Merge branch 'feature/user-invite-password' into feature/identity-pro…
braginini 92528d8
Clear up password from the state
braginini cdbd9ba
Merge branch 'feature/user-invite-password' into feature/identity-pro…
braginini 07f538b
Show IdPs and create user when enabled
braginini cb93781
Merge branch 'main' into feature/identity-providers
braginini ee18fab
Fetch IdPs only when embedded idp is enabled
braginini 561826f
Update src/app/(dashboard)/settings/page.tsx
braginini 34214df
Update src/app/(dashboard)/settings/page.tsx
braginini 46d95ff
Update src/modules/settings/IdentityProvidersTab.tsx
braginini 7775709
Update src/modules/settings/IdentityProviderModal.tsx
braginini 375c60b
Update src/modules/settings/IdentityProvidersTab.tsx
braginini 4b6c02c
Update src/modules/settings/IdentityProviderModal.tsx
braginini 0dd2f2e
Rename IdentityProvider to SSOIdentityProvider
braginini ed579f1
Fix build and extract icons
braginini 9f830e8
Fix initial onboarding
braginini b961966
Add icons
braginini 90a0ed6
Move name to the top
braginini 506fb65
Fix setup wizard background color
braginini fb003a9
Update instance setup ui
heisbrot b401a49
Update instance setup ui
heisbrot 99b4f0e
Use input component
heisbrot 6adc5b2
Move idp label and icons
heisbrot 02dce01
Fix setup wizard width
braginini 5826b3f
Add authentik and keycloak
braginini aec7364
Add idp hints
braginini 32eef30
Handle idp permissions
braginini 3c6dc92
Consider selfhosted instances when checking if netbird is hosted
braginini 49cf8fc
Update redirect
heisbrot b0b253f
Add max retries to redirect
heisbrot 340fe18
Require new secret when clientid changed
braginini 2324d53
Add callback URL on the idp creation step
braginini 9270b60
Add idp activity events
braginini File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import { globalMetaTitle } from "@utils/meta"; | ||
| import type { Metadata } from "next"; | ||
| import BlankLayout from "@/layouts/BlankLayout"; | ||
|
|
||
| export const metadata: Metadata = { | ||
| title: `Instance Setup - ${globalMetaTitle}`, | ||
| }; | ||
| export default BlankLayout; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| "use client"; | ||
|
|
||
| import InstanceSetupWizard from "@/modules/instance-setup/InstanceSetupWizard"; | ||
|
|
||
| export default function SetupPage() { | ||
| return <InstanceSetupWizard />; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| import { iconProperties, IconProps } from "@/assets/icons/IconProperties"; | ||
|
|
||
| export default function AuthentikIcon(props: Readonly<IconProps>) { | ||
| return ( | ||
| <svg | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| viewBox="-0.03 59.9 512.03 392.1" | ||
| {...iconProperties(props)} | ||
| > | ||
| <path | ||
| d="M279.9 141h17.9v51.2h-17.9zm46.6-2.2h17.9v40h-17.9zM65.3 197.3c-24 0-46 13.2-57.4 34.3h30.4c13.5-11.6 33-15 47.1 0h32.2c-12.6-17.1-31.4-34.3-52.3-34.3" | ||
| fill="#fd4b2d" | ||
| /> | ||
| <path | ||
| d="M108.7 262.4C66.8 350-6.6 275.3 38.3 231.5H7.9C-15.9 273 17 329 65.3 327.8c37.4 0 68.2-55.5 68.2-65.3 0-4.3-6-17.6-16-31H85.4c10.7 9.7 20 23.7 23.3 30.9m1.1-2.6" | ||
| fill="#fd4b2d" | ||
| /> | ||
| <path | ||
| d="M512 140.3v231.3c0 44.3-36.1 80.4-80.4 80.4h-34.1v-78.8h-163V452h-34.1c-44.4 0-80.4-36.1-80.4-80.4v-72.8h258.4v-139H253.6V238H119.9v-97.6c0-3.1.2-6.2.5-9.2.4-3.7 1.1-7.3 2-10.8.3-1.1.6-2.3 1-3.4.1-.3.2-.6.3-.8.2-.6.4-1.1.5-1.7.2-.5.4-1.1.6-1.7s.5-1.2.7-1.8.5-1.2.8-1.8c2-4.7 4.4-9.3 7.3-13.6l.1-.1c.7-1.1 1.5-2.1 2.3-3.2.7-.9 1.3-1.7 2-2.6.8-.9 1.6-1.9 2.4-2.8s1.6-1.8 2.4-2.6l.1-.1c.4-.5.9-.9 1.4-1.4 3-2.9 6.2-5.6 9.6-8 .9-.7 1.9-1.3 2.8-1.9 1.1-.7 2.2-1.4 3.3-2 2.1-1.2 4.2-2.4 6.5-3.4.7-.3 1.4-.7 2.1-1 3.1-1.3 6.2-2.5 9.4-3.4 1.2-.4 2.5-.7 3.7-1 .6-.2 1.2-.3 1.8-.4 3.6-.8 7.2-1.3 10.9-1.6l1.6-.1h.8c1.2-.1 2.4-.1 3.7-.1h231.3c1.2 0 2.5 0 3.7.1h.8l1.6.1c3.7.3 7.3.8 10.9 1.6.6.1 1.2.3 1.8.4 1.3.3 2.5.6 3.7 1 3.2.9 6.3 2.1 9.4 3.4.7.3 1.4.6 2.1 1 2.2 1 4.4 2.2 6.5 3.4 1.1.7 2.2 1.3 3.3 2 1 .6 1.9 1.3 2.8 1.9 3.9 2.8 7.6 6 11 9.4.8.8 1.7 1.7 2.4 2.6.8.9 1.6 1.9 2.4 2.8.7.8 1.3 1.7 2 2.6.8 1.1 1.5 2.1 2.3 3.2l.1.1c2.9 4.3 5.3 8.8 7.3 13.6.2.6.5 1.2.8 1.8.2.6.5 1.2.7 1.8.2.5.4 1.1.6 1.7s.4 1.1.5 1.7c.1.3.2.6.3.8.3 1.1.7 2.3 1 3.4.9 3.6 1.6 7.2 2 10.8 0 3.1.2 6.1.2 9.2" | ||
| fill="#fd4b2d" | ||
| /> | ||
| <path | ||
| d="M498.3 95.5H133.5c14.9-22.2 40-35.6 66.7-35.6h231.3c26.9 0 51.9 13.4 66.8 35.6m13.2 35.6H120.4c1.4-12.8 6-25 13.1-35.6h364.8c7.2 10.6 11.7 22.9 13.2 35.6m.5 9.2v26.4H378.3v-6.9H253.6v6.9H119.9v-26.4c0-3.1.2-6.2.5-9.2h391.1c.3 3.1.5 6.1.5 9.2M119.9 166.7h133.7v35.6H119.9zm258.4 0H512v35.6H378.3zm-258.4 35.6h133.7v35.6H119.9zm258.4 0H512v35.6H378.3z" | ||
| fill="#fd4b2d" | ||
| /> | ||
| </svg> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import { SSOIdentityProviderType } from "@/interfaces/IdentityProvider"; | ||
| import React from "react"; | ||
| import GoogleIcon from "@/assets/icons/GoogleIcon"; | ||
| import MicrosoftIcon from "@/assets/icons/MicrosoftIcon"; | ||
| import EntraIcon from "@/assets/icons/EntraIcon"; | ||
| import OktaIcon from "@/assets/icons/OktaIcon"; | ||
| import PocketIdIcon from "@/assets/icons/PocketIdIcon"; | ||
| import ZitadelIcon from "@/assets/icons/ZitadelIcon"; | ||
| import AuthentikIcon from "@/assets/icons/AuthentikIcon"; | ||
| import KeycloakIcon from "@/assets/icons/KeycloakIcon"; | ||
| import { KeyRound } from "lucide-react"; | ||
|
|
||
| export const idpIcon = ( | ||
| type: SSOIdentityProviderType, | ||
| size: number = 16, | ||
| ): React.ReactNode => { | ||
| const icons: Record<SSOIdentityProviderType, React.ReactNode> = { | ||
| google: <GoogleIcon size={size} />, | ||
| microsoft: <MicrosoftIcon size={size} />, | ||
| entra: <EntraIcon size={size} />, | ||
| okta: <OktaIcon size={size} className="text-nb-gray-300" />, | ||
| pocketid: <PocketIdIcon size={size} />, | ||
| zitadel: <ZitadelIcon size={size} />, | ||
| authentik: <AuthentikIcon size={size} />, | ||
| keycloak: <KeycloakIcon size={size} />, | ||
| oidc: <KeyRound size={size} className="text-nb-gray-400" />, | ||
| }; | ||
|
|
||
| return icons[type]; | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| import { iconProperties, IconProps } from "@/assets/icons/IconProperties"; | ||
|
|
||
| export default function KeycloakIcon(props: Readonly<IconProps>) { | ||
| return ( | ||
| <svg | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| viewBox="0 0 512 512" | ||
| {...iconProperties(props)} | ||
| > | ||
| <g transform="translate(.714 .07)"> | ||
| <path | ||
| d="M432.9 149.2c-1.4 0-2.7-.7-3.4-2L370.1 44.1c-.7-1.2-2-2-3.5-2H124.2c-1.4 0-2.7.7-3.4 2L58.9 150.9l23.9 34.9c-.7 1.2-6.2 24-5.5 25.2L58.9 360.9l61.9 106.9c.7 1.2 2 2 3.4 2h242.4c1.4 0 2.7-.7 3.5-2l59.4-103.2c.7-1.2 2-2 3.4-2h73.8c2.4 0 4.4-2 4.4-4.4V153.6c0-2.4-2-4.4-4.4-4.4z" | ||
| fill="#4d4d4d" | ||
| /> | ||
| <path d="M72.7 245.3 6.4 269.4l-6.6-11.3c-.7-1.2-.7-2.7 0-3.9l30-52z" fill="#e1e1e1" /> | ||
| <path d="M511.3 258.3V309l-43.7-44.5z" fill="#c8c8c8" /> | ||
| <path | ||
| d="m467.5 264.5 43.7 44.5v49.6c0 2.4-2 4.4-4.4 4.4H456z" | ||
| fill="#c2c2c2" | ||
| /> | ||
| <path d="M467.5 264.5 456 362.9h-61.2l-18.5-44.7z" fill="#c7c7c7" /> | ||
| <path d="M511.3 211.2v47l-43.7 6.2z" fill="#cecece" /> | ||
| <path | ||
| d="M511.3 153.6v57.6l-43.7 53.2-33.1-115.3h72.2c2.4-.1 4.5 1.8 4.6 4.3z" | ||
| fill="#d3d3d3" | ||
| /> | ||
| <path d="M394.8 362.9h-32.3l-8.4-12 22.1-32.7z" fill="#c6c6c6" /> | ||
| <path d="m467.5 264.5-121.1-51.2 63.7-64.1h24.4z" fill="#d5d5d5" /> | ||
| <path d="m346.5 213.3 29.8 105 91.2-53.8z" fill="#d0d0d0" /> | ||
| <path d="m353.8 362.9.4-12 8.4 12z" fill="#bfbfbf" /> | ||
| <path d="m410.1 149.2-63.7 64.1-11.4-57.4 24.6-6.8h50.5z" fill="#d9d9d9" /> | ||
| <path d="m346.5 213.3-147 33.9 154.7 103.7z" fill="#d4d4d4" /> | ||
| <path d="m346.5 213.3 7.7 137.6 22.1-32.7z" fill="#d0d0d0" /> | ||
| <path d="m335 155.9-135.5 91.2 147-33.9z" fill="#d9d9d9" /> | ||
| <path d="m199.5 247.2-63.7 115.7H99.6L72.7 245.3z" fill="#d8d8d8" /> | ||
| <path | ||
| d="m134.3 149.2-61.5 96.1L57.3 155l2.2-3.8c.7-1.2 2-1.9 3.4-1.9z" | ||
| fill="#e2e2e2" | ||
| /> | ||
| <path | ||
| d="M99.6 362.9H62.7c-1.4 0-2.8-.8-3.5-2L6.4 269.4l66.4-24.1z" | ||
| fill="#d8d8d8" | ||
| /> | ||
| <path d="M29.9 202.1 57.1 155l15.7 90.3z" fill="#e4e4e4" /> | ||
| <path d="m335 155.9-40.8-6.8H159.4l40.1 98z" fill="#dedede" /> | ||
| <path d="m199.5 247.2-40.1-98h-25.1l-61.5 96.1z" fill="#dedede" /> | ||
| <path d="M324.7 362.9h29.1l.4-12z" fill="#c5c5c5" /> | ||
| <path d="M266.7 362.9h58l29.5-12-154.7-103.7 27.9 115.7z" fill="#d0d0d0" /> | ||
| <path d="m227.4 362.9-27.9-115.7-63.7 115.7z" fill="#d1d1d1" /> | ||
| <path d="m335.4 149.2-.4 6.8 24.6-6.8z" fill="#ddd" /> | ||
| <path d="m335 155.9-3.8-6.8h-37z" fill="#e3e3e3" /> | ||
| <path d="m335 155.9.4-6.8h-4.2z" fill="#e2e2e2" /> | ||
| <path | ||
| d="m223.9 151-59.7 103.4c-.3.5-.4 1.1-.4 1.7h-41.7l82-142q.75.45 1.2 1.2l18.6 32.3c.5 1.1.5 2.4 0 3.4" | ||
| fill="#00b8e3" | ||
| /> | ||
| <path | ||
| d="M223.8 364.9 205.3 397q-.45.75-1.2 1.2l-82-142.2h41.7c0 .6.1 1.1.4 1.6l59.6 103.2c.8 1.2.9 2.9 0 4.1" | ||
| fill="#33c6e9" | ||
| /> | ||
| <path | ||
| d="m204 114.2-82 141.9-20.6 35.6-19.6-34c-.3-.5-.4-1-.4-1.6s.1-1.2.4-1.7l19.9-34.4 60.4-104.5c.6-1.1 1.8-1.8 3-1.8h37.2c.6 0 1.2.2 1.7.5" | ||
| fill="#008aaa" | ||
| /> | ||
| <path | ||
| d="M204 398.2c-.5.3-1.1.5-1.8.5h-37.1c-1.3 0-2.4-.7-3-1.8l-55.2-95.6-5.5-9.5 20.6-35.6z" | ||
| fill="#00b8e3" | ||
| /> | ||
| <path | ||
| d="m368.9 256.1-82 142q-.75-.45-1.2-1.2L267 364.7c-.5-1-.5-2.3 0-3.3L326.7 258c.3-.5.5-1.2.5-1.8z" | ||
| fill="#008aaa" | ||
| /> | ||
| <path | ||
| d="M409.4 256.1c0 .6-.2 1.3-.5 1.8l-80.3 139.3c-.6 1-1.8 1.7-3 1.6h-37c-.6 0-1.2-.2-1.8-.5L368.9 256l20.6-35.6 19.5 33.8c.3.7.4 1.3.4 1.9" | ||
| fill="#00b8e3" | ||
| /> | ||
| <path | ||
| d="M368.9 256.1h-41.7c0-.6-.2-1.2-.5-1.8L267 151.2c-.6-1.1-.6-2.5 0-3.6l18.6-32.2q.45-.75 1.2-1.2z" | ||
| fill="#00b8e3" | ||
| /> | ||
| <path | ||
| d="m389.4 220.5-20.6 35.6-82-142c.6-.3 1.2-.5 1.8-.5h37.1c1.2 0 2.3.6 3 1.6z" | ||
| fill="#33c6e9" | ||
| /> | ||
| </g> | ||
| </svg> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import { iconProperties, IconProps } from "@/assets/icons/IconProperties"; | ||
|
|
||
| export default function MicrosoftIcon(props: Readonly<IconProps>) { | ||
| return ( | ||
| <svg | ||
| viewBox="0 0 221 221" | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| {...iconProperties(props)} | ||
| > | ||
| <path fill="#F1511B" d="M104.868 104.868H0V0h104.868z" /> | ||
| <path fill="#80CC28" d="M220.654 104.868H115.788V0h104.866z" /> | ||
| <path fill="#00ADEF" d="M104.865 220.695H0V115.828h104.865z" /> | ||
| <path fill="#FBBC09" d="M220.654 220.695H115.788V115.828h104.866z" /> | ||
| </svg> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import { iconProperties, IconProps } from "@/assets/icons/IconProperties"; | ||
|
|
||
| export default function PocketIdIcon(props: Readonly<IconProps>) { | ||
| return ( | ||
| <svg | ||
| viewBox="0 0 512 512" | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| {...iconProperties(props)} | ||
| > | ||
| <circle cx="256" cy="256" r="256" fill="#fff" /> | ||
| <path | ||
| d="M268.6 102.4c64.4 0 116.8 52.4 116.8 116.7 0 25.3-8 49.4-23 69.6-14.8 19.9-35 34.3-58.4 41.7l-6.5 2-15.5-76.2 4.3-2c14-6.7 23-21.1 23-36.6 0-22.4-18.2-40.6-40.6-40.6S228 195.2 228 217.6c0 15.5 9 29.8 23 36.6l4.2 2-25 153.4h-69.5V102.4z" | ||
| fill="#191919" | ||
| /> | ||
| </svg> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import { iconProperties, IconProps } from "@/assets/icons/IconProperties"; | ||
|
|
||
| export default function ZitadelIcon(props: Readonly<IconProps>) { | ||
| return ( | ||
| <svg | ||
| viewBox="0 0 80 79" | ||
| fill="none" | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| {...iconProperties(props)} | ||
| > | ||
| <defs> | ||
| <linearGradient | ||
| id="zitadel-grad" | ||
| x1="3.86" | ||
| x2="76.88" | ||
| y1="47.89" | ||
| y2="47.89" | ||
| gradientUnits="userSpaceOnUse" | ||
| > | ||
| <stop stopColor="#FF8F00" /> | ||
| <stop offset="1" stopColor="#FE00FF" /> | ||
| </linearGradient> | ||
| </defs> | ||
| <path | ||
| fill="url(#zitadel-grad)" | ||
| fillRule="evenodd" | ||
| d="M17.12 39.17l1.42 5.32-6.68 6.68 9.12 2.44 1.43 5.32-19.77-5.3L17.12 39.17zM58.82 22.41l-5.32-1.43-2.44-9.12-6.68 6.68-5.32-1.43 14.47-14.47 5.3 19.77zM52.65 67.11l3.89-3.89 9.12 2.44-2.44-9.12 3.9-3.9 5.29 19.77-19.76-5.3zM36.43 69.54l-1.18-12.07 8.23 2.21-7.05 9.86zM23 23.84l5.02 11.04 6.02-6.02L23 23.84zM69.32 36.2l-12.07-1.18 2.2 8.23 9.87-7.05z" | ||
| clipRule="evenodd" | ||
| /> | ||
| </svg> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical accessibility issues with the password toggle button.
The password toggle implementation has two major accessibility problems:
tabIndex={-1}excludes keyboard users from accessing the toggle. Keyboard-only users (e.g., those with motor disabilities) cannot toggle password visibility.aria-labelprevents screen reader users from understanding the button's purpose.These violations block users with disabilities from using a core feature.
🔎 Proposed accessibility fixes
const passwordToggle = isPasswordType && showPasswordToggle ? ( <button type="button" onClick={() => setShowPassword(!showPassword)} className="text-nb-gray-400 hover:text-nb-gray-200 transition-colors" - tabIndex={-1} + aria-label={showPassword ? "Hide password" : "Show password"} > {showPassword ? <EyeOff size={16} /> : <Eye size={16} />} </button> ) : null;Removing
tabIndex={-1}allows keyboard navigation, and addingaria-labelprovides screen reader context.📝 Committable suggestion
🤖 Prompt for AI Agents