diff --git a/docs/guides/javascript/react/theming.md b/docs/guides/javascript/react/theming.md index f2ef85dab..6bc0c78a1 100644 --- a/docs/guides/javascript/react/theming.md +++ b/docs/guides/javascript/react/theming.md @@ -141,6 +141,61 @@ export const ExampleComponent = (props) => { ``` +## Generating overrides with the swizzle CLI + + + +The **swizzle CLI** generates the override files described above for you, instead of you creating them by hand. It scaffolds either a `wrap` (a component that decorates the original) or an `eject` (a full copy of the original source) into your theme. + +Run it from the project root, or from inside a `public/theme/` directory to have the target theme inferred automatically: + +```bash +npm run swizzle +``` + +This launches an interactive wizard that asks you to pick a component, an action (`wrap` or `eject`), and a target theme, then generates the files for you. Once generated, run `grunt react[:watch]` to compile the override. + +### Risk profiles + +Not every component is safe to override. A component's public-facing props are usually stable, but its internal markup and children can change between releases. Each swizzleable component declares an independent safety level for **eject** and **wrap** in its plugin's `js/esm/src/swizzle.json`: + +| Level | Meaning | +| --- | --- | +| `safe` | Stable enough to override with minimal upgrade risk. | +| `risky` | Works, but internals may change between minor releases, so you may need to revisit the override after upgrading. | +| `prohibited` | Blocked by the component's author, usually because the component depends on internal implementation details that are not part of its public API. | + +The CLI enforces these levels: a `risky` action asks for confirmation before continuing, and a `prohibited` action is refused outright, with a suggestion to look for a hook, event, or a nearby `safe`/`risky` component instead. + +A plugin's `swizzle.json` maps each module name to its levels, for example: + +```json title="public/lib/js/esm/src/swizzle.json" +{ + "ExampleComponent": { + "eject": "risky", + "wrap": "safe" + } +} +``` + +:::info[Undeclared components default to risky] + +Every `grunt react`/`grunt esm` build scans for swizzleable components with no entry in their plugin's `swizzle.json`, and adds one that defaults both `eject` and `wrap` to `risky`. This keeps the manifest up to date automatically as components are added. A plugin author only needs to loosen a component to `safe` or tighten one to `prohibited`, either by hand-editing `swizzle.json` or with the `manifest set` command described below. + +::: + +### Setting a component's safety level + +Plugin authors can set a component's levels directly, without hand-editing `swizzle.json`, with: + +```bash +./scripts/swizzle.mjs manifest set [specifier] [ejectLevel] [wrapLevel] +``` + +- Omit `specifier` and the levels for an interactive prompt that lets you pick the component and level. +- Provide a specifier and one level (for example, `./scripts/swizzle.mjs manifest set @moodle/lms/mod_assign/local/grader/GradingPanel safe`) to set both `eject` and `wrap` to that level. +- Provide a specifier and two levels (eject, then wrap) to set them independently. + ## Testing theme overrides You can write tests for your theme-specific overrides in the same way that tests can be written for other components.