diff --git a/.claude/skills/create-core-component/SKILL.md b/.claude/skills/create-core-component/SKILL.md index 93b7ad3a05..14d22b1408 100644 --- a/.claude/skills/create-core-component/SKILL.md +++ b/.claude/skills/create-core-component/SKILL.md @@ -17,17 +17,21 @@ Scaffold a complete, production-ready AEM Core Form Component across all layers ### Phase 1: Gather Requirements -Before generating any code, collect the following from the user: - -1. **Component name** — e.g., `ImageChoice`, `StarRating`, `ColorPicker` -2. **Component type** — which category: - - **Simple field** (text-like input) → extends `AbstractFieldImpl` / implements `Field` - - **Options field** (multiple choices) → extends `AbstractOptionsFieldImpl` / implements `OptionsConstraint` - - **Container** (holds child components) → extends `AbstractContainerImpl` - - **Display-only** (non-input: text, image, separator) → extends `AbstractBaseImpl` / implements `Base` -3. **Custom properties** — any JCR properties beyond what the base class provides -4. **Widget HTML** — what the interactive element looks like (input, select, custom markup) +Before generating any code or reading any reference files, collect all of the following from the user in a single message. Do not proceed until all answers are received. + +1. **Component name and purpose** — e.g., `ImageChoice` (radio group with image thumbnails), `StarRating` (captures 1–5 star rating) +2. **Component type** — which category (see `docs/architecture/overview.md` for the base class and interface each one maps to): + - **Simple field** (text-like input that captures a single value) + - **Options field** (multiple choices: checkboxes, radios, dropdowns) + - **Container** (holds child components) + - **Step / display** (non-input: text, image, separator) + - **Display/text** (renders authored HTML content with a title label) — `sling:resourceSuperType="core/fd/components/form/text/v1/text"` +3. **Custom properties** — any JCR properties beyond what the base class provides (name, type, default, purpose for each) +4. **Widget HTML** — what the interactive element looks like (input type, select, custom div, etc.) 5. **Constraints** — which constraint interfaces apply (String, Number, Date, Options, File) +6. **Target repository and component group** — which repo (`aem-core-forms-components`, or a project overlay) and what `componentGroup` for the author toolbar (e.g., `".core-adaptiveform"`) +7. **Java backend** — does this component need a custom Sling Model, or can it reuse an existing Core model via `sling:resourceSuperType`? (Reuse is appropriate when the component only adds JS behavior on top of an existing field type; custom Java is required for new authored properties exposed in HTL or JSON) +8. **FormContainer-level properties** — does this component need any configuration authored on the parent form container rather than on the component instance itself? (e.g., a signing service path set once for the whole form) If yes: what properties, and what tab name should they appear under in the form container dialog? ### Phase 2: Derive Naming Conventions @@ -44,6 +48,7 @@ From the component name, derive all naming variants. For example, given `ImageCh | Resource type | `core/fd/components/form/imagechoice/v1/imagechoice` | | Clientlib category | `core.forms.components.imagechoice.v1.runtime` | | FormConstant | `RT_FD_FORM_IMAGE_CHOICE_V1` | +| `fd:viewType` (step only) | `image-choice` | ### Phase 3: Generate Files @@ -70,9 +75,14 @@ Read `references/templates.md` for the full template set. Read `references/compo #### 3b. UI AF Apps (HTL, Dialogs, Clientlibs) -4. **Component definition** — `.content.xml` with `sling:resourceSuperType="core/fd/components/form/base/v1/base"` +4. **Component definition** — `.content.xml` with `sling:resourceSuperType` set to the appropriate base. Also create `_cq_template.xml` (instance defaults: `jcr:title`, `fieldType`, and `fd:viewType` for step components) and `_cq_editConfig.xml` (author toolbar — use the inplace RTE variant from `references/templates.md` template #16 for display/text components). See `references/templates.md` templates #6, #6b, and #16. -5. **HTL template** — Follow the standard structure: +5. **HTL template** — Choose the correct variant from `references/templates.md`: + - **Template #7** — field components (captures a value) + - **Template #7b** — step/display components (no widget) + - **Template #7c** — display/text with label and rich-text value area + + Follow the standard structure for the chosen variant: - Include shared templates via `data-sly-use` (label, shortDescription, longDescription, errorMessage, questionMark) - Root `
` with `data-cmp-is`, `data-cmp-visible`, `data-cmp-enabled`, `data-cmp-required`, `data-cmp-readonly` - Label container with label + question mark @@ -87,9 +97,9 @@ Read `references/templates.md` for the full template set. Read `references/compo 7. **Dialog XML** — Include base dialog fields via `granite/ui/components/coral/foundation/include`, add component-specific tabs/fields -8. **Site clientlib** — `.content.xml`, `js.txt`, `css.txt`, view JS, styles. **Before writing the view JS, read `references/runtime-view-js.md`** — it defines the `FormFieldBase` override contract (`super` calls, `updateEmptyStatus`, composite-widget focus guard). +8. **Site clientlib** — `.content.xml`, `js.txt`, `css.txt`, view JS (`references/templates.md` #11 or #11b), the CSS stub (empty BEM rules in `aem-core-forms-components`) plus the theme SCSS (actual styles in `aem-forms-theme-canvas`). See `references/css-architecture.md` and `references/templates.md` #12. **Before writing the view JS, read `references/runtime-view-js.md`** — it defines the `FormFieldBase` override contract (`super` calls, `updateEmptyStatus`, composite-widget focus guard). -9. **Editor clientlib** — `.content.xml` with editor category. In editor JS use `textContent` (never `innerHTML`) and don't wrap locale-neutral format strings in `Granite.I18n.get`. +9. **Editor clientlib** — `.content.xml` with editor category. See `references/editor-clientlib.md` for JS safety rules (`textContent` vs `innerHTML`, i18n) and the conditional-field-visibility pattern. 10. **Register the runtime clientlib** — embed the component's `core.forms.components.{componentname}.v1.runtime` category in `ui.af.apps/.../af-clientlibs/core-forms-components-runtime-all/.content.xml`. Missing this silently breaks the runtime Cypress suite. @@ -120,15 +130,21 @@ required** (they catch HTL/view-JS/dialog/sync bugs that unit tests cannot). Rea 17. **Example content page** — Page structure with `guideContainer` and sample component instance 18. **Register in example index** — Add entry to `examples/ui.content/.../adaptive-form/.content.xml` -### Phase 4: Accessibility Verification +#### 3e. Wiring and Registration + +After all files are created, complete the wiring steps from `references/wiring-steps.md`: -After generating all files, read `references/accessibility-checklist.md` and verify: +- **Step 1** — Embed the clientlib category in `core-forms-components-runtime-all/.content.xml` +- **Step 2** — Add `FormConstants` resource type constant (if needed by other Java code) +- **Step 3** — Add i18n strings to all 10 language files (if new constraint messages were added) +- **Step 4** — Content migration (see `migrate-foundation-component` skill — not applicable for new components) +- **Step 5** — Extend FormContainer dialog (if component reads form-level properties) +- **Step 6** — Register component group in the production template policy +- **Step 7** — Create integration test content and register it in the IT template policy + +### Phase 4: Accessibility Verification -1. **HTL template** — Every interactive element has `aria-label` or `