Skip to content

feat: convert remaining JS assets to Typescript#153

Open
justlevine wants to merge 3 commits intodevelopfrom
feat/typescript
Open

feat: convert remaining JS assets to Typescript#153
justlevine wants to merge 3 commits intodevelopfrom
feat/typescript

Conversation

@justlevine
Copy link
Collaborator

@justlevine justlevine commented Mar 10, 2026

Description

Migrates the remaining JS asset files to typescript

Important

This PR is based on #152 which should be merged first.

Technical Details

  1. Prompted (oh-my-opencode + glm+5)

    Make a plan and convert any Javascript files in assets/src to Typescript.
    
    1. Run npm run lint:js:types to see the current repository errors, and npm run test:js:coverage to see the current coverage baselines.
    2. Find any assets/src .js or .jsx files, and convert them to typescript.
    3. For each file, study, make a plan, and fix any Typescript/eslint errors: npm run lint:js && npm run lint:js:types must pass.
    4. Ensure npm run test:js:coverage tests still pass and coverage hasn't meaningfully dropped.
    ulw
    Audit these new tsx files for slop ulw
  2. Manually reviewed the changes.

Checklist

Screenshots

To-do

Fixes/Covers issue

Fixes #

Open WordPress Playground Preview

@justlevine justlevine changed the base branch from develop to tests/backfill-jest March 10, 2026 01:48
@justlevine justlevine requested a review from Copilot March 10, 2026 01:48
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR continues the JS→TypeScript migration for admin search-related assets, updating build entrypoints and adding stronger typing + small UI/accessibility adjustments in several React components.

Changes:

  • Switch the search webpack entry from index.js to index.tsx.
  • Add TypeScript typings and URL-normalization helpers across search settings and indexable entities components.
  • Refactor MultiSelectChips for better keyboard interaction and typed event handling.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
webpack.config.js Updates admin search entrypoint to index.tsx.
assets/src/admin/search/index.tsx Converts admin search settings page to TSX with typed state, fetch responses, and notice handling.
assets/src/components/SiteSearchSettings.tsx Adds TS types, uses shared withTrailingSlash, and refines dirty-checking/auto-save typing.
assets/src/components/SiteIndexableEntities.tsx Adds TS types for entity maps and API responses; refines error handling and UI keys.
assets/src/components/MultiSelectChips.tsx Adds TS props/types and improves keyboard interactions / ARIA labeling for chip removal.
.stylelint.config.js Expands ignore patterns to include JSX/TS/TSX (currently with malformed TS globs).
Comments suppressed due to low confidence (8)

assets/src/admin/search/index.tsx:15

  • defaultBrandSite is imported using import type, but this module later uses typeof defaultBrandSite (a type query) which requires defaultBrandSite to be available in the value space. With strict + isolatedModules, this will fail to type-check. Import defaultBrandSite as a normal value import (and keep BrandSite/NoticeType as type-only imports) or avoid the typeof type query here.
    assets/src/admin/search/index.tsx:33
  • BrandSiteFormData = typeof defaultBrandSite will error as long as defaultBrandSite is a type-only import. Either switch to a value import for defaultBrandSite, or replace this with an explicit interface/type (e.g., BrandSite) so the file doesn’t depend on a value-level symbol for typing.
    assets/src/components/MultiSelectChips.tsx:132
  • The trigger is now a div with role="button", but it doesn’t set aria-disabled when disabled is true. Since there is no native disabled attribute on a div, screen readers won’t reliably announce the disabled state. Add aria-disabled={disabled} on the element with role="button" (and keep the existing tabIndex/click guards).
    assets/src/components/SiteIndexableEntities.tsx:386
  • Brand-site lookups use the raw site.url as the key (e.g., allPostTypes?.[ site?.url ]), but other parts of the flow normalize URLs with withTrailingSlash when building the allPostTypes map. This mismatch can cause valid post types to appear missing for brand sites. Normalize site.url before indexing into allPostTypes here.
    assets/src/components/SiteIndexableEntities.tsx:395
  • selectedEntities is keyed by site URL, but this block reads/writes using the raw site?.url and passes it to handleSelectedEntitiesChange. If the API keys are normalized (trailing slash) this will store selections under a different key and the UI will not reflect saved selections. Use the same normalized URL key (e.g., withTrailingSlash(site.url)) consistently for value, onChange, and map access.
    assets/src/components/SiteSearchSettings.tsx:549
  • ToggleControl is given an empty label. This makes the control effectively unlabeled for assistive tech. Provide an accessible label (and optionally hide it visually with hideLabelFromVision) that describes what toggling does for the specific site.
    assets/src/admin/search/index.tsx:94
  • This useEffect uses fetchEntities from the component scope but has an empty dependency array. With the repo’s React hooks linting, this will be flagged as missing dependencies. Wrap fetchEntities in useCallback and include it in the deps array (or inline the fetch logic inside the effect).
    assets/src/components/MultiSelectChips.tsx:41
  • useRef< HTMLDivElement >( null ) is not valid under strictNullChecks because null isn’t assignable to HTMLDivElement. Use useRef<HTMLDivElement | null>( null ) (or a non-null assertion) so the ref type matches its initial null value.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

@justlevine
Copy link
Collaborator Author

@justlevine justlevine requested a review from up1512001 March 10, 2026 02:06
Copy link
Member

@up1512001 up1512001 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@justlevine Did not tested locally but I would highly doubt that this will work same as previous...

</span>
<span
role="button"
<button
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because changing a <span> to a <button> to fix a nesting violation is less intrusive then migrating an entire component.


/**
* Internal dependencies
* External dependencies
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

types are from our internal file 😕

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ makes them external to the current module. Fixed the labeling here: 48873cb

[ siteUrl: string ]: string[];
}

interface SiteIndexableEntitiesProps {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

confirmed originalData props are not used so no need to pass it, why types check did not pickup this issue @justlevine may be you need to check?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<Button
variant="primary"
onClick={ handleReIndex }
onClick={ () => handleReIndex() }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what problem does this solves, as we are not passing any events to handleReIndex function, I don't think this change is required

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The signature still has to match, and I thought this was less disruptive
image

@justlevine
Copy link
Collaborator Author

@justlevine Did not tested locally but I would highly doubt that this will work same as previous...

Thanks for the feedback and I'll review shortly. Keep in mind the goal isn't to fix the logical issues with the current implementation, just to make them typesafe.

Base automatically changed from tests/backfill-jest to test/skeleton-migration March 10, 2026 14:29
Base automatically changed from test/skeleton-migration to develop March 10, 2026 14:40
@justlevine justlevine force-pushed the feat/typescript branch 2 times, most recently from 3bd4d40 to 53fdb7b Compare March 10, 2026 18:24
@justlevine justlevine requested a review from up1512001 March 10, 2026 19:25
@justlevine
Copy link
Collaborator Author

@up1512001 I cleaned up based on your feedback (rebasing the diff helped too). Remaining open comments are for your approval

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.

3 participants