Make the theme a prop, next to the language

The theme is state — what Element Call should look like right now — and
so belongs beside `language` as a prop, not on the imperative handle
(where it was a request, `setTheme`, because the internal host bridge
speaks the widget API and a widget's host sends theme changes as
requests) and not in the configuration (where `config.theme` only ever
set the starting theme).

The `theme` prop feeds the same channel the rest of Element Call listens
to for a host's theme, replayed so that whatever subscribes after the
host has set it still hears the current one. Changing it re-themes the
container and nothing else; unlike the language, it is per component.
`setTheme` and `config.theme` are gone, and the harness gets a theme
picker in place of its per-pane buttons.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Timo K.
2026-09-08 17:02:24 +02:00
co-authored by Claude Fable 5.1
parent f994586eeb
commit b722cc277e
5 changed files with 89 additions and 48 deletions
+16 -9
View File
@@ -111,14 +111,15 @@ export {
* takes the default that {@link ElementCallProps.intent} implies.
*
* This is the behaviour a widget can be configured with through its URL, plus
* the two facts about the call a host has a say in: the theme to start in and
* the background. The rest of what a widget's URL carries — who the user is,
* how to reach the homeserver, where to report analytics, the shared secret of
* a room that is encrypted with one — a component host supplies by other
* routes, or not at all.
* the one fact about the call a host has a say in here, the background. The
* rest of what a widget's URL carries — who the user is, how to reach the
* homeserver, where to report analytics, the shared secret of a room that is
* encrypted with one — a component host supplies by other routes, or not at
* all; and what can change while the call is running, the theme and the
* language, is a prop of its own.
*/
export type ElementCallConfiguration = Partial<UrlConfiguration> &
Partial<Pick<UrlProperties, "theme" | "background">>;
Partial<Pick<UrlProperties, "background">>;
export interface ElementCallProps {
/**
@@ -154,10 +155,15 @@ export interface ElementCallProps {
*/
hostBridge?: ElementCallHostBridge;
/**
* What the host tells Element Call: to change theme, to hang up, to mute.
* Available once the component has rendered.
* What the host tells Element Call: to hang up, to mute, to join. Available
* once the component has rendered.
*/
ref?: Ref<ElementCallHandle>;
/**
* The theme to show Element Call in, `light` or `dark`. Left out, Element
* Call picks. Changes take effect at once, and cost nothing else.
*/
theme?: string;
/**
* The language to show Element Call in, as a BCP 47 tag: one of
* {@link supportedLanguages}, or something that falls back to one (`de-AT`
@@ -229,9 +235,10 @@ export const ElementCall: FC<ElementCallProps> = ({
config,
hostBridge: suppliedHostBridge,
ref,
theme,
language,
}): ReactNode => {
const hostBridge = useComponentHostBridge(suppliedHostBridge, ref);
const hostBridge = useComponentHostBridge(suppliedHostBridge, ref, theme);
useEffect(() => {
if (language !== undefined)