diff --git a/.storybook/main.ts b/.storybook/main.ts index a62960db85..865ae90848 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -13,7 +13,7 @@ const isChromatic = process.env.STORYBOOK_STORY_SET === 'chromatic'; // All stories for full development const allStories = isChromatic - ? ['packages/ui'] + ? ['packages/ui', 'plugins/app'] : [ 'packages/ui', 'packages/core-components', diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 022b6123e2..916c48951d 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -6,7 +6,7 @@ import { definePreview } from '@storybook/react-vite'; import React, { useEffect } from 'react'; import { TestApiProvider } from '@backstage/test-utils'; import { AlertDisplay } from '@backstage/core-components'; -import { apis } from './support/apis'; +import { apis, appThemeApi } from './support/apis'; import { useGlobals } from 'storybook/preview-api'; import { UnifiedThemeProvider, themes } from '@backstage/theme'; import { allModes } from './modes'; @@ -157,6 +157,10 @@ export default definePreview({ }; }, [selectedTheme, selectedThemeName]); + useEffect(() => { + appThemeApi.setActiveThemeId(selectedThemeMode); + }, [selectedThemeMode]); + document.body.style.backgroundColor = 'var(--bui-bg-app)'; document.body.style.padding = isFullscreen && selectedBackground !== 'app' ? '1rem' : ''; diff --git a/.storybook/support/apis.js b/.storybook/support/apis.js index 905c5f2dc8..42085591c0 100644 --- a/.storybook/support/apis.js +++ b/.storybook/support/apis.js @@ -1,5 +1,6 @@ import { AlertApiForwarder, + AppThemeSelector, ErrorAlerter, ErrorApiForwarder, GithubAuth, @@ -13,6 +14,7 @@ import { import { alertApiRef, + appThemeApiRef, errorApiRef, githubAuthApiRef, gitlabAuthApiRef, @@ -24,10 +26,16 @@ import { featureFlagsApiRef, } from '@backstage/core-plugin-api'; +import { themes } from '@backstage/theme'; + import { translationApiRef } from '@backstage/core-plugin-api/alpha'; import { MockTranslationApi } from '@backstage/test-utils/alpha'; const configApi = new ConfigReader({}); +export const appThemeApi = AppThemeSelector.createWithStorage([ + { id: 'light', title: 'Light', variant: 'light', theme: themes.light }, + { id: 'dark', title: 'Dark', variant: 'dark', theme: themes.dark }, +]); const featureFlagsApi = new LocalStorageFeatureFlags(); const alertApi = new AlertApiForwarder(); const errorApi = new ErrorAlerter(alertApi, new ErrorApiForwarder()); @@ -62,6 +70,7 @@ const translationApi = MockTranslationApi.create(); export const apis = [ [configApiRef, configApi], + [appThemeApiRef, appThemeApi], [featureFlagsApiRef, featureFlagsApi], [alertApiRef, alertApi], [errorApiRef, errorApi], diff --git a/plugins/app/src/components/Toast/Toast.stories.tsx b/plugins/app/src/components/Toast/Toast.stories.tsx index f008bc2550..10eb05476d 100644 --- a/plugins/app/src/components/Toast/Toast.stories.tsx +++ b/plugins/app/src/components/Toast/Toast.stories.tsx @@ -28,7 +28,7 @@ const toastQueue = new ToastQueue({ }); const meta = preview.meta({ - title: 'Plugins/App/Toast', + title: 'App/Toast', component: ToastContainer, parameters: { layout: 'centered', @@ -157,6 +157,35 @@ export const Default = meta.story({ ), }); +const previewQueue = new ToastQueue({ + maxVisibleToasts: 4, +}); +previewQueue.add({ + title: 'Changes saved successfully', + description: 'Your changes have been saved.', + status: 'success', +}); + +export const PreviewToast = meta.story({ + render: () => , +}); + +const timerQueue = new ToastQueue({ + maxVisibleToasts: 4, +}); +timerQueue.add( + { + title: 'Auto-dismissing in 5 seconds', + description: 'This toast will disappear automatically.', + status: 'info', + }, + { timeout: 5000 }, +); + +export const PreviewToastWithTimer = meta.story({ + render: () => , +}); + export const StatusVariants = meta.story({ render: () => ( <> @@ -557,113 +586,4 @@ export const AlertApiIntegration = meta.story({ }, }); -/** - * This story tests the real AlertApi integration. - * It uses the alertApi from the TestApiProvider (set up in storybook preview) - * and shows how alerts posted via alertApi.post() appear. - * - * Note: The storybook preview.tsx renders AlertDisplay from core-components, - * which still uses Material UI. To test the new ToastDisplay, run the actual - * Backstage app where the app plugin's elements.tsx is used. - */ -function RealAlertApiStory() { - // eslint-disable-next-line @backstage/no-relative-monorepo-imports - const { useApi, alertApiRef } = require('@backstage/core-plugin-api'); - const alertApi = useApi(alertApiRef); - - return ( - - - - Real AlertApi Test - - - These buttons call alertApi.post() directly. Alerts appear in the OLD - AlertDisplay (top of screen) because Storybook uses core-components. - - - To test the NEW ToastDisplay, run: yarn start - - - - - - - - - - - - - - ); -} - -export const RealAlertApi = meta.story({ - name: 'Real AlertApi Test', - render: () => , -}); - export default meta;