Skip to content

Stand up ESLint with a TypeScript + react-hooks baseline - #130

Merged
finnar-bin merged 3 commits into
mainfrom
chore/128-add-eslint
Sep 3, 2026
Merged

Stand up ESLint with a TypeScript + react-hooks baseline#130
finnar-bin merged 3 commits into
mainfrom
chore/128-add-eslint

Conversation

@finnar-bin

Copy link
Copy Markdown
Contributor

Summary

  • Adds ESLint via flat config (eslint.config.js) with typescript-eslint's recommended config and eslint-plugin-react-hooks's recommended config against src/**/*.{ts,tsx}, plus an npm run lint script.
  • Fixes the ~30 scattered findings outside theme/**/LegacyTheme/** (dead imports/args in .stories.tsx files, unused vars, letconst, etc.).
  • Types the ~56 theme: any params in src/theme/index.tsx as MUI's Theme (parameterizing components as Components<Omit<Theme, "components">> so this type-checks), which also surfaced and fixed a real gap: body3 was only augmented on TypographyVariantsOptions (createTheme input) and never on TypographyVariants (what theme.typography.body3 reads at runtime). One remaining any (MuiAutocomplete.inputRoot's ownerState) can't be typed — MUI's AutocompleteOwnerState generics don't unify against the untyped styleOverrides slot — so it's a scoped inline disable instead. Net effect: the directory-wide no-explicit-anywarn override called for in the issue is no longer needed and has been removed; no-explicit-any is back to error repo-wide.
  • Triages the four items called out in the issue:
    • ConfirmDialog/index.tsx — the unused onClose destructure was a real bug silently stripping onClose before it reached MUI's Dialog, so backdrop/Escape-driven close never fired. Fixed.
    • FieldTypeSort/index.tsx — the two onChange && onChange(...) were functionally fine, just an unused-expression lint shape; rewritten as onChange?.(...).
    • SSOButtonGroup/index.tsx — the exhaustive-deps warning is not a bug: adding the missing deps would re-fire onSuccess/onError on every parent re-render for unmemoized callbacks. Left as-is with a justified inline disable.
    • utils/useSSO.ts — genuine stale-closure bug: the message listener closed over authServiceUrl but only ran on mount, so a changed authServiceUrl after mount kept validating against the stale origin. Fixed with useCallback.
  • LegacyTheme/index.ts's file-wide @ts-nocheck gets a scoped, justified disable instead of being left as a raw finding.
  • Pins Node via volta/.nvmrc to 18.20.4 — needed for ESLint 9's structuredClone requirement, while keeping Storybook 6/webpack 4 working via NODE_OPTIONS=--openssl-legacy-provider on the storybook/build-storybook scripts specifically (rather than a project-wide Node downgrade).

Out of scope (per issue)

  • CI wiring — deferred to a separate ticket.
  • Formatting/Prettier rules.
  • Any rule beyond the two named recommended configs.

Test plan

  • npm run lint exits 0 (0 errors, 0 warnings)
  • tsc --noEmit -p tsconfig.json exits 0
  • Manually verified in Storybook: ConfirmDialog now closes on backdrop click/Escape; other touched stories render without console errors
  • Built and imported into manager-ui — works as expected

Closes #128

🤖 Generated with Claude Code

finnar-bin and others added 2 commits September 2, 2026 11:51
Fixes the ~30 findings the config surfaced across src/ (dead imports,
unused vars, non-null-safe optional calls), triages the flagged
ConfirmDialog onClose and useSSO stale-closure bugs, and scopes
no-explicit-any to a warning under theme/**/LegacyTheme/** only.
Pins Node via volta/.nvmrc to satisfy both ESLint 9's engine requirement
and Storybook 6's webpack 4 OpenSSL provider (flag added to the
storybook/build-storybook scripts).

Closes #128

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Parameterizes the components object as Components<Omit<Theme, "components">>
so MUI can actually check styleOverrides callbacks, then types the ~56
previously-any theme params as Theme. Fixes a real gap this exposed:
body3 was only augmented on TypographyVariantsOptions (createTheme input),
never on TypographyVariants (what theme.typography.body3 reads at runtime).

The one any that can't be typed (MuiAutocomplete.inputRoot's ownerState —
MUI's AutocompleteOwnerState generics don't unify against the untyped
styleOverrides slot) gets a scoped disable comment instead. With nothing
left for it to cover, removes the theme/**/LegacyTheme/** no-explicit-any
override added for #128 so future any usage there is caught as an error
again.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@finnar-bin finnar-bin self-assigned this Sep 2, 2026
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Code Review — ✅ No blockers

# Conflicts:
#	package-lock.json
#	package.json
#	src/ConfirmDialog/ConfirmDialog.stories.tsx
#	src/ConfirmDialog/index.tsx
#	src/FieldTypeColor/index.tsx
#	src/FieldTypeNumber/index.tsx
#	src/FieldTypeOneToMany/index.tsx
#	src/FieldTypeOneToOne/index.tsx
#	src/FieldTypeSort/index.tsx
#	src/SSOButtonGroup/SSOButtonGroup.stories.tsx
#	src/TextField.stories.tsx
#	src/VitualizedAutocomplete/index.tsx
#	src/theme/index.tsx
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Code Review — ✅ No blockers

@finnar-bin
finnar-bin merged commit ae897cb into main Sep 3, 2026
1 check passed
@finnar-bin
finnar-bin deleted the chore/128-add-eslint branch September 3, 2026 01:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stand up ESLint with a TypeScript + react-hooks baseline

2 participants