fix(充点弹窗): 方向键切换页签与档位后移动焦点

- PlatformRechargeTabNav 与 PlatformPointProductGrid 在方向键 / Home / End 改变选中项后,用 ref 把焦点移到新按钮,保持 roving tabindex 焦点与选中一致。
This commit is contained in:
2026-10-03 17:30:05 +08:00
parent 803d5ccb0a
commit cec4b7ec5e
@@ -2,7 +2,14 @@ import './index.css';
import QRCode from 'qrcode';
import type { ReactNode } from 'react';
import { useCallback, useEffect, useId, useMemo, useState } from 'react';
import {
useCallback,
useEffect,
useId,
useMemo,
useRef,
useState,
} from 'react';
import type {
ProfileMembership,
@@ -495,6 +502,8 @@ function PlatformRechargeTabNav({
{ id: 'subscription', label: '会员订阅' },
{ id: 'recharge', label: '泥点充值' },
];
// 方向键移动选中项后把焦点一并移到新页签,保持 roving tabindex 的焦点与选中一致。
const tabRefs = useRef<Record<string, HTMLButtonElement | null>>({});
return (
<div
@@ -519,6 +528,7 @@ function PlatformRechargeTabNav({
const nextTab = tabs[nextIndex];
if (nextTab) {
onChange(nextTab.id);
tabRefs.current[nextTab.id]?.focus();
}
}}
>
@@ -527,6 +537,9 @@ function PlatformRechargeTabNav({
return (
<button
key={tab.id}
ref={(node) => {
tabRefs.current[tab.id] = node;
}}
type="button"
role="tab"
id={`platform-recharge-tab-${tab.id}`}
@@ -823,6 +836,8 @@ function PlatformPointProductGrid({
submittingProductId: string | null;
onSelect: (product: ProfileRechargeProduct) => void;
}) {
// 方向键移动选中项后同步移动焦点,保持 roving tabindex 的焦点与选中一致。
const productRefs = useRef<Record<string, HTMLButtonElement | null>>({});
return (
<div
role="radiogroup"
@@ -848,6 +863,7 @@ function PlatformPointProductGrid({
const nextProduct = products[nextIndex];
if (nextProduct) {
onSelect(nextProduct);
productRefs.current[nextProduct.productId]?.focus();
}
}}
>
@@ -857,6 +873,9 @@ function PlatformPointProductGrid({
return (
<button
key={product.productId}
ref={(node) => {
productRefs.current[product.productId] = node;
}}
type="button"
role="radio"
aria-checked={selected}