diff --git a/app/(tools)/jwt-decoder/JwtDecoderClient.tsx b/app/(tools)/jwt-decoder/JwtDecoderClient.tsx index b5b9e80..bc8b10d 100644 --- a/app/(tools)/jwt-decoder/JwtDecoderClient.tsx +++ b/app/(tools)/jwt-decoder/JwtDecoderClient.tsx @@ -37,8 +37,12 @@ import { cn } from "@/lib/cn"; type TabId = "decode" | "encode"; +const TAB_IDS: TabId[] = ["decode", "encode"]; + export function JwtDecoderClient() { const [tab, setTab] = useState("decode"); + const tablistRef = useRef(null); + const [token, setToken] = useState(""); const [error, setError] = useState(null); const [decoded, setDecoded] = useState(null); @@ -97,6 +101,18 @@ export function JwtDecoderClient() { push("Could not copy link", "error"); } }, [token, push]); + function onTabKeyDown(e: React.KeyboardEvent, index: number) { + let next = index; + if (e.key === "ArrowRight") next = (index + 1) % TAB_IDS.length; + else if (e.key === "ArrowLeft") next = (index - 1 + TAB_IDS.length) % TAB_IDS.length; + else if (e.key === "Home") next = 0; + else if (e.key === "End") next = TAB_IDS.length - 1; + else return; + e.preventDefault(); + setTab(TAB_IDS[next]!); + const btns = tablistRef.current?.querySelectorAll('[role="tab"]'); + btns?.[next]?.focus(); + } const downloadJson = useCallback(() => { if (!decoded) return; @@ -141,12 +157,29 @@ export function JwtDecoderClient() { return ( <>
-
- setTab("decode")}> +
+ setTab("decode")} + onKeyDown={(e) => onTabKeyDown(e, 0)} + > Decode - setTab("encode")}> + setTab("encode")} + onKeyDown={(e) => onTabKeyDown(e, 1)} + > Encode @@ -155,7 +188,12 @@ export function JwtDecoderClient() { {tab === "decode" && ( <> -
+
@@ -215,6 +253,7 @@ export function JwtDecoderClient() {