Skip to content

Commit

Permalink
Reflect theme changes without a refresh
Browse files Browse the repository at this point in the history
By leveraging `IThemeManager.themeChanged`, we can listen on theme change signals
and rebuild the theme object in response. This allows CSS variable changes to reflect
in the MUI theme without having to refresh the page.
  • Loading branch information
gchow committed Jan 11, 2024
1 parent 814eb44 commit d47f56c
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 2 deletions.
7 changes: 6 additions & 1 deletion packages/jupyter-ai/src/components/jl-theme-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';

import { Theme, ThemeProvider, createTheme } from '@mui/material/styles';
import { getJupyterLabTheme } from '../theme-provider';
import { getJupyterLabTheme, getThemeManager } from '../theme-provider';

export function JlThemeProvider(props: {
children: React.ReactNode;
Expand All @@ -13,6 +13,11 @@ export function JlThemeProvider(props: {
setTheme(await getJupyterLabTheme());
}
setJlTheme();

const manager = getThemeManager();
if (manager) {
manager.themeChanged.connect(setJlTheme);
}
}, []);

return <ThemeProvider theme={theme}>{props.children}</ThemeProvider>;
Expand Down
14 changes: 13 additions & 1 deletion packages/jupyter-ai/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ import {
ILayoutRestorer
} from '@jupyterlab/application';

import { IWidgetTracker, ReactWidget } from '@jupyterlab/apputils';
import {
IWidgetTracker,
ReactWidget,
IThemeManager
} from '@jupyterlab/apputils';
import { IDocumentWidget } from '@jupyterlab/docregistry';
import { IGlobalAwareness } from '@jupyter/collaboration';
import type { Awareness } from 'y-protocols/awareness';
import { buildChatSidebar } from './widgets/chat-sidebar';
import { SelectionWatcher } from './selection-watcher';
import { ChatHandler } from './chat_handler';
import { buildErrorWidget } from './widgets/chat-error';
import { setThemeManager } from './theme-provider';

export type DocumentTracker = IWidgetTracker<IDocumentWidget>;

Expand All @@ -22,8 +27,10 @@ const plugin: JupyterFrontEndPlugin<void> = {
id: 'jupyter_ai:plugin',
autoStart: true,
optional: [IGlobalAwareness, ILayoutRestorer],
requires: [IThemeManager],
activate: async (
app: JupyterFrontEnd,
manager: IThemeManager,
globalAwareness: Awareness | null,
restorer: ILayoutRestorer | null
) => {
Expand Down Expand Up @@ -57,6 +64,11 @@ const plugin: JupyterFrontEndPlugin<void> = {
if (restorer) {
restorer.add(chatWidget, 'jupyter-ai-chat');
}

/**
* Set the theme manager
*/
setThemeManager(manager);
}
};

Expand Down
11 changes: 11 additions & 0 deletions packages/jupyter-ai/src/theme-provider.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { IThemeManager } from '@jupyterlab/apputils';
import { Theme, createTheme } from '@mui/material/styles';

let themeManager: IThemeManager | null = null;

function getCSSVariable(name: string): string {
return getComputedStyle(document.body).getPropertyValue(name).trim();
}
Expand All @@ -10,6 +13,14 @@ export async function pollUntilReady(): Promise<void> {
}
}

export function setThemeManager(manager: IThemeManager): void {
themeManager = manager;
}

export function getThemeManager(): IThemeManager | null {
return themeManager;
}

export async function getJupyterLabTheme(): Promise<Theme> {
await pollUntilReady();
const light = document.body.getAttribute('data-jp-theme-light');
Expand Down

0 comments on commit d47f56c

Please sign in to comment.