id: window-in-render-direct
language: tsx
severity: error
message: window/document accessed during React render — SSR crash
note: '{"severity":"medium","category":"convention","resolution":"Move into useEffect/useLayoutEffect, an event handler, or guard with typeof window !== \"undefined\"."}'
files:
  - '**/src/components/**'
  - '**/src/features/**'
  - '**/fixtures/src/components/**'
ignores:
  - '**/features/design-system/**'
  - '**/*.test.ts'
  - '**/*.test.tsx'
rule:
  any:
    - all:
        - pattern: window.$PROP
        - inside:
            stopBy: end
            kind: function_declaration
            has:
              field: name
              regex: '^[A-Z]'
    - all:
        - pattern: document.$PROP
        - inside:
            stopBy: end
            kind: function_declaration
            has:
              field: name
              regex: '^[A-Z]'
    - all:
        - pattern: window.$PROP
        - inside:
            stopBy: end
            all:
              - kind: arrow_function
              - not:
                  has:
                    kind: variable_declarator
                    has:
                      field: name
                      regex: '^[A-Z]'
    - all:
        - pattern: document.$PROP
        - inside:
            stopBy: end
            all:
              - kind: arrow_function
              - not:
                  has:
                    kind: variable_declarator
                    has:
                      field: name
                      regex: '^[A-Z]'
    - all:
        - pattern: window.$PROP
        - inside:
            stopBy: end
            all:
              - kind: function_expression
              - not:
                  has:
                    kind: variable_declarator
                    has:
                      field: name
                      regex: '^[A-Z]'
    - all:
        - pattern: document.$PROP
        - inside:
            stopBy: end
            all:
              - kind: function_expression
              - not:
                  has:
                    kind: variable_declarator
                    has:
                      field: name
                      regex: '^[A-Z]'
  not:
    any:
      - inside:
          stopBy: end
          all:
            - kind: arrow_function
            - not:
                inside:
                  stopBy: neighbor
                  kind: variable_declarator
                  has:
                    field: name
                    regex: '^[A-Z]'
      - inside:
          stopBy: end
          all:
            - kind: function_expression
            - not:
                inside:
                  stopBy: neighbor
                  kind: variable_declarator
                  has:
                    field: name
                    regex: '^[A-Z]'
      - inside:
          stopBy: end
          kind: function_declaration
          has:
            field: name
            regex: '^[a-z]'
      - inside:
          stopBy: end
          pattern: useEffect($$$)
      - inside:
          stopBy: end
          pattern: useLayoutEffect($$$)
      - inside:
          stopBy: end
          kind: jsx_attribute
      - inside:
          stopBy: end
          pattern: typeof window
      - inside:
          stopBy: end
          kind: variable_declarator
          has:
            field: name
            regex: ^(handle|on)[A-Z]
