mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-06 21:25:04 +03:00
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:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useEffect, useId, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
AutoComplete,
|
||||
@@ -82,6 +82,7 @@ export default function ClientBulkAddModal({
|
||||
onSaved,
|
||||
}: ClientBulkAddModalProps) {
|
||||
const { t } = useTranslation();
|
||||
const uid = useId();
|
||||
const [messageApi, messageContextHolder] = message.useMessage();
|
||||
const { bulkCreate } = useClients({ list: false });
|
||||
|
||||
@@ -254,13 +255,18 @@ export default function ClientBulkAddModal({
|
||||
>
|
||||
<FormProvider {...methods}>
|
||||
<Form colon={false} labelCol={{ sm: { span: 8 } }} wrapperCol={{ sm: { span: 14 } }}>
|
||||
<Form.Item label={t('pages.clients.attachedInbounds')} required>
|
||||
<Form.Item
|
||||
label={t('pages.clients.attachedInbounds')}
|
||||
required
|
||||
htmlFor={`${uid}-inbounds`}
|
||||
>
|
||||
<SelectAllClearButtons
|
||||
options={inboundOptions}
|
||||
value={inboundIds}
|
||||
onChange={(v) => methods.setValue('inboundIds', v)}
|
||||
/>
|
||||
<Select
|
||||
id={`${uid}-inbounds`}
|
||||
mode="multiple"
|
||||
value={inboundIds}
|
||||
onChange={(v) => methods.setValue('inboundIds', v)}
|
||||
@@ -323,16 +329,17 @@ export default function ClientBulkAddModal({
|
||||
</FormField>
|
||||
)}
|
||||
|
||||
<Form.Item label={t('pages.clients.subId')}>
|
||||
<Form.Item label={t('pages.clients.subId')} htmlFor={`${uid}-sub-id`}>
|
||||
<Space.Compact style={{ display: 'flex' }}>
|
||||
<Input
|
||||
id={`${uid}-sub-id`}
|
||||
value={subId}
|
||||
onChange={(e) => methods.setValue('subId', e.target.value)}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
<Button
|
||||
aria-label={t('regenerate')}
|
||||
icon={<ReloadOutlined />}
|
||||
icon={<ReloadOutlined aria-hidden />}
|
||||
onClick={() => methods.setValue('subId', RandomUtil.randomLowerAndNum(16))}
|
||||
/>
|
||||
</Space.Compact>
|
||||
@@ -376,10 +383,11 @@ export default function ClientBulkAddModal({
|
||||
</FormField>
|
||||
)}
|
||||
|
||||
<Form.Item label={t('pages.clients.limitIp')}>
|
||||
<Form.Item label={t('pages.clients.limitIp')} htmlFor={`${uid}-limit-ip`}>
|
||||
<Tooltip title={limitIpNotice || undefined}>
|
||||
<span style={{ display: 'inline-flex' }}>
|
||||
<InputNumber
|
||||
id={`${uid}-limit-ip`}
|
||||
value={limitIp}
|
||||
min={0}
|
||||
disabled={limitIpDisabled}
|
||||
@@ -399,8 +407,9 @@ export default function ClientBulkAddModal({
|
||||
<InputNumber min={0} step={1} />
|
||||
</FormField>
|
||||
|
||||
<Form.Item label={t('pages.clients.delayedStart')}>
|
||||
<Form.Item label={t('pages.clients.delayedStart')} htmlFor={`${uid}-delayed-start`}>
|
||||
<Switch
|
||||
id={`${uid}-delayed-start`}
|
||||
checked={delayedStart}
|
||||
onClick={() => {
|
||||
setDelayedStart(!delayedStart);
|
||||
@@ -410,16 +419,18 @@ export default function ClientBulkAddModal({
|
||||
</Form.Item>
|
||||
|
||||
{delayedStart ? (
|
||||
<Form.Item label={t('pages.clients.expireDays')}>
|
||||
<Form.Item label={t('pages.clients.expireDays')} htmlFor={`${uid}-expire-days`}>
|
||||
<InputNumber
|
||||
id={`${uid}-expire-days`}
|
||||
value={delayedExpireDays}
|
||||
min={0}
|
||||
onChange={(v) => methods.setValue('expiryTime', -86400000 * (Number(v) || 0))}
|
||||
/>
|
||||
</Form.Item>
|
||||
) : (
|
||||
<Form.Item label={t('pages.inbounds.expireDate')}>
|
||||
<Form.Item label={t('pages.inbounds.expireDate')} htmlFor={`${uid}-expiry`}>
|
||||
<DateTimePicker
|
||||
id={`${uid}-expiry`}
|
||||
value={expiryDate}
|
||||
onChange={(next) => methods.setValue('expiryTime', next ? next.valueOf() : 0)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user