From 01dbd7b3db96b5fd42c056aae38d0e17f78cea1f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 13 Sep 2025 18:34:33 +0200 Subject: [PATCH] bui-themer: more files! Signed-off-by: Patrik Oldsberg --- .../BuiThemerPage/BuiThemePreview.tsx | 143 ++++++++++ .../BuiThemerPage/BuiThemerPage.tsx | 261 +----------------- .../BuiThemerPage/MuiThemeExtractor.tsx | 42 +++ .../components/BuiThemerPage/ThemeContent.tsx | 127 +++++++++ .../src/components/BuiThemerPage/index.ts | 3 + plugins/bui-themer/src/setupTests.ts | 16 -- 6 files changed, 319 insertions(+), 273 deletions(-) create mode 100644 plugins/bui-themer/src/components/BuiThemerPage/BuiThemePreview.tsx create mode 100644 plugins/bui-themer/src/components/BuiThemerPage/MuiThemeExtractor.tsx create mode 100644 plugins/bui-themer/src/components/BuiThemerPage/ThemeContent.tsx delete mode 100644 plugins/bui-themer/src/setupTests.ts diff --git a/plugins/bui-themer/src/components/BuiThemerPage/BuiThemePreview.tsx b/plugins/bui-themer/src/components/BuiThemerPage/BuiThemePreview.tsx new file mode 100644 index 0000000000..d04cc5eabd --- /dev/null +++ b/plugins/bui-themer/src/components/BuiThemerPage/BuiThemePreview.tsx @@ -0,0 +1,143 @@ +/* + * Copyright 2025 The Backstage Authors + * + * 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 { + Button, + Card, + CardBody, + CardHeader, + Checkbox, + Flex, + Radio, + RadioGroup, + Select, + Text, + TextField, +} from '@backstage/ui'; + +interface IsolatedPreviewProps { + mode: 'light' | 'dark'; + styleObject: Record; +} + +export function BuiThemePreview({ mode, styleObject }: IsolatedPreviewProps) { + return ( +
+ + + Theme Preview + + + This preview shows how your theme will look with various Backstage + UI components + + + + + + Button Variants + + + + + + + + + + + Form Inputs + + + + - - - - Option 1 - - Option 2 - - Option 3 - - - - - - - Surface Variations - - - - Surface 1 - - - Surface 2 - - - Solid - - - - - -
- ); -} - -function ThemeContent({ - themeId, - themeTitle, - variant, - muiTheme, -}: ThemeContentProps) { - const [activeTab, setActiveTab] = useState('css'); - - const { css, styleObject } = useMemo(() => { - return convertMuiToBuiTheme(muiTheme); - }, [muiTheme]); - - const handleCopy = useCallback(() => { - window.navigator.clipboard.writeText(css); - }, [css]); - - const handleDownload = useCallback(() => { - const blob = new Blob([css], { type: 'text/css' }); - const url = URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = url; - a.download = `bui-theme-${themeId}.css`; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - URL.revokeObjectURL(url); - }, [css, themeId]); - - return ( - - - - - {themeTitle} - - {variant} theme - - - - - - - - - setActiveTab(key as string)} - > - - Generated CSS - Live Preview - - - - - {css} - - - - - - - - - - - - - ); -} - -function MuiThemeExtractor(props: { - appTheme: AppTheme; - children: (theme: Theme) => JSX.Element; -}): JSX.Element { - const { appTheme, children } = props; - const [theme, setTheme] = useState(null); - const { Provider } = appTheme; - if (theme) { - return children(theme); - } - - return ( - - - - ); -} - -function MuiThemeExtractorInner(props: { setTheme: (theme: Theme) => void }) { - props.setTheme(useTheme()); - return null; -} +import { Box, Card, Container, Flex, HeaderPage, Text } from '@backstage/ui'; +import { ThemeContent } from './ThemeContent'; +import { MuiThemeExtractor } from './MuiThemeExtractor'; export function BuiThemerPage() { const appThemeApi = useApi(appThemeApiRef); diff --git a/plugins/bui-themer/src/components/BuiThemerPage/MuiThemeExtractor.tsx b/plugins/bui-themer/src/components/BuiThemerPage/MuiThemeExtractor.tsx new file mode 100644 index 0000000000..b935720b9e --- /dev/null +++ b/plugins/bui-themer/src/components/BuiThemerPage/MuiThemeExtractor.tsx @@ -0,0 +1,42 @@ +/* + * Copyright 2025 The Backstage Authors + * + * 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 { useState } from 'react'; +import { AppTheme } from '@backstage/core-plugin-api'; +import { Theme, useTheme } from '@mui/material/styles'; + +export function MuiThemeExtractor(props: { + appTheme: AppTheme; + children: (theme: Theme) => JSX.Element; +}): JSX.Element { + const { appTheme, children } = props; + const [theme, setTheme] = useState(null); + const { Provider } = appTheme; + if (theme) { + return children(theme); + } + + return ( + + + + ); +} + +function MuiThemeExtractorInner(props: { setTheme: (theme: Theme) => void }) { + props.setTheme(useTheme()); + return null; +} diff --git a/plugins/bui-themer/src/components/BuiThemerPage/ThemeContent.tsx b/plugins/bui-themer/src/components/BuiThemerPage/ThemeContent.tsx new file mode 100644 index 0000000000..0974b8f15d --- /dev/null +++ b/plugins/bui-themer/src/components/BuiThemerPage/ThemeContent.tsx @@ -0,0 +1,127 @@ +/* + * Copyright 2025 The Backstage Authors + * + * 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 { useMemo, useState, useCallback } from 'react'; +import { Theme } from '@mui/material/styles'; +import { + Box, + Button, + Card, + Flex, + Text, + Tabs, + TabList, + Tab, + TabPanel, +} from '@backstage/ui'; +import { convertMuiToBuiTheme } from './convertMuiToBuiTheme'; +import { BuiThemePreview } from './BuiThemePreview'; + +interface ThemeContentProps { + themeId: string; + themeTitle: string; + variant: 'light' | 'dark'; + muiTheme: Theme; +} + +export function ThemeContent({ + themeId, + themeTitle, + variant, + muiTheme, +}: ThemeContentProps) { + const [activeTab, setActiveTab] = useState('css'); + + const { css, styleObject } = useMemo(() => { + return convertMuiToBuiTheme(muiTheme); + }, [muiTheme]); + + const handleCopy = useCallback(() => { + window.navigator.clipboard.writeText(css); + }, [css]); + + const handleDownload = useCallback(() => { + const blob = new Blob([css], { type: 'text/css' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `bui-theme-${themeId}.css`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + }, [css, themeId]); + + return ( + + + + + {themeTitle} + + {variant} theme + + + + + + + + + setActiveTab(key as string)} + > + + Generated CSS + Live Preview + + + + + {css} + + + + + + + + + + + + + ); +} diff --git a/plugins/bui-themer/src/components/BuiThemerPage/index.ts b/plugins/bui-themer/src/components/BuiThemerPage/index.ts index 3d32f11259..cbc645e02a 100644 --- a/plugins/bui-themer/src/components/BuiThemerPage/index.ts +++ b/plugins/bui-themer/src/components/BuiThemerPage/index.ts @@ -15,3 +15,6 @@ */ export { BuiThemerPage } from './BuiThemerPage'; +export { BuiThemePreview } from './BuiThemePreview'; +export { ThemeContent } from './ThemeContent'; +export { MuiThemeExtractor } from './MuiThemeExtractor'; diff --git a/plugins/bui-themer/src/setupTests.ts b/plugins/bui-themer/src/setupTests.ts deleted file mode 100644 index b57590b525..0000000000 --- a/plugins/bui-themer/src/setupTests.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2025 The Backstage Authors - * - * 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 '@testing-library/jest-dom';