diff --git a/docs/gates.md b/docs/gates.md index 835997c4..651e4d34 100644 --- a/docs/gates.md +++ b/docs/gates.md @@ -56,9 +56,7 @@ them itself (`no-undef`, `no-redeclare`, `no-dupe-keys`, …), nor the formattin | lib/http.ts | `no-restricted-globals` — narrowed | A network owner (`NETWORK_OWNERS` in eslint.config.js): the one module that may call `fetch` (`send`, which `req` and the public pages go through). Every other network global stays restricted there. | 1 global | | lib/api/core.ts | `no-restricted-globals` — narrowed | A network owner: `uploadReq` is the one `XMLHttpRequest` (upload progress). | 1 global | | src tests · ui tests · lib tests | `no-restricted-globals`, `no-restricted-properties` — off | A test stands a double in for the network (`vi.stubGlobal("fetch", …)`) and may reach it directly. | — | -| src tests · ui tests · lib tests | `local/literal-a11y-text`, `local/button-primitive`, `local/input-primitive`, `local/surface-role`, `local/glyph-link` — off | A test renders throwaway markup (a raw button as a focus target, an untranslated label) that is not product UI. | — | -| FocusSafeButton.tsx + AnchoredPopover.tsx | `local/focus-safe-disabled` — off | FocusSafeButton: it IS the focus-safe primitive the rule points everyone else to. | — | -| FocusSafeButton.tsx + AnchoredPopover.tsx | `local/focus-safe-disabled` — off | AnchoredPopover: the popover's menu row: its native `disabled` is what floating-ui's roving focus reads to skip it. | — | +| src tests · ui tests · lib tests | `local/literal-a11y-text`, `local/input-primitive`, `local/surface-role`, `local/glyph-link` — off | A test renders throwaway markup (a raw input as a focus target, an untranslated label) that is not product UI. `local/button-primitive` stays on: in a test file (and in a control primitive) it only refuses a raw `;\n"; + describe("a raw button that can be disabled", () => { it("is refused, statically or not", async () => { expect( @@ -20,13 +23,15 @@ describe("a raw button that can be disabled", () => { expect(await hits("export const B = () => ;\n")).toBe(1); }); - it("leaves a raw button with no disabled, and the primitive, alone", async () => { + it("is refused inside a control primitive and in a test too", async () => { + expect(await hits(DISABLED, "src/components/ui/Button.tsx")).toBe(1); + // an existing test file: the project service admits only lintProbe.testkit's probe names + expect(await hits(DISABLED, "src/components/Feed.countStale.dom.test.tsx")).toBe(1); + }); + + it("leaves a raw button with no disabled, and the two native-disabled owners, alone", async () => { expect(await hits("export const C = () => ;\n")).toBe(0); - expect( - await hits( - "export const D = (p: { d: boolean }) => ;\n", - "src/components/ui/FocusSafeButton.tsx", - ), - ).toBe(0); + expect(await hits(DISABLED, "src/components/ui/FocusSafeButton.tsx")).toBe(0); + expect(await hits(DISABLED, "src/components/ui/AnchoredPopover.tsx")).toBe(0); }); }); diff --git a/frontend/src/lib/gates.snapshot.json b/frontend/src/lib/gates.snapshot.json index b311c0f0..46fe0b2a 100644 --- a/frontend/src/lib/gates.snapshot.json +++ b/frontend/src/lib/gates.snapshot.json @@ -1,48 +1,6 @@ { "eslint": { "configs": { - "FocusSafeButton.tsx + AnchoredPopover.tsx": { - "languageOptions": { - "ecmaVersion": 2022, - "globals": "1169 names, sha1 aee621727a03", - "parser": "typescript-eslint/parser", - "parserOptions": { "projectService": true, "tsconfigRootDir": "." }, - "sourceType": "module" - }, - "linterOptions": { "reportUnusedDisableDirectives": 2 }, - "notApplied": [], - "plugins": [ - "@", - "@eslint-community/eslint-comments", - "@typescript-eslint", - "local", - "react-hooks", - "react-refresh" - ], - "rules": { - "local/focus-safe-disabled": [0], - "no-restricted-imports": [ - 2, - { - "patterns": [ - { - "message": "components/ui/ is domain-free: a platform component may not import a feature component. Invert the dependency (take a prop/render-prop) or keep the component outside ui/.", - "regex": "^\\.\\./(?!\\.\\./)" - }, - { - "message": "components/ui/ is domain-free: a platform component may not import a feature component. Invert the dependency (take a prop/render-prop) or keep the component outside ui/.", - "regex": "^\\.\\./\\.\\./components/(?!ui/)" - }, - { - "message": "components/ui/ is domain-free: a platform component may not call a domain API slice. Take the data as props.", - "regex": "^\\.\\./\\.\\./lib/api(/|$)" - } - ] - } - ] - }, - "settings": null - }, "design-lab": { "languageOptions": { "ecmaVersion": 2022, @@ -75,7 +33,6 @@ "linterOptions": { "reportUnusedDisableDirectives": 2 }, "notApplied": [ "local/button-primitive", - "local/focus-safe-disabled", "local/glyph-link", "local/input-primitive", "local/jsx-comment-text", @@ -158,7 +115,6 @@ "@typescript-eslint/prefer-namespace-keyword", "@typescript-eslint/triple-slash-reference", "local/button-primitive", - "local/focus-safe-disabled", "local/glyph-link", "local/input-primitive", "local/jsx-comment-text", @@ -248,7 +204,6 @@ "vitest" ], "rules": { - "local/button-primitive": [0], "local/glyph-link": [0], "local/input-primitive": [0], "local/literal-a11y-text": [0], @@ -711,7 +666,6 @@ "linebreak-style": [0], "lines-around-comment": [0], "local/button-primitive": [2], - "local/focus-safe-disabled": [2], "local/glyph-link": [2], "local/input-primitive": [2], "local/jsx-comment-text": [2], @@ -1062,7 +1016,6 @@ "vitest" ], "rules": { - "local/button-primitive": [0], "local/glyph-link": [0], "local/input-primitive": [0], "local/literal-a11y-text": [0], @@ -1153,7 +1106,6 @@ "linterOptions": { "reportUnusedDisableDirectives": 2 }, "notApplied": [ "local/button-primitive", - "local/focus-safe-disabled", "local/glyph-link", "local/input-primitive", "local/jsx-comment-text", @@ -1262,7 +1214,6 @@ "vitest" ], "rules": { - "local/button-primitive": [0], "local/glyph-link": [0], "local/input-primitive": [0], "local/literal-a11y-text": [0], @@ -1331,10 +1282,6 @@ }, "files": { "(not linted)": [], - "FocusSafeButton.tsx + AnchoredPopover.tsx": [ - "src/components/ui/AnchoredPopover.tsx", - "src/components/ui/FocusSafeButton.tsx" - ], "design-lab": [ "src/design-lab/DesignLab.tsx", "src/design-lab/batchA.tsx", @@ -1959,6 +1906,7 @@ ], "ui": [ "src/components/ui/ActionMenu.tsx", + "src/components/ui/AnchoredPopover.tsx", "src/components/ui/Avatar.tsx", "src/components/ui/BackToTop.tsx", "src/components/ui/Badge.tsx", @@ -1978,6 +1926,7 @@ "src/components/ui/FilterChipGroup.tsx", "src/components/ui/FilterFold.tsx", "src/components/ui/FilterSelect.tsx", + "src/components/ui/FocusSafeButton.tsx", "src/components/ui/Headings.tsx", "src/components/ui/HiddenFilterCue.tsx", "src/components/ui/IconButton.tsx",