chore(skill): improve port-widget audit and add --gaps mode#7020
Open
aymeric-giraudet wants to merge 2 commits into
Open
chore(skill): improve port-widget audit and add --gaps mode#7020aymeric-giraudet wants to merge 2 commits into
aymeric-giraudet wants to merge 2 commits into
Conversation
The audit script previously missed widgets like `dynamic-widgets` (uses `.ts`, not `.tsx`) and falsely flagged variants like `range-input`/`menu-select` as missing their connector/hook. It also looked for Vue placeholders by exact PascalCase match, missing irregular names like `RelatedProduct` (singular). Adds a `--gaps` mode so contributors can see all open porting work across flavors at a glance, and refreshes the skill docs around an audit-first workflow with a Vue render-function template for the recommendation/chat family of widgets.
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Duplication | 0 |
TIP This summary will be updated as you push new changes.
More templates
algoliasearch-helper
instantsearch-ui-components
instantsearch.css
instantsearch.js
react-instantsearch
react-instantsearch-core
react-instantsearch-nextjs
react-instantsearch-router-nextjs
vue-instantsearch
commit: |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR improves the “port-widget” skill’s repository audit tooling and documentation, aiming to make widget porting status across JS / React / Vue more accurate and actionable (including a new --gaps summary mode).
Changes:
- Enhanced
audit_widget_coverage.pyto handle variant widgets, special layouts (e.g.dynamic-widgets), Vue placeholder name irregularities, and added a--gapsgrouped summary mode. - Updated
SKILL.mdto promote an audit-first workflow and document variant/precedent guidance. - Refreshed Vue/React flavor reference docs (Vue render-function template + updated precedent lists).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
.claude/skills/port-widget/SKILL.md |
Updates workflow guidance, variant table, and adds a “precedent picker” to support audit-driven porting. |
.claude/skills/port-widget/scripts/audit_widget_coverage.py |
Fixes audit accuracy and adds --gaps mode to summarize missing artifacts by flavor. |
.claude/skills/port-widget/references/vue-flavor.md |
Expands Vue precedents and adds an annotated render-function wrapper template for shared UI factories. |
.claude/skills/port-widget/references/react-flavor.md |
Adjusts React UI precedent list (removes incorrect MenuSelect.tsx reference). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+70
to
+72
| For these, the audit will show `no` on connector/hook rows by design. Skip | ||
| connector/hook creation, import the upstream hook directly, and only port the | ||
| wrapper plus wrapper tests. |
Comment on lines
+27
to
+35
| - Use `createSuitMixin({ name: '<Pascal>' })` for BEM classes. When the widget | ||
| delegates all rendering to a shared `createXxxComponent` factory, the suit | ||
| mixin's `suit()` method goes unused but the `classNames` prop it provides is | ||
| still convenient. Pass `this.classNames` directly to the shared component's | ||
| `classNames` prop (semantic keys like `{ root, container }`, not BEM keys). | ||
| - Expose connector params through a computed `widgetParams()` object. | ||
| - When reusing shared UI factories, wrap the render function with `renderCompat(...)` and map `this.classNames` into the `classNames` prop expected by the shared component. | ||
| - Prefer `getScopedSlot` or `getDefaultSlot` helpers over direct slot access when matching render-function components. | ||
| - In render-function callbacks that reference connector state (e.g. `onSubmit`, `onInput`), read from `this.state.xxx` instead of destructured locals. Vue batches re-renders, so destructured values become stale between synchronous user interactions (type then click). | ||
| - When reusing shared UI factories, wrap the render function with | ||
| `renderCompat(...)` and map `this.classNames` into the `classNames` prop | ||
| expected by the shared component. |
Comment on lines
+21
to
+27
| # Widgets that reuse another widget's connector/hook. | ||
| # A variant's connector and hook entries are expected to be absent. | ||
| VARIANTS: dict[str, str] = { | ||
| "menu-select": "menu", # uses connectMenu / useMenu | ||
| "range-input": "range", # uses connectRange / useRange | ||
| "range-slider": "range", # JS-only widget that uses connectRange | ||
| } |
Comment on lines
+48
to
+53
| # Vue widgets known to ship as `.js` render-function wrappers around a shared | ||
| # UI factory rather than `.vue` SFCs. Useful as precedents when porting newer | ||
| # recommendation/chat widgets. | ||
| VUE_RENDER_FUNCTION_PRECEDENTS = ("Hits.js", "Highlighter.js", "DynamicWidgets.js", "Feeds.js") | ||
|
|
||
|
|
Comment on lines
+147
to
+150
| hook_owner = variant_of | ||
| else: | ||
| connector_owner = widget | ||
| hook_owner = widget |
Adds a "Pitfalls discovered while porting recommendation widgets" section to the Vue reference, covering the Fragment shim, status tracking via `createRecommendMixin`, async state delivery in test setups, Vue's swallowed connector throws, and flavored test suites that need real Vue widgetParams. Captured while implementing the actual ports in a separate PR; surfacing the lessons here so the next contributor doesn't have to rediscover them.
This was referenced May 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
audit_widget_coverage.py: also looks for.tsJS widgets (was missingdynamic-widgets), treats variants (range-input,menu-select,range-slider) as reusing their upstream connector/hook instead of flagging them as missing, and matches Vue placeholder strings that don't follow PascalCase (e.g. singularRelatedProductforrelated-products).--gapsmode that lists every widget with open porting work, grouped by flavor, and separates real porting gaps from low-priority test-suite-only follow-ups.SKILL.mdaround an audit-first workflow, add a variants table, a precedent picker, and a current-gap-shape snapshot.references/vue-flavor.md(distilled fromHits.js/Feeds.js) that covers the recommendation/chat widgets still missing in Vue.MenuSelect.tsxprecedent reference fromreferences/react-flavor.md.Test plan
python3 .claude/skills/port-widget/scripts/audit_widget_coverage.py --gapslists the expected React (numeric-menu, menu-select, rating-menu) and Vue (chat, filter-suggestions, frequently-bought-together, looking-similar, related-products, trending-facets, trending-items, autocomplete) gaps.python3 .claude/skills/port-widget/scripts/audit_widget_coverage.py menu-select range-input dynamic-widgets related-productsshows variant/special notes and the correct placeholder string forrelated-products.python3 .claude/skills/port-widget/scripts/audit_widget_coverage.py refinement-listreports a fully covered widget with no notes.