review-component-pr
GitHub提供组件Pull Request的代码审查清单,涵盖结构、公共API、规范准确性、无障碍、行为、样式、测试及构建卫生等维度的检查项。
Trigger Scenarios
Install
npx skills add IgniteUI/igniteui-webcomponents --skill review-component-pr -g -y
SKILL.md
Frontmatter
{
"name": "review-component-pr",
"description": "Code review checklist for component pull requests covering structure, public API, specification accuracy, accessibility, behavior, styles, tests, and build hygiene"
}
Review Component PR
A checklist to use on a diff. The rules are in the Coding Guidelines.
Read the spec.md of the component before the diff. A change that contradicts the spec is a
bug, or the author must also update the spec.
Review in this order. The public API is hard to change after release, so review it early.
1. Structure
-
[name].ts(single default export),[name].spec.tsandspec.mdinsrc/components/[name]/ -
stories/[name].stories.ts, with a filename that matches the tag - Complete theme scaffold, with every file in
themes.ts - Exported from
src/index.tsin alphabetical order. No new exports fromsrc/internalsbeyond the approved list in Project Structure. -
#internals/#theming/#animationsaliases for cross-cutting imports. Relative imports between components..jsspecifiers. - A new alias is in
package.jsonand inscripts/_package.json
2. Public API and Documentation
-
tagName,styles,register()(with all rendered dependencies),HTMLElementTagNameMap - Only primitives are attributes. Complex types use
attribute: falseand do not reflect. - Booleans default to
false. Multi-word attributes are kebab-case and explicit. - Events use
EventEmitterMixinwith a typed map. Names areigc+ camelCase, cancelable events end in-ingand the code checks their return value. - Events come from user interaction, not from property sets or method calls
- JSDoc tags come after the description.
@deprecated since [SemVer]. Use the \[new]` [type] instead.` - No
igc-tag names in description prose. No "…attribute of…", noGets/Sets. Booleans start with "Whether" and match thetruestate.
# Tag-name leak check: expect no output outside @element/@example
grep -rn "igc-" --include="*.ts" src/ \
| grep -E "^\S+:[0-9]+:\s*\*" \
| grep -vE "@element|@example|\.spec\.ts"
3. Specification
Map each change to a spec section with Keeping it current.
- A new component has a
spec.mdin the splitter structure - API tables match the JSDoc for each added, renamed, deprecated or removed member
- Keyboard, ARIA and limitations sections are updated where the behavior changed
- Test scenarios mirror the
describeblocks and are numbered contiguously. Gaps are listed under### Not covered by the suite. -
## Revision historyhas a new row - New headings have TOC entries. Anchors and relative sibling links resolve.
4. Accessibility
- The a11y audit covers
shadowDomand the light DOM - Semantic elements are used, not
divs with click handlers - ARIA is set through
addInternalsController(initialARIA,setARIA(),reflectRole), never withthis.role = … - Keyboard support uses
addKeybindingsoraddRovingFocusController. Focus is visible. On adelegatesFocusitem, the roving tab index is on the host, not on an inner element. - Composite hosts use
addAriaProjector/addAriaTarget, with no ARIA on adelegatesFocushost. Cross-root relations use element reflection, not IDREFs. - Theme selectors use
data-role/data-haspopup, notrole/aria-* - Cross-component access uses
internalsOf(), not new@hiddenpublic members - Cross-root ARIA is tested with
runExternalLabelAssociationTests/runAriaProjectionTests. Relations are checked by identity readback.axeReflectedRelationsOptionsis used only next to such a check.
5. Behavior
- Region fences and member order follow the guidelines. Internal members use
_. No#fields.readonlyon fields that are not reassigned. Noany. - Derived state in
willUpdate(). DOM side effects inupdate()withsuper.update(). Both guarded bychangedProperties.has(). - Coercion and per-set side effects use
@coercedProperty, not a hand-written backing-field accessor pair - Existing internals are reused (controllers,
resizable()/draggable(),createTimer,internals/utils), not written again - Dynamic
window/documentlisteners are removed indisconnectedCallback - User-facing strings come from
I18nMixin/addI18nController, with defaults fromigniteui-i18n-core - Form controls: the correct mixin,
createFormValueState,__validatorsfrom#internals/validators.js,setValueAndFormState(), re-validation through@coercedPropertyon constraint properties, and_handleBlur/_handleEnterKeydownon the native editor. No copied touched/pristine logic.formResetCallbackoverrides callsuper.
6. Styles and Themes
- No generated
.css.tsin the diff - Load-path specifiers. Values come from
var-get()and the theming functions. -
[part~='…']selectors. Dark files emit only thediff(). - All four themes work in light and dark mode.
:hosthas adisplayvalue. Specificity is low.
7. Tests and Generated Artifacts
-
defineComponents()inbefore().elementUpdated()after programmatic changes. - Tests cover defaults, reflection, events, interaction and edge cases
- Interaction uses
#internals/testing/simulate.spec.js. Forms usecreateFormAssociatedTestBedand the validity helpers. - No spec imports another component's spec. Shared helpers are in
src/internals/testing/. - The story's
// region defaultblock was regenerated (cem+build:meta), not edited - CHANGELOG updated
8. Build and Hygiene
-
npm run check,npm run lintandnpm run testpass - No
console.log,debuggeror commented-out code. No unexplained magic numbers. - No new heavy third-party dependency
Frequent Findings
| Finding | Why it matters |
|---|---|
Missing addThemingController |
The component ignores theme changes |
Relative import into internals |
npm run check fails |
Alias only in package.json |
Breaks only for consumers of the published package |
igc- in a description |
Goes into the API docs of every framework wrapper |
Hand-edited story region or .css.ts |
Overwritten on the next build |
[part='base'] with partMap |
Stops matching when a second part name is added |
ARIA on a delegatesFocus host |
Assistive technology reads the native editor |
New @hidden public member |
Leaks into the public API. Use internalsOf(). |
| Hand-written accessor pair for coercion | @coercedProperty does this in fewer lines |
API change with no spec.md change |
The spec no longer describes the component |
| Spec scenario with no test | Shows coverage that does not exist |
Verdict
Request changes if the a11y audit is missing or fails, ARIA is on the wrong element, any
or # fields are in the code, generated files are edited or stale, themes are incomplete, the
public API has no documentation, or spec.md does not match the behavior.
Approve if the checklist passes and check, lint and test pass. Each comment must
give the file, the line and the guideline it applies.
Version History
- 7.4.1 Current 2026-09-28 12:53


