Skip to content

Commit 30e5d44

Browse files
committed
docs(many): fix default theme variables sections on component docs pages
1 parent 9618859 commit 30e5d44

30 files changed

Lines changed: 105 additions & 30 deletions

File tree

packages/__docs__/buildScripts/DataTypes.mts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,14 @@ type ResolvedColors = {
149149
semantic: Record<string, string>
150150
}
151151

152+
// At runtime, build-docs.mts also attaches `resolvedComponents` (and on
153+
// canvas / canvas-high-contrast: `key`, `description`) to the new-system
154+
// entries. Not declared per-branch; surfaced as optional on `MainDocsData.themes`.
152155
type ThemeResource =
153156
| (BaseTheme & { resolvedComponents: Record<string, any> }) // legacy-canvas, legacy-canvas-high-contrast
154157
| (NewBaseTheme & { resolvedColors: ResolvedColors }) // canvas, canvas-high-contrast
155-
| (LightTheme & { resolvedColors: ResolvedColors })
156-
| (DarkTheme & { resolvedColors: ResolvedColors })
158+
| (LightTheme & { resolvedColors: ResolvedColors }) // light
159+
| (DarkTheme & { resolvedColors: ResolvedColors }) // dark
157160
| SharedTokens
158161

159162
type MainDocsData = {

packages/__docs__/buildScripts/build-docs.mts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -420,17 +420,44 @@ function parseThemes() {
420420
parsed['legacy-canvas-high-contrast'] = {
421421
resource: { ...canvasHighContrast, resolvedComponents: resolveComponents(legacyCanvasHighContrast) }
422422
}
423+
// `key` is read by Document.tsx's `componentDidUpdate` to detect theme
424+
// changes and refetch the Default Theme Variables. `legacyCanvas` /
425+
// `legacyCanvasHighContrast` from `newThemeTokens` do not include a `key`
426+
// field (unlike `light` / `dark`, which come through wrappers that set it).
427+
// Without it, switching e.g. canvas (legacy) → canvas-high-contrast (legacy)
428+
// on v11_7 leaves `themeVariables.key` `undefined` on both sides, so
429+
// `undefined !== undefined` is false and the refetch never fires.
423430
parsed['canvas'] = {
424-
resource: { ...legacyCanvas, resolvedColors: resolveNewThemeColors(legacyCanvas), description: canvas.description }
431+
resource: {
432+
...legacyCanvas,
433+
key: 'canvas',
434+
resolvedColors: resolveNewThemeColors(legacyCanvas),
435+
resolvedComponents: resolveComponents(legacyCanvas),
436+
description: canvas.description
437+
}
425438
}
426439
parsed['canvas-high-contrast'] = {
427-
resource: { ...legacyCanvasHighContrast, resolvedColors: resolveNewThemeColors(legacyCanvasHighContrast), description: canvasHighContrast.description }
440+
resource: {
441+
...legacyCanvasHighContrast,
442+
key: 'canvas-high-contrast',
443+
resolvedColors: resolveNewThemeColors(legacyCanvasHighContrast),
444+
resolvedComponents: resolveComponents(legacyCanvasHighContrast),
445+
description: canvasHighContrast.description
446+
}
428447
}
429448
parsed[light.key] = {
430-
resource: { ...light, resolvedColors: resolveNewThemeColors(light.newTheme as typeof legacyCanvas) }
449+
resource: {
450+
...light,
451+
resolvedColors: resolveNewThemeColors(light.newTheme as typeof legacyCanvas),
452+
resolvedComponents: resolveComponents(light.newTheme as typeof legacyCanvas)
453+
}
431454
}
432455
parsed[dark.key] = {
433-
resource: { ...dark, resolvedColors: resolveNewThemeColors(dark.newTheme as typeof legacyCanvas) }
456+
resource: {
457+
...dark,
458+
resolvedColors: resolveNewThemeColors(dark.newTheme as typeof legacyCanvas),
459+
resolvedComponents: resolveComponents(dark.newTheme as typeof legacyCanvas)
460+
}
434461
}
435462
const canvasSemantics = legacyCanvas.semantics(legacyCanvas.primitives)
436463
parsed['shared-tokens'] = { resource: legacyCanvas.sharedTokens(canvasSemantics) }

packages/__docs__/src/App/index.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,13 @@ class App extends Component<AppProps, AppState> {
602602
const allThemeKeys = Object.keys(this.state.docsData!.themes)
603603
const showNewThemes = selectedMinorVersion !== 'v11_6'
604604

605+
// The `parsed.themes` map in build-docs.mts contains both:
606+
// - `canvas` / `canvas-high-contrast` → new-system resources (primitives/semantics/sharedTokens/components`)
607+
// - `legacy-canvas` / `legacy-canvas-high-contrast` → legacy wrappers (full theme object)
608+
// v11_6 components' `generateComponentTheme(theme)` reads `theme.colors`,
609+
// `theme.spacing`, etc., so v11_6 MUST be backed by the legacy wrappers.
610+
// We pick `legacy-*` as the actual selected keys, and strip the prefix for
611+
// display so the user still sees "canvas" / "canvas-high-contrast".
605612
const themeKeys = showNewThemes
606613
? allThemeKeys.filter(
607614
(k) =>
@@ -610,7 +617,7 @@ class App extends Component<AppProps, AppState> {
610617
k !== 'legacy-canvas-high-contrast'
611618
)
612619
: allThemeKeys.filter(
613-
(k) => k === 'canvas' || k === 'canvas-high-contrast'
620+
(k) => k === 'legacy-canvas' || k === 'legacy-canvas-high-contrast'
614621
)
615622

616623
const displayThemeName = (themeKey: string) => {
@@ -620,6 +627,10 @@ class App extends Component<AppProps, AppState> {
620627
) {
621628
return `${themeKey} (legacy)`
622629
}
630+
// On v11_6 strip the `legacy-` prefix so the user sees the plain names.
631+
if (!showNewThemes) {
632+
return themeKey.replace(/^legacy-/, '')
633+
}
623634
return themeKey
624635
}
625636

packages/__docs__/src/Document/index.tsx

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { View } from '@instructure/ui-view'
2929
import { Tabs } from '@instructure/ui-tabs'
3030
import type { TabsProps } from '@instructure/ui-tabs'
3131
import type { NewBaseTheme } from '@instructure/ui-themes'
32+
import type { ComponentTheme as ComponentThemeData } from '@instructure/shared-types'
3233
import { SourceCodeEditor } from '@instructure/ui-source-code-editor'
3334
import { withStyleForDocs as withStyleNew } from '../withStyleForDocs'
3435

@@ -78,47 +79,48 @@ class Document extends Component<DocumentProps, DocumentState> {
7879

7980
fetchGenerateComponentTheme = async () => {
8081
const { doc, themeVariables } = this.props
81-
let generateTheme
82-
// Doc IDs use dot notation (e.g. "Menu.Item") but theme component keys
83-
// use PascalCase without dots (e.g. "MenuItem").
84-
// New-theme entries are in themeVariables.newTheme.components.
8582
const selectedId = this.state.selectedDetailsTabId
8683
type ComponentKey = keyof NewBaseTheme['components']
84+
// When a child tab is selected, work from the child's doc/component;
85+
// otherwise from the main doc's.
8786
const childDoc =
8887
selectedId !== doc.id
8988
? doc?.children?.find((value) => value.id === selectedId)
9089
: null
91-
// in case of some components, we need to display the theme variables of other components based on themeId (like displaying the theme variables of Options in Drillsdown.Group)
90+
const currentComponentInstance =
91+
selectedId === doc.id
92+
? doc?.componentInstance
93+
: childDoc?.componentInstance
94+
// Resolve the theme registry key. Default: doc id with dots stripped
95+
// (e.g. "Menu.Item" → "MenuItem"). Two ways to override the default:
96+
// - `themeId:` in YAML frontmatter (read from childDoc.themeId) — used
97+
// when a doc page wants to show another component's tokens
98+
// (e.g. Drilldown.Group → 'Options').
99+
// - `static themeId` on the component class — used when a component
100+
// borrows another's tokens via `useTokensFrom` at runtime
101+
// (e.g. Button → 'BaseButton', ColorMixer.Slider → 'Slider').
92102
const themeKey: ComponentKey = (childDoc?.themeId ||
103+
currentComponentInstance?.themeId ||
93104
selectedId?.replace(/\./g, '')) as ComponentKey
94105
const isLegacyTheme = this.context?.componentVersion == 'v11_6'
95-
// new theme
106+
// New theme: tokens are pre-resolved into plain objects at build time
107+
// (the build emits JSON, so generator functions can't be carried through).
96108
if (!isLegacyTheme) {
97-
// resolvedComponents contains pre-computed plain objects (built at build time)
98109
const resolvedComponents = (themeVariables as Record<string, unknown>)
99110
?.resolvedComponents as Record<string, unknown> | undefined
100111
const newThemeEntry = resolvedComponents?.[themeKey as string]
101-
const componentInstance =
102-
selectedId === doc.id
103-
? doc?.componentInstance
104-
: childDoc?.componentInstance
105112
if (
106113
newThemeEntry &&
107-
typeof componentInstance?.generateComponentTheme !== 'function'
114+
typeof currentComponentInstance?.generateComponentTheme !== 'function'
108115
) {
109-
// new theme - use pre-computed theme object directly
110116
this.setState({
111117
componentTheme: newThemeEntry as DocumentState['componentTheme']
112118
})
113119
return
114120
}
115121
}
116-
// old theme - use generateComponentTheme function
117-
if (selectedId === doc.id) {
118-
generateTheme = doc?.componentInstance?.generateComponentTheme
119-
} else {
120-
generateTheme = childDoc?.componentInstance?.generateComponentTheme
121-
}
122+
// Legacy theme: call the component's generateComponentTheme directly.
123+
const generateTheme = currentComponentInstance?.generateComponentTheme
122124
if (typeof generateTheme === 'function' && themeVariables) {
123125
this.setState({ componentTheme: generateTheme(themeVariables) })
124126
} else {
@@ -179,9 +181,7 @@ class Document extends Component<DocumentProps, DocumentState> {
179181
</code>
180182
</View>
181183
) : null}
182-
<ComponentTheme
183-
componentTheme={componentTheme as any /* TODO-theme-types check */}
184-
/>
184+
<ComponentTheme componentTheme={componentTheme as ComponentThemeData} />
185185

186186
<View margin="x-large 0 0" display="block">
187187
<Heading

packages/__docs__/src/Document/props.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,16 @@ type DocumentProps = DocumentOwnProps & WithStyleProps<null, DocumentStyle>
4646

4747
type DocumentStyle = ComponentStyle<'githubCornerOctoArm' | 'githubCorner'>
4848

49+
type ResolvedNewComponentTheme = ReturnType<
50+
NewBaseTheme['components'][keyof NewBaseTheme['components']]
51+
>
52+
4953
type DocumentState = {
5054
selectedDetailsTabId: string | undefined
5155
pageRef: HTMLDivElement | null
5256
componentTheme:
5357
| ThemeVariables[keyof ThemeVariables]
54-
| NewBaseTheme['components'][keyof NewBaseTheme['components']]
58+
| ResolvedNewComponentTheme
5559
| undefined
5660
}
5761

packages/ui-buttons/src/Button/v2/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ category: components
4141
@withStyleNew(null, 'BaseButton')
4242
class Button extends Component<ButtonProps> {
4343
static readonly componentId = 'Button'
44+
// Button v2 uses BaseButton's tokens; tell Document where to look for theme variables
45+
static readonly themeId = 'BaseButton'
4446

4547
static allowedProps = allowedProps
4648
static defaultProps = {

packages/ui-buttons/src/CloseButton/v2/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ category: components
4444
@withStyleNew(generateStyle, 'BaseButton')
4545
class CloseButton extends Component<CloseButtonProps> {
4646
static readonly componentId = 'CloseButton'
47+
// Uses BaseButton's tokens; tell Document where to look for theme variables
48+
static readonly themeId = 'BaseButton'
4749

4850
static allowedProps = allowedProps
4951
static defaultProps = {

packages/ui-buttons/src/CondensedButton/v2/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ category: components
4141
@withStyleNew(null, 'BaseButton')
4242
class CondensedButton extends Component<CondensedButtonProps> {
4343
static readonly componentId = 'CondensedButton'
44+
// Uses BaseButton's tokens; tell Document where to look for theme variables
45+
static readonly themeId = 'BaseButton'
4446

4547
static allowedProps = allowedProps
4648
static defaultProps = {

packages/ui-buttons/src/IconButton/v2/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ category: components
4444
@withStyleNew(null, 'BaseButton')
4545
class IconButton extends Component<IconButtonProps> {
4646
static readonly componentId = 'IconButton'
47+
// Uses BaseButton's tokens; tell Document where to look for theme variables
48+
static readonly themeId = 'BaseButton'
4749

4850
static allowedProps = allowedProps
4951
static defaultProps = {

packages/ui-checkbox/src/Checkbox/v2/CheckboxFacade/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ parent: Checkbox
4545
@withStyleNew(generateStyle, 'Checkbox')
4646
class CheckboxFacade extends Component<CheckboxFacadeProps> {
4747
static readonly componentId = 'CheckboxFacade'
48+
static readonly themeId = 'Checkbox'
4849

4950
static allowedProps = allowedProps
5051
static defaultProps = {

0 commit comments

Comments
 (0)