fix(frontend): make the panel usable with screen readers (#6907)

* fix(frontend): make the panel usable with screen readers

* fix(frontend): keep mobile tab names and the inbound expiry hint

Review of #6907 found two gaps in the screen-reader pass:

- On phone-width screens catTabLabel renders only the icon and names the
  tab by putting aria-label on it, but callers now pass that icon with
  aria-hidden for the desktop label, so every Settings, Xray and Host
  category tab lost its name under TalkBack. catTabLabel now clears
  aria-hidden on the icon it uses as the name.
- DateTimePicker forwarded id and aria-label but not aria-describedby,
  so the inbound expiry hint ("leave blank to never expire") was never
  attached. It now forwards it on both the Gregorian and Jalali input.
This commit is contained in:
Alireza Ahmadi
2026-10-23 18:29:47 +02:00
committed by GitHub
parent 775b2b0b26
commit e2184777a0
156 changed files with 2373 additions and 863 deletions
@@ -221,14 +221,14 @@ export default function DnsServerModal({
<Button
size="small"
type="primary"
icon={<PlusOutlined />}
icon={<PlusOutlined aria-hidden />}
aria-label={t('add')}
onClick={() => methods.setValue('domains', [...domains, ''])}
/>
{domains.map((_, i) => (
<Space.Compact key={i} block style={{ marginTop: 4 }}>
<FormField name={`domains.${i}`} noStyle>
<Input />
<Input aria-label={t('pages.xray.dns.domains')} />
</FormField>
<InputAddon
ariaLabel={t('remove')}
@@ -239,7 +239,7 @@ export default function DnsServerModal({
)
}
>
<MinusOutlined />
<MinusOutlined aria-hidden />
</InputAddon>
</Space.Compact>
))}
@@ -249,14 +249,14 @@ export default function DnsServerModal({
<Button
size="small"
type="primary"
icon={<PlusOutlined />}
icon={<PlusOutlined aria-hidden />}
aria-label={t('add')}
onClick={() => methods.setValue('expectedIPs', [...expectedIPs, ''])}
/>
{expectedIPs.map((_, i) => (
<Space.Compact key={i} block style={{ marginTop: 4 }}>
<FormField name={`expectedIPs.${i}`} noStyle>
<Input />
<Input aria-label={t('pages.xray.dns.expectIPs')} />
</FormField>
<InputAddon
ariaLabel={t('remove')}
@@ -267,7 +267,7 @@ export default function DnsServerModal({
)
}
>
<MinusOutlined />
<MinusOutlined aria-hidden />
</InputAddon>
</Space.Compact>
))}
@@ -277,14 +277,14 @@ export default function DnsServerModal({
<Button
size="small"
type="primary"
icon={<PlusOutlined />}
icon={<PlusOutlined aria-hidden />}
aria-label={t('add')}
onClick={() => methods.setValue('unexpectedIPs', [...unexpectedIPs, ''])}
/>
{unexpectedIPs.map((_, i) => (
<Space.Compact key={i} block style={{ marginTop: 4 }}>
<FormField name={`unexpectedIPs.${i}`} noStyle>
<Input />
<Input aria-label={t('pages.xray.dns.unexpectIPs')} />
</FormField>
<InputAddon
ariaLabel={t('remove')}
@@ -295,7 +295,7 @@ export default function DnsServerModal({
)
}
>
<MinusOutlined />
<MinusOutlined aria-hidden />
</InputAddon>
</Space.Compact>
))}