Skip to content

Commit 264f681

Browse files
committed
docs: add branding examples to new-theme-overrides
1 parent 50a4f82 commit 264f681

1 file changed

Lines changed: 262 additions & 0 deletions

File tree

docs/theming/new-theme-overrides.md

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,268 @@ type: example
601601
</InstUISettingsProvider>
602602
```
603603
604+
### 15. Branding (user customizable theming)
605+
606+
The new theming system exposes the equivalents of the legacy Canvas `ic-brand-*` variables under `semantics.color.institutional.*`. Overriding these has the same broad effect as Canvas's [Theme Editor](https://community.canvaslms.com/t5/Admin-Guide/How-do-I-create-a-theme-for-an-account-using-the-Theme-Editor/ta-p/242) — the Button family, `SideNavBar`, `Link`, `Billboard`, and several other components consume them automatically.
607+
608+
| Legacy variable | New semantic token |
609+
| --------------------------------------------------- | --------------------------------------- |
610+
| `ic-brand-primary` | `brandPrimary` |
611+
| `ic-brand-font-color-dark` | `brandFontColorDark` |
612+
| `ic-link-color` | `linkColor` |
613+
| `ic-brand-button--primary-bgd` | `brandButtonPrimaryBgd` |
614+
| `ic-brand-button--primary-text` | `brandButtonPrimaryText` |
615+
| `ic-brand-global-nav-bgd` | `brandGlobalNavBgd` |
616+
| `ic-global-nav-link-hover` | `globalNavLinkHover` |
617+
| `ic-brand-global-nav-menu-item__text-color` | `brandGlobalNavMenuItemTextColor` |
618+
| `ic-brand-global-nav-menu-item__text-color--active` | `brandGlobalNavMenuItemTextColorActive` |
619+
620+
A handful of legacy variables are not in the new system, for two different reasons:
621+
622+
- **SVG icon-fill variables** (`ic-brand-global-nav-ic-icon-svg-fill` and `--active`) — these _were_ consumed by the `v11.6` to recolor its icons, but `v11.7` uses a different icon-coloring mechanism so they were not migrated.
623+
- **Variables that no InstUI component ever consumed** (`ic-brand-button--secondary-bgd`, `ic-brand-button--secondary-text`, `ic-link-decoration`)
624+
625+
#### Common variables — broad-impact branding
626+
627+
`brandPrimary` is the main brand color hook — consumed by the Tabs active indicator, `Badge` primary color, `RangeInput` handle, `TableRow` hover border, and several other accent colors. `brandFontColorDark` is the default dark text color used across many components.
628+
629+
> **Heads up:** unlike the legacy `ic-brand-primary`, in the new system `brandPrimary` **no longer drives** the secondary `Button` border or the `TextInput` focus ring. Focus rings are now centrally controlled via `sharedTokens.focusOutline` — see the [Overriding shared tokens](#new-theme-overrides) section above to customize them.
630+
631+
```ts
632+
---
633+
type: example
634+
---
635+
const Example = () => {
636+
const [brandPrimary, setBrandPrimary] = useState(canvas['ic-brand-primary'])
637+
const [brandFontColorDark, setBrandFontColorDark] = useState(canvas['ic-brand-font-color-dark'])
638+
639+
return (
640+
<div>
641+
<Flex gap="small">
642+
<Flex.Item size="45%">
643+
<TextInput
644+
renderLabel="brandPrimary"
645+
value={brandPrimary}
646+
onChange={(e, v) => setBrandPrimary(v)}
647+
messages={[{text:'Tabs indicator, Badge, RangeInput handle, etc.', type:'hint'}]}
648+
/>
649+
</Flex.Item>
650+
<Flex.Item size="45%">
651+
<TextInput
652+
renderLabel="brandFontColorDark"
653+
value={brandFontColorDark}
654+
onChange={(e, v) => setBrandFontColorDark(v)}
655+
messages={[{text:'default dark text color in many components', type:'hint'}]}
656+
/>
657+
</Flex.Item>
658+
</Flex>
659+
<hr style={{width:'100%', margin:'2rem 0 1rem'}}/>
660+
<InstUISettingsProvider theme={canvas}>
661+
<InstUISettingsProvider
662+
themeOverride={{
663+
semantics: {
664+
color: {
665+
institutional: { brandPrimary, brandFontColorDark }
666+
}
667+
}
668+
}}
669+
>
670+
<Tabs>
671+
<Tabs.Panel id="tabA" renderTitle="Tab A" isSelected={true}></Tabs.Panel>
672+
<Tabs.Panel id="tabB" renderTitle="Tab B"></Tabs.Panel>
673+
<Tabs.Panel id="tabC" renderTitle="Tab C"></Tabs.Panel>
674+
</Tabs>
675+
<Flex gap="medium" margin="medium 0 0 0">
676+
<Flex.Item>
677+
<Badge count={42} countUntil={100} margin="0 medium 0 0">
678+
<Button color="secondary">Notifications</Button>
679+
</Badge>
680+
</Flex.Item>
681+
<Flex.Item shouldGrow>
682+
<Text>Default body text — uses brandFontColorDark.</Text>
683+
</Flex.Item>
684+
</Flex>
685+
</InstUISettingsProvider>
686+
</InstUISettingsProvider>
687+
</div>
688+
)
689+
}
690+
691+
render(<Example/>)
692+
```
693+
694+
#### `Button` branding
695+
696+
These semantics only affect the `primary` color `Button`.
697+
698+
```ts
699+
---
700+
type: example
701+
---
702+
const Example = () => {
703+
const [brandButtonPrimaryBgd, setBrandButtonPrimaryBgd] = useState(canvas['ic-brand-button--primary-bgd'])
704+
const [brandButtonPrimaryText, setBrandButtonPrimaryText] = useState(canvas['ic-brand-button--primary-text'])
705+
706+
return (
707+
<div>
708+
<Flex gap="small">
709+
<Flex.Item size="45%">
710+
<TextInput
711+
renderLabel="brandButtonPrimaryBgd"
712+
value={brandButtonPrimaryBgd}
713+
onChange={(e, v) => setBrandButtonPrimaryBgd(v)}
714+
messages={[{text:"primary Button background", type:'hint'}]}
715+
/>
716+
</Flex.Item>
717+
<Flex.Item size="45%">
718+
<TextInput
719+
renderLabel="brandButtonPrimaryText"
720+
value={brandButtonPrimaryText}
721+
onChange={(e, v) => setBrandButtonPrimaryText(v)}
722+
messages={[{text:"primary Button text color", type:'hint'}]}
723+
/>
724+
</Flex.Item>
725+
</Flex>
726+
<hr style={{width:'100%', margin:'2rem 0 1rem'}}/>
727+
<InstUISettingsProvider theme={canvas}>
728+
<InstUISettingsProvider
729+
themeOverride={{
730+
semantics: {
731+
color: {
732+
institutional: { brandButtonPrimaryBgd, brandButtonPrimaryText }
733+
}
734+
}
735+
}}
736+
>
737+
<Button color="primary">I'm a 'primary' color button</Button>
738+
</InstUISettingsProvider>
739+
</InstUISettingsProvider>
740+
</div>
741+
)
742+
}
743+
744+
render(<Example/>)
745+
```
746+
747+
#### `Link` and `Billboard` branding
748+
749+
`linkColor` is used by non-inverse `Link` and by clickable `Billboard`.
750+
751+
```ts
752+
---
753+
type: example
754+
---
755+
const Example = () => {
756+
const [linkColor, setLinkColor] = useState(canvas['ic-link-color'])
757+
758+
return (
759+
<div>
760+
<Flex gap="small">
761+
<Flex.Item size="60%">
762+
<TextInput
763+
renderLabel="linkColor"
764+
value={linkColor}
765+
onChange={(e, v) => setLinkColor(v)}
766+
messages={[{text:'used by non-inverse Link and clickable Billboard', type:'hint'}]}
767+
/>
768+
</Flex.Item>
769+
</Flex>
770+
<hr style={{width:'100%', margin:'2rem 0 1rem'}}/>
771+
<InstUISettingsProvider theme={canvas}>
772+
<InstUISettingsProvider
773+
themeOverride={{
774+
semantics: {
775+
color: {
776+
institutional: { linkColor }
777+
}
778+
}
779+
}}
780+
>
781+
<Flex gap="small">
782+
<Flex.Item size="50%">
783+
<Link href="https://instructure.github.io/instructure-ui/">normal link</Link>
784+
</Flex.Item>
785+
<Flex.Item size="50%">
786+
<Billboard
787+
margin="small"
788+
message="Billboard with link"
789+
href="http://instructure.com"
790+
hero={(size) => <IconGradebookLine size={size} />}
791+
/>
792+
</Flex.Item>
793+
</Flex>
794+
</InstUISettingsProvider>
795+
</InstUISettingsProvider>
796+
</div>
797+
)
798+
}
799+
800+
render(<Example/>)
801+
```
802+
803+
#### `SideNavBar` branding
804+
805+
These semantics control the `SideNavBar` background, hover state, and menu item text colors — for both default and active states.
806+
807+
```ts
808+
---
809+
type: example
810+
---
811+
const Example = () => {
812+
const [brandGlobalNavBgd, setBrandGlobalNavBgd] = useState(canvas['ic-brand-global-nav-bgd'])
813+
const [globalNavLinkHover, setGlobalNavLinkHover] = useState(canvas['ic-global-nav-link-hover'])
814+
const [brandGlobalNavMenuItemTextColor, setBrandGlobalNavMenuItemTextColor] = useState(canvas['ic-brand-global-nav-menu-item__text-color'])
815+
const [brandGlobalNavMenuItemTextColorActive, setBrandGlobalNavMenuItemTextColorActive] = useState(canvas['ic-brand-global-nav-menu-item__text-color--active'])
816+
817+
return (
818+
<div>
819+
<Flex gap="small">
820+
<Flex.Item size="45%">
821+
<TextInput renderLabel="brandGlobalNavBgd" value={brandGlobalNavBgd} onChange={(e, v) => setBrandGlobalNavBgd(v)}/>
822+
<TextInput renderLabel="globalNavLinkHover" value={globalNavLinkHover} onChange={(e, v) => setGlobalNavLinkHover(v)}/>
823+
</Flex.Item>
824+
<Flex.Item size="45%">
825+
<TextInput renderLabel="brandGlobalNavMenuItemTextColor" value={brandGlobalNavMenuItemTextColor} onChange={(e, v) => setBrandGlobalNavMenuItemTextColor(v)}/>
826+
<TextInput renderLabel="brandGlobalNavMenuItemTextColorActive" value={brandGlobalNavMenuItemTextColorActive} onChange={(e, v) => setBrandGlobalNavMenuItemTextColorActive(v)}/>
827+
</Flex.Item>
828+
</Flex>
829+
<hr style={{width:'100%', margin:'2rem 0 1rem'}}/>
830+
<InstUISettingsProvider theme={canvas}>
831+
<InstUISettingsProvider
832+
themeOverride={{
833+
semantics: {
834+
color: {
835+
institutional: {
836+
brandGlobalNavBgd,
837+
globalNavLinkHover,
838+
brandGlobalNavMenuItemTextColor,
839+
brandGlobalNavMenuItemTextColorActive
840+
}
841+
}
842+
}
843+
}}
844+
>
845+
<SideNavBar
846+
label="Main navigation"
847+
toggleLabel={{
848+
expandedLabel: 'Minimize SideNavBar',
849+
minimizedLabel: 'Expand SideNavBar'
850+
}}
851+
>
852+
<SideNavBar.Item icon={<IconUserLine />} label="Home" href="#" />
853+
<SideNavBar.Item icon={<IconAdminLine />} label="Admin" href="#" />
854+
<SideNavBar.Item selected icon={<IconDashboardLine />} label="Dashboard" href="#" />
855+
<SideNavBar.Item icon={<IconInboxLine />} label="Inbox" href="#" />
856+
</SideNavBar>
857+
</InstUISettingsProvider>
858+
</InstUISettingsProvider>
859+
</div>
860+
)
861+
}
862+
863+
render(<Example/>)
864+
```
865+
604866
### Override priority (highest to lowest)
605867

606868
1. **Per-component `themeOverride` prop** - affects a single instance

0 commit comments

Comments
 (0)