diff --git a/workspaces/intelligent-assistant/.changeset/gentle-foxes-glow.md b/workspaces/intelligent-assistant/.changeset/gentle-foxes-glow.md new file mode 100644 index 00000000000..9bbf40617dc --- /dev/null +++ b/workspaces/intelligent-assistant/.changeset/gentle-foxes-glow.md @@ -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. diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/report-legacy.api.md b/workspaces/intelligent-assistant/plugins/intelligent-assistant/report-legacy.api.md index eea48d96949..9965c4e1cc7 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/report-legacy.api.md +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/report-legacy.api.md @@ -24,7 +24,7 @@ export type DrawerStateExposerProps = { onStateChange: (state: DrawerState) => void; }; -// @public (undocumented) +// @public export const LightspeedChatContainer: () => JSX_2.Element; // @public diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightspeedChatContainer.tsx b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightspeedChatContainer.tsx index 31688c4e1e4..3b01bd0da01 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightspeedChatContainer.tsx +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightspeedChatContainer.tsx @@ -14,7 +14,10 @@ * limitations under the License. */ -import { useEffect, useMemo, useState } from 'react'; +import '@patternfly/react-core/dist/styles/base-no-reset.css'; +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'; @@ -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); @@ -103,6 +105,10 @@ const LightspeedChatContainerInner = () => { } }, [type]); + useLayoutEffect(() => { + document.documentElement.style.containerType = 'normal'; + }, []); + // Load last selected model from localStorage useEffect(() => { if (modelsItems.length > 0) { diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightspeedChatContainerLazy.tsx b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightspeedChatContainerLazy.tsx new file mode 100644 index 00000000000..3aabb14a862 --- /dev/null +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightspeedChatContainerLazy.tsx @@ -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 = () => ( + }> + + +); diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightspeedDrawerProvider.tsx b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightspeedDrawerProvider.tsx index 560c490f541..26cd4a05136 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightspeedDrawerProvider.tsx +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightspeedDrawerProvider.tsx @@ -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 => ({ diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/__tests__/LightspeedDrawerProvider.test.tsx b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/__tests__/LightspeedDrawerProvider.test.tsx index 363edffefb3..8e9ae572025 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/__tests__/LightspeedDrawerProvider.test.tsx +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/__tests__/LightspeedDrawerProvider.test.tsx @@ -76,7 +76,7 @@ jest.mock('@patternfly/chatbot', () => { }; }); -jest.mock('../LightspeedChatContainer', () => ({ +jest.mock('../LightspeedChatContainerLazy', () => ({ LightspeedChatContainer: () => (
Chat Container
), diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/index.tsx b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/index.tsx index c09ede2ca7c..6013a0e4d9c 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/index.tsx +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/index.tsx @@ -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'; @@ -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 { diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/legacy.ts b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/legacy.ts index b18235b19d2..8eb45509ed8 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/legacy.ts +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/legacy.ts @@ -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 => @@ -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, diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/plugin.ts b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/plugin.ts index 641ed79222e..6439d36e7b1 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/plugin.ts +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/plugin.ts @@ -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 {