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
@@ -32,7 +32,13 @@ export default function FallbacksCard({
const addButtons = (
<Space size={8} wrap>
<Button type="primary" ghost size="small" icon={<PlusOutlined />} onClick={addFallback}>
<Button
type="primary"
ghost
size="small"
icon={<PlusOutlined aria-hidden />}
onClick={addFallback}
>
{t('pages.inbounds.fallbacks.add') || 'Add fallback'}
</Button>
<Button
@@ -90,25 +96,26 @@ export default function FallbacksCard({
disabled={idx === 0}
onClick={() => moveFallback(idx, -1)}
title={t('pages.inbounds.form.moveUp')}
icon={<ArrowUpOutlined />}
icon={<ArrowUpOutlined aria-hidden />}
/>
<Button
aria-label={t('pages.inbounds.form.moveDown')}
disabled={idx === fallbacks.length - 1}
onClick={() => moveFallback(idx, 1)}
title={t('pages.inbounds.form.moveDown')}
icon={<ArrowDownOutlined />}
icon={<ArrowDownOutlined aria-hidden />}
/>
<Button
aria-label={t('delete')}
danger
onClick={() => removeFallback(idx)}
icon={<DeleteOutlined />}
icon={<DeleteOutlined aria-hidden />}
/>
</Space.Compact>
<Row gutter={[8, 8]}>
<Col xs={24} sm={12}>
<Input
aria-label="SNI"
prefix="SNI"
placeholder={t('pages.inbounds.fallbacks.matchAny') || 'any'}
value={record.name}
@@ -117,6 +124,7 @@ export default function FallbacksCard({
</Col>
<Col xs={24} sm={12}>
<Input
aria-label="ALPN"
prefix="ALPN"
placeholder={t('pages.inbounds.fallbacks.matchAny') || 'any'}
value={record.alpn}
@@ -125,6 +133,7 @@ export default function FallbacksCard({
</Col>
<Col xs={24} sm={12}>
<Input
aria-label="Path"
prefix="Path"
placeholder="/"
value={record.path}
@@ -133,6 +142,7 @@ export default function FallbacksCard({
</Col>
<Col xs={24} sm={12}>
<Input
aria-label="Dest"
prefix="Dest"
placeholder={t('pages.inbounds.fallbacks.destPlaceholder') || 'auto'}
value={record.dest}
@@ -141,6 +151,7 @@ export default function FallbacksCard({
</Col>
<Col xs={24} sm={12}>
<InputNumber
aria-label="xver"
prefix="xver"
min={0}
max={2}