Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions docs/guides/javascript/react/theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,61 @@ export const ExampleComponent = (props) => {

```

## Generating overrides with the swizzle CLI

<Since version="5.3" issueNumber="MDL-88509" />

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/<themename>` 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.
Expand Down
Loading