Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion docs/guides/accessing-the-dom.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Accessing the DOM
category: Guides
order: 3
order: 4
relevantForAI: true
---

Expand Down
108 changes: 108 additions & 0 deletions docs/guides/component-versioning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
title: Component versioning
category: Guides
order: 2
---

## Why components are versioned

When InstUI needs to make a breaking change to a component (renamed props, changed behaviour, etc.), the old version is **kept alongside the new one** instead of being replaced. Upgrading the library no longer forces you to immediately rewrite every component usage — you can migrate to new versions on your own schedule.

New component versions appear with InstUI **minor** version bumps (e.g. `11.7` → `11.8`). Patch releases never include breaking changes.

## Import paths

Every InstUI component package supports three import styles:

### Default — `@instructure/ui-<name>`

Always points to the **oldest** still-supported component version. Upgrading the library without changing your imports will keep your code working without surprises.

```js
---
type: code
---
import { Alert } from '@instructure/ui-alerts'
```

### Pinned — `@instructure/ui-<name>/v11_X`

Locks the import to a specific InstUI minor version of the component. When you are ready to adopt a breaking change, update the path to the next pinned version.

```js
---
type: code
---
import { Alert } from '@instructure/ui-alerts/v11_7'
```

### Latest — `@instructure/ui-<name>/latest`

Always points to the newest component version. This may bring breaking changes when you upgrade InstUI itself.

```js
---
type: code
---
import { Alert } from '@instructure/ui-alerts/latest'
```

### Per-package or umbrella package

InstUI also ships an umbrella package, `@instructure/ui`, which re-exports every component from the individual `@instructure/ui-*` packages. Two equivalent import styles work — both resolve to the same component:

```js
---
type: code
---
// per-package import
import { Alert } from '@instructure/ui-alerts/v11_7'

// umbrella package import
import { Alert } from '@instructure/ui/v11_7'
```

The same three path styles (default / `/v11_X` / `/latest`) work on the umbrella package as well. Pick per-package imports when you want better tree-shaking and only pull in what you use, or the umbrella package when you'd rather depend on a single `@instructure/ui` entry in your `package.json`.

## Versions and theming engines

InstUI is in the middle of a transition between two theming systems. Which engine a component uses depends on which version you import:

- **`v11_6` and earlier** — legacy theming. Components are configured through the Canvas theme variables and the `themeOverride` prop, which accepts a function or object that maps to the component's own theme map. See the [Legacy theme overrides](legacy-theme-overrides) guide.

- **`v11_7` and newer** — new theming system. Components consume pre-resolved design tokens, and theming is done through the new token override structure. See the [New theme overrides](new-theme-overrides) guide.

Mixing imports from both groups in the same app is fully supported — the two engines run side-by-side without conflict.

### Supported themes per version

You import themes the same way as before — from `@instructure/ui-themes` — and pass them to `InstUISettingsProvider`:

```js
---
type: code
---
import { canvas } from '@instructure/ui-themes'

<InstUISettingsProvider theme={canvas}>
<App />
</InstUISettingsProvider>
```

The `canvas` (and `canvasHighContrast`) export works for **both `v11_6` and `v11_7+` components in the same app** — internally it carries the data each engine needs. You don't need to switch theme objects when you bump a component import to `/v11_7`.

- **`v11_6` and earlier** — supports the original two themes:

- `canvas` — default theme used by Canvas products
- `canvasHighContrast` — same as `canvas`, with colors WCAG-tuned for high-contrast accessibility

- **`v11_7` and newer** — supports the same two themes (rendered through the new engine, labelled `(legacy)` in the docs UI Theme selector) plus two brand-new ones:

- `canvas` — same import as above, now driven by the new engine (labelled as `(legacy)`)
- `canvasHighContrast` — same import as above, now driven by the new engine (labelled as `(legacy)`)
- `light` — new light theme
- `dark` — new dark theme

This means that when you move a component import from `/v11_6` to `/v11_7`, you can continue using the `canvas` theme to maintain a familiar look and feel, and opt in to `light` or `dark` only when you're ready.

> The `@instructure/ui-themes` package also exports `legacyCanvas` and `legacyCanvasHighContrast`. These are the raw new-engine forms that `canvas` / `canvasHighContrast` wrap internally — most consumers don't need to import them directly.
2 changes: 1 addition & 1 deletion docs/guides/forms.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Forms
category: Guides
order: 4
order: 5
relevantForAI: true
---

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/module-federation.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Module federation
category: Guides
order: 2
order: 3
relevantForAI: true
---

Expand Down
9 changes: 0 additions & 9 deletions docs/theming/legacy-theme-overrides.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,6 @@ relevantForAI: true

## Using theme overrides

```js
---
type: embed
---
<Alert variant="warning" margin="0 0 medium">
The examples on this page use the <strong>legacy theming system</strong> and are designed for <strong>v11.6</strong> components. If you are viewing the v11.7 version, <Link href={window.location.pathname.match(/v\d+_\d+/) ? window.location.pathname.replace(/v\d+_\d+/, 'v11_6') : `/v11_6${window.location.pathname}`}>switch to v11.6</Link> to see the examples working correctly.
</Alert>
```

This document gives an overview on how you can customize Instructure UI components by tweaking their theme variables.
While this gives you a level of flexibility on the look and feel of the components you should be aware of 2 things:

Expand Down
56 changes: 45 additions & 11 deletions docs/theming/new-theme-overrides.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,6 @@ relevantForAI: true

## New Theme Override Patterns

```js
---
type: embed
---
<Alert variant="warning" margin="0 0 medium">
The examples on this page use the <strong>new theming system</strong> and require <strong>v11.7+</strong> components. If you are viewing the v11.6 version, <Link href={window.location.pathname.match(/v\d+_\d+/) ? window.location.pathname.replace(/v\d+_\d+/, 'v11_7') : `/v11_7${window.location.pathname}`}>switch to v11.7</Link> to see the examples working correctly.
</Alert>
```

This guide covers all the override patterns available in the new theming system (v11.7+). The new system uses a layered token architecture: **primitives** (raw values) -> **semantics** (meaning) -> **components** (per-component tokens).

Overrides are applied via the `themeOverride` prop on `InstUISettingsProvider`, which is separate from the `theme` prop. The `theme` prop replaces the active theme entirely; `themeOverride` layers modifications on top.
Expand Down Expand Up @@ -527,9 +518,52 @@ type: example
</InstUISettingsProvider>
```

### 13. Provider-level overrides cannot target a child component selectively
### 13. Independent overrides for child parts of compound components

Most compound components expose each part as a separate component with its own `componentId`. This means you can independently override each part via `components` — both overrides take effect:

```js
---
type: example
---
<InstUISettingsProvider theme={canvas}>
<InstUISettingsProvider
themeOverride={{
components: {
TableColHeader: {
background: 'rebeccapurple',
color: 'gold'
},
TableRowHeader: {
background: 'deeppink',
color: 'white'
}
}
}}
>
<Table caption="Independent overrides: ColHeader purple, RowHeader deeppink">
<Table.Head>
<Table.Row>
<Table.ColHeader id="row-headers">Row headers column - purple</Table.ColHeader>
<Table.ColHeader id="cells">Cells column - purple</Table.ColHeader>
</Table.Row>
</Table.Head>
<Table.Body>
<Table.Row>
<Table.RowHeader>TableRowHeader — deeppink</Table.RowHeader>
<Table.Cell>TableCell — unchanged</Table.Cell>
</Table.Row>
<Table.Row>
<Table.RowHeader>TableRowHeader — deeppink</Table.RowHeader>
<Table.Cell>TableCell — unchanged</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
</InstUISettingsProvider>
</InstUISettingsProvider>
```

Because `Button` uses `BaseButton`'s theme internally, a `components.Button` entry in the provider's `themeOverride` does **not** override `BaseButton`'s tokens for `Button` instances only. Both `BaseButton` and `Button` share the same `BaseButton` theme variables, so a `components.BaseButton` override affects both, regardless of whether a separate `components.Button` entry is also present.
**Exception — `Button` and `BaseButton`:** `Button` uses `BaseButton`'s `componentId` internally, so `components.Button` has no effect. A `components.BaseButton` override affects all `BaseButton` instances including those rendered inside `Button` — there is no way to target only one:

```js
---
Expand Down
Loading
Loading