Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@red-hat-developer-hub/backstage-plugin-intelligent-assistant': patch
---

Scope PatternFly CSS imports to the chatbot component and use useLayoutEffect for dark theme class toggle to prevent white background leak on dark themes.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export type DrawerStateExposerProps = {
onStateChange: (state: DrawerState) => void;
};

// @public (undocumented)
// @public
export const LightspeedChatContainer: () => JSX_2.Element;

// @public
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
* limitations under the License.
*/

import { useEffect, useMemo, useState } from 'react';
import '@patternfly/react-core/dist/styles/base-no-reset.css';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] correctness

CSS imports in LightspeedChatContainer.tsx still load eagerly through static import chains in index.tsx (line 47) and legacy.ts (line 33). The CSS deferral benefit described in the PR only applies to the lazy path in plugin.ts. The useLayoutEffect change is the actual effective fix for the white flash.

Suggested fix: For full CSS deferral, convert the static import in index.tsx to a dynamic import() and have legacy.ts re-export the lazy extension from plugin.ts instead of the raw component.

import '@patternfly/chatbot/dist/css/main.css';

import { useEffect, useLayoutEffect, useMemo, useState } from 'react';
import { useAsync } from 'react-use';

import { identityApiRef, useApi } from '@backstage/core-plugin-api';
Expand Down Expand Up @@ -93,8 +96,7 @@ const LightspeedChatContainerInner = () => {
[models],
);

// Handle dark theme class on document
useEffect(() => {
useLayoutEffect(() => {
const htmlTagElement = document.documentElement;
if (type === THEME_DARK) {
htmlTagElement.classList.add(THEME_DARK_CLASS);
Expand All @@ -103,6 +105,10 @@ const LightspeedChatContainerInner = () => {
}
}, [type]);

useLayoutEffect(() => {
document.documentElement.style.containerType = 'normal';
}, []);

// Load last selected model from localStorage
useEffect(() => {
if (modelsItems.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { lazy, Suspense } from 'react';

import { LightspeedChatModelsLoading } from './LightspeedChatModelsState';

const LazyLightspeedChatContainer = lazy(() =>
import('./LightspeedChatContainer').then(m => ({
default: m.LightspeedChatContainer,
})),
);

/**
* Lazy wrapper around LightspeedChatContainer that defers loading of
* PatternFly CSS until the component is actually rendered, preventing
* global :root variable overrides from leaking into the host app theme.
*
* @public
*/
export const LightspeedChatContainer = () => (
<Suspense fallback={<LightspeedChatModelsLoading />}>
<LazyLightspeedChatContainer />
</Suspense>
);
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { ChatbotModal } from '@patternfly/chatbot';

import { DOCKED_CONTENT_OFFSET } from '../const';
import { useLightspeedProviderState } from '../hooks/useLightspeedProviderState';
import { LightspeedChatContainer } from './LightspeedChatContainer';
import { LightspeedChatContainer } from './LightspeedChatContainerLazy';
import { LightspeedDrawerContext } from './LightspeedDrawerContext';

const useStyles = makeStyles(theme => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jest.mock('@patternfly/chatbot', () => {
};
});

jest.mock('../LightspeedChatContainer', () => ({
jest.mock('../LightspeedChatContainerLazy', () => ({
LightspeedChatContainer: () => (
<div data-testid="lightspeed-chat-container">Chat Container</div>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@
* limitations under the License.
*/

import { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className';

import '@patternfly/react-core/dist/styles/base-no-reset.css';
import '@patternfly/chatbot/dist/css/main.css';

import { useEffect, type ReactNode } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';

Expand All @@ -38,13 +33,15 @@ import {
TranslationBlueprint,
} from '@backstage/plugin-app-react';

import { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className';

import { AppDrawerContentBlueprint } from '@red-hat-developer-hub/backstage-plugin-app-react/alpha';

import { lightspeedApiRef } from './api/api';
import { LightspeedApiClient } from './api/LightspeedApiClient';
import { notebooksApiRef } from './api/notebooksApi';
import { NotebooksApiClient } from './api/NotebooksApiClient';
import { LightspeedChatContainer as LightspeedChatContainerElement } from './components/LightspeedChatContainer';
import { LightspeedChatContainer as LightspeedChatContainerElement } from './components/LightspeedChatContainerLazy';
import { LightspeedDrawerProvider as LightspeedProvider } from './components/LightspeedDrawerProvider';
import { LightspeedFABContent as LightspeedFABComponent } from './components/LightspeedFABContent';
import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
* limitations under the License.
*/

import '@patternfly/react-core/dist/styles/base-no-reset.css';
import '@patternfly/chatbot/dist/css/main.css';

import { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className';

ClassNameGenerator.configure(componentName =>
Expand All @@ -30,7 +27,7 @@ export {
} from './plugin';
export { LightspeedIcon } from './components/LightspeedIcon';
export { LightspeedFAB } from './components/LightspeedFAB';
export { LightspeedChatContainer } from './components/LightspeedChatContainer';
export { LightspeedChatContainer } from './components/LightspeedChatContainerLazy';
export { LightspeedDrawerStateExposer } from './components/LightspeedDrawerStateExposer';
export type {
DrawerStateExposerProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
* limitations under the License.
*/

import '@patternfly/react-core/dist/styles/base-no-reset.css';
import '@patternfly/chatbot/dist/css/main.css';

import { PropsWithChildren } from 'react';

import {
Expand Down
Loading