Re-establish the Theme Outside the Chat Shell
The SDK's design tokens (--asg-color-*, radii, spacing) are emitted onto the
Chatbot container's root. Any SDK component rendered outside that subtree misses
them and falls back to the literals baked into each CSS rule — and those literals are
light-themed.
How badly it shows depends on the component: a panel like <TaskList> loses the theme's
accent and border colors (toggle the demo below and watch the border and spinner),
while <FileExplorerPanel> — large and mostly filled surfaces — comes out flat white on
a dark page.
Re-establish the Theme Outside the Chat Shell
The SDK's design tokens (--asg-color-*, radii, spacing) are emitted onto the Chatbot container's root. Any SDK component rendered outside that subtree — a consumer-placed <TaskList>, <SubagentList> or <FileExplorerPanel> — misses them and falls back to the literals baked into each rule, which are light-themed. <AsgardThemeScope> re-establishes the same tokens somewhere else.
A TaskList placed outside the Chatbot
import { AsgardThemeScope, FileExplorerPanel } from '@asgard-js/react';
const theme = {
chatbot: {
backgroundColor: '#1a1430',
borderColor: '#6d4aff',
primaryComponent: { mainColor: '#7c5cff' },
},
};
<Chatbot theme={theme} {...rest} />
// anywhere outside the chat shell
<AsgardThemeScope theme={theme}>
<FileExplorerPanel {...panelProps} />
</AsgardThemeScope>Toggle it: wrapped, the panel's border and spinner take the theme's purple and match the Chatbot on the right; unwrapped, they fall back to the built-in defaults (grey border, amber spinner). Pass the same object you give <Chatbot theme> to <AsgardThemeScope theme> so both surfaces stay in step. It is unnecessary inside <Chatbot> — the shell already scopes the tokens.
Usage
Wrap the components you place outside, passing the same object you give
<Chatbot theme>:
import { AsgardThemeScope, FileExplorerPanel } from "@asgard-js/react";
const theme = {
chatbot: {
backgroundColor: "#1a1430",
borderColor: "#6d4aff",
primaryComponent: { mainColor: "#7c5cff" },
},
};
<Chatbot theme={theme} {...rest} />
// anywhere outside the chat shell
<AsgardThemeScope theme={theme}>
<FileExplorerPanel {...panelProps} />
</AsgardThemeScope>
Passing the same object to both is what keeps the two surfaces in step.
Props
<AsgardThemeScope
theme={theme} // same shape as <Chatbot theme>, optional
className="..." // optional
style={{ ... }} // optional
>
Besides the tokens it also establishes the font and box-model baseline these components expect.
When You Need It
| Situation | Needed? |
|---|---|
The component is inside <Chatbot> | No — the shell already scopes the tokens |
A self-docked <TaskList> / <SubagentList> | Yes |
A consumer-placed <FileExplorerPanel> | Yes |
Anything drawn by renderFooter / renderHeader | No — those still render inside the shell |
The test is simple: is the component rendered inside <Chatbot>'s DOM subtree?
See Also
- Theme — what the theme object actually contains
- Dock the Run-Chrome Yourself
- File Explorer