Skip to main content

review-component-pr

Comprehensive code review checklist for component pull requests ensuring quality, accessibility, and adherence to project conventions

Ir para a instalação

Informações da origem

Repositório
IgniteUI/igniteui-webcomponents
Última atividade na origem
18 de agosto de 2026 às 07:53
Idioma detectado do SKILL.md
inglês
Estrelas
170
Forks
11

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
review-component-pr
description
Comprehensive code review checklist for component pull requests ensuring quality, accessibility, and adherence to project conventions
# Review Component PR A review checklist for pull requests that add or modify components. The rules behind it live in the [Coding Guidelines](../../CODING_GUIDELINES.md); this skill is the pass over a diff. ## When to Use - Reviewing a PR that adds or changes a component - Pre-merge quality gate, or a self-review before opening a PR ## Review Order 1. **Structure** — are all the required files there? 2. **Public API** — properties, events, docs; this is the part that cannot be changed later 3. **Accessibility** — mandatory, never skipped 4. **Behavior** — lifecycle, state, forms 5. **Styles and themes** 6. **Tests and generated artifacts** 7. **Build and hygiene** ## 1. Structure - [ ] Component at `src/components/[name]/[name].ts` with a single default export - [ ] Spec at `src/components/[name]/[name].spec.ts` - [ ] Story at `stories/[name].stories.ts` — filename matches the tag name - [ ] Theme scaffold complete: `[name].base.scss`, `shared/`, `light/`, `dark/`, `themes.ts` - [ ] Exported from `src/index.ts` in alphabetical order - [ ] Cross-cutting imports use `#internals/*`, `#theming/*`, `#animations/*`; component-to-component imports stay relative; every specifier ends in `.js` - [ ] Nothing new under `src/internals` is exported from the public entry point ## 2. Public API and Documentation - [ ] `tagName`, `styles` and `register()` static members present; `register()` also registers every dependency rendered in the template - [ ] `HTMLElementTagNameMap` declaration added - [ ] Only primitives are attributes; complex types use `attribute: false` and are never reflected - [ ] Booleans default to `false` - [ ] Attribute names are kebab-case, spelled out for multi-word properties - [ ] Events go through `EventEmitterMixin` with a typed event map; names are `igc`-prefixed camelCase, cancelable ones use the `-ing` suffix and their return value is checked - [ ] Events are emitted from user interaction, not from property assignment or method calls - [ ] JSDoc carries `@element`, `@slot`, `@csspart`, `@cssproperty`, `@attr`, `@default`, `@event` as applicable, with tags after the description - [ ] Deprecations follow `@deprecated since [SemVer]. Use the \`[new API]\` [type] instead.` - [ ] **No `igc-` tag names in description prose** — they ship verbatim into `custom-elements.json` and every framework wrapper's docs. Allowed only in `@element`, fenced `@example` blocks, literal `igc-`-containing event/attribute names, and `@internal`/`@hidden` members. - [ ] Descriptions don't restate the tag ("The label _attribute_ of…"), don't use `Gets/Sets`, and booleans start with "Whether" describing the `true` state accurately ```bash # Quick leak check — should return nothing outside @element/@example grep -rn "igc-" --include="*.ts" src/ \ | grep -E "^\S+:[0-9]+:\s*\*" \ | grep -vE "@element|@example|\.spec\.ts" ``` ## 3. Accessibility - [ ] The spec contains the mandatory a11y audit (`shadowDom` **and** light DOM) - [ ] Semantic elements used instead of `div`s with click handlers - [ ] ARIA set through `addInternalsController` (`initialARIA`, `setARIA()`) — never `this.role = '…'`; `reflectRole: true` when attribute-only tooling must see the role - [ ] Keyboard interaction implemented through `addKeybindings` (Tab, arrows, Enter/Space, Escape, Home/End as applicable) with visible focus indicators - [ ] Composite hosts wrapping an input-shaped component project their semantics with `addAriaProjector` / `addAriaTarget` instead of setting `role`/`aria-*` on the host or the wrapper - [ ] Cross-root relations use ARIA element reflection, never IDREFs - [ ] Theme selectors for composite anchors key off the mirrored `data-role`/`data-haspopup` attributes, not `role`/`aria-*` - [ ] No `public` members tagged `@hidden`/`@internal` added for cross-component access — use `internalsOf()` - [ ] Cross-root ARIA is covered by `runExternalLabelAssociationTests` / `runAriaProjectionTests`; reflected relations are asserted by identity readback, with `axeReflectedRelationsOptions` suppressing the known `aria-required-attr` false positive ## 4. Behavior - [ ] Region fences and member order follow the standard component structure - [ ] Internal API is `_`-prefixed; no native private fields (`#`); `readonly` on controllers and other non-reassigned fields - [ ] No `any`; explicit return types except where obviously noise - [ ] Derived state computed in `willUpdate()`, side effects in `update()` with `super.update()` called; guarded by `changedProperties.has()` - [ ] No new `@watch` usages - [ ] Existing controllers reused rather than reimplemented (slots, observers, root click, keybindings, gestures, i18n) - [ ] Dynamically added listeners on `window`/`document` are removed in `disconnectedCallback`; listeners in templates and on the host are not manually cleaned up - [ ] User-facing strings come from the i18n controller, not inlined in templates - [ ] Form controls: extend the right form-associated mixin, own their `_formValue` through `createFormValueState`, expose validators via `__validators` (reusing `#internals/validators.js`), update through `setValueAndFormState`, call `_validate()` from constraint-affecting setters, and wire `_handleBlur` / `_handleEnterKeydown` on the native editor - [ ] Form controls don't reimplement touched/pristine/invalid bookkeeping; overrides of `formResetCallback` call `super` ## 5. Styles and Themes - [ ] Only `.scss` edited — no generated `.css.ts` in the diff - [ ] Load-path specifiers (`@use 'styles/utilities' as *`), no relative global imports - [ ] Values read through `var-get()` and the theming functions; nothing hardcoded - [ ] Part selectors use `[part~='…']` - [ ] All four themes covered in light and dark; dark files emit only the `diff()` - [ ] `themes.ts` aggregates every theme file that was added - [ ] `:host` has an appropriate `display`; selector specificity kept low ## 6. Tests and Generated Artifacts - [ ] `defineComponents()` in the `before()` hook; `elementUpdated()` after programmatic changes - [ ] Coverage for defaults, property/attribute reflection, events, interaction and edge cases - [ ] Interaction driven by the shared simulators from `#internals/testing/simulate.spec.js`, not raw `click()` / hand-built events - [ ] Form controls tested through `createFormAssociatedTestBed` and the validity helpers - [ ] The story's `// region default … // endregion` block was regenerated (`npm run cem && npm run build:meta`), not hand-edited, and is committed - [ ] Hand-written stories cover the states a user cares about - [ ] CHANGELOG updated ## 7. Build and Hygiene - [ ] `npm run check` (aliases, dependency rules, types) passes - [ ] `npm run lint` passes — oxlint, lit-analyzer, oxfmt, stylelint - [ ] `npm run test` passes - [ ] No leftover `console.log`/`debugger`, no commented-out code, no unexplained magic numbers - [ ] No new heavy third-party dependency ## Frequent Findings | Finding | Why it matters | | ---------------------------------------------- | --------------------------------------------------------------------- | | Missing `addThemingController` | The component never reacts to theme changes | | Relative import into `internals`/`theming` | `npm run check` fails; alias is the contract | | Alias added to `package.json` only | Breaks only for consumers of the published package | | `igc-` tag name in a description | Ships verbatim into every framework wrapper's API docs | | Hand-edited story metadata | Reverts on the next `npm run build:meta` | | `.css.ts` file in the diff | Generated and gitignored — the `.scss` is the source | | `[part='base']` with `partMap` | Selector silently stops matching once a second part name is emitted | | ARIA on a `delegatesFocus` host | Assistive technology reads the native editor, not the host | | New `@hidden` public member | Leaks into the compiled public API — use `internalsOf()` | | Boolean property defaulting to `true` | Cannot be turned off from markup | | `@watch` in new code | Lifecycle hooks are the supported path | ## Verdict **Request changes** when: the a11y audit is missing or failing, ARIA is set on the wrong element, `any` types or native private fields appear, generated artifacts are hand-edited or missing, themes are incomplete, or the public API is undocumented. **Approve** when the checklist passes, `npm run check`, `npm run lint` and `npm run test` are green, and the public API reads the way it will be documented for users. Be specific in feedback: name the file, the line and the guideline it maps to.
Ver no GitHub