Files
3x-ui/frontend/tools/oxlint/icon-a11y-guard.mjs
T
Alireza Ahmadi e2184777a0 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.
2026-10-23 18:29:47 +02:00

33 lines
1.2 KiB
JavaScript

// @ant-design/icons render role="img" aria-label="<icon-name>", so screen readers speak
// "plus", "question-circle" etc. in English inside every button and label (s-ui#1293).
const MESSAGE =
'Ant Design icon announces its English name; add aria-hidden if decorative, or aria-label with translated text.';
const EXPLICIT = new Set(['aria-hidden', 'aria-label', 'aria-labelledby']);
export default {
meta: { name: 'antd-icon' },
rules: {
'explicit-a11y': {
create(context) {
const icons = new Set();
return {
ImportDeclaration(node) {
if (node.source.value !== '@ant-design/icons') return;
for (const spec of node.specifiers) {
if (spec.type === 'ImportSpecifier') icons.add(spec.local.name);
}
},
JSXOpeningElement(node) {
if (node.name.type !== 'JSXIdentifier' || !icons.has(node.name.name)) return;
const explicit = node.attributes.some(
(attr) => attr.type !== 'JSXAttribute' || EXPLICIT.has(attr.name.name),
);
if (!explicit) context.report({ node, message: MESSAGE });
},
};
},
},
},
};