mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-03 03:35:04 +03:00
1bdb517b88
Ant Design's Spin wraps its content in aria-live="polite", so every WebSocket tick on the dashboard, inbounds, clients and nodes pages was announced, and only the changed number was read, with no label. Pass aria-live="off" on every Spin that wraps content; aria-busy still signals loading. Each vital tile is now a group named by its metric, so "47.2 %" is read as CPU. rc-select renders each tag's remove "x" as an aria-hidden span with no tabIndex, so screen-reader users could only Backspace the last value away, never remove one SNI or inbound from the middle. selectTagRender swaps in a real button named "Remove <value>" and moves focus to the next tag after removal. It is applied to every tags/multiple Select. maxTagCount="responsive" is dropped because it hid selected inbounds behind "+N", where no screen reader could reach them. Two oxlint rules (antd-a11y/spin-content-not-live and antd-a11y/select-tag-remove) keep new code from regressing either fix.
103 lines
2.5 KiB
JSON
103 lines
2.5 KiB
JSON
{
|
|
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
|
"ignorePatterns": [
|
|
"node_modules/**"
|
|
],
|
|
"plugins": [
|
|
"typescript",
|
|
"react",
|
|
"jsx-a11y"
|
|
],
|
|
"jsPlugins": [
|
|
"./tools/oxlint/input-number-guard.mjs",
|
|
"./tools/oxlint/control-label-guard.mjs",
|
|
"./tools/oxlint/icon-a11y-guard.mjs",
|
|
"./tools/oxlint/antd-a11y-guard.mjs"
|
|
],
|
|
"categories": {
|
|
"correctness": "error"
|
|
},
|
|
"env": {
|
|
"browser": true,
|
|
"es2022": true
|
|
},
|
|
"rules": {
|
|
"typescript/no-explicit-any": "error",
|
|
"typescript/no-unused-vars": [
|
|
"warn",
|
|
{
|
|
"argsIgnorePattern": "^_",
|
|
"varsIgnorePattern": "^_",
|
|
"caughtErrorsIgnorePattern": "^_"
|
|
}
|
|
],
|
|
"typescript/ban-ts-comment": "error",
|
|
"typescript/no-empty-object-type": "error",
|
|
"typescript/no-namespace": "error",
|
|
"typescript/no-require-imports": "error",
|
|
"typescript/no-this-alias": "error",
|
|
"typescript/no-unsafe-function-type": "error",
|
|
"typescript/no-unused-expressions": "warn",
|
|
"typescript/no-wrapper-object-types": "error",
|
|
"typescript/prefer-as-const": "error",
|
|
"typescript/triple-slash-reference": "error",
|
|
"no-empty": [
|
|
"error",
|
|
{
|
|
"allowEmptyCatch": true
|
|
}
|
|
],
|
|
"react-hooks/rules-of-hooks": "error",
|
|
"react-hooks/exhaustive-deps": "error",
|
|
"jsx-a11y/no-autofocus": "off",
|
|
"input-number/no-synthetic-clear": "off",
|
|
"jsx-a11y/prefer-tag-over-role": "off",
|
|
"control-label/has-name": "off",
|
|
"antd-icon/explicit-a11y": "off",
|
|
"antd-a11y/spin-content-not-live": "off",
|
|
"antd-a11y/select-tag-remove": "off"
|
|
},
|
|
"overrides": [
|
|
{
|
|
"files": [
|
|
"src/pages/settings/**/*.tsx",
|
|
"src/pages/xray/**/*.tsx"
|
|
],
|
|
"rules": {
|
|
"input-number/no-synthetic-clear": "error"
|
|
}
|
|
},
|
|
{
|
|
"files": [
|
|
"src/pages/xray/**/*Modal.tsx"
|
|
],
|
|
"rules": {
|
|
"input-number/no-synthetic-clear": "off"
|
|
}
|
|
},
|
|
{
|
|
"files": [
|
|
"src/**/*.tsx"
|
|
],
|
|
"rules": {
|
|
"control-label/has-name": "error",
|
|
"antd-icon/explicit-a11y": "error",
|
|
"antd-a11y/spin-content-not-live": "error",
|
|
"antd-a11y/select-tag-remove": "error"
|
|
}
|
|
},
|
|
{
|
|
"files": [
|
|
"src/**/*.stories.tsx",
|
|
"src/test/**"
|
|
],
|
|
"rules": {
|
|
"control-label/has-name": "off",
|
|
"antd-icon/explicit-a11y": "off",
|
|
"antd-a11y/spin-content-not-live": "off",
|
|
"antd-a11y/select-tag-remove": "off"
|
|
}
|
|
}
|
|
]
|
|
}
|