diff --git a/.changeset/honest-teams-shave.md b/.changeset/honest-teams-shave.md new file mode 100644 index 0000000000..6afbf37039 --- /dev/null +++ b/.changeset/honest-teams-shave.md @@ -0,0 +1,10 @@ +--- +'@backstage/plugin-home-react': patch +'@backstage/plugin-home': patch +--- + +Export ContentModal from `@backstage/plugin-home-react` so people can use this in other scenarios. +Renamed `CatalogReactComponentsNameToClassKey` to `PluginHomeComponentsNameToClassKey` in `overridableComponents.ts` + +Made QuickStartCard `docsLinkTitle` prop more flexible to allow for any React.JSX.Element instead of just a string. +Added QuickStartCard prop `additionalContent` which can eventually replace the prop `video`. diff --git a/plugins/home-react/report.api.md b/plugins/home-react/report.api.md index c7e847fb36..26ef6267aa 100644 --- a/plugins/home-react/report.api.md +++ b/plugins/home-react/report.api.md @@ -5,9 +5,19 @@ ```ts import { Extension } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react/jsx-runtime'; +import { JSX as JSX_3 } from 'react'; +import { Overrides } from '@material-ui/core/styles/overrides'; import { RJSFSchema } from '@rjsf/utils'; +import { StyleRules } from '@material-ui/core/styles/withStyles'; import { UiSchema } from '@rjsf/utils'; +// @public (undocumented) +export type BackstageOverrides = Overrides & { + [Name in keyof PluginHomeComponentsNameToClassKey]?: Partial< + StyleRules + >; +}; + // @public (undocumented) export type CardConfig = { layout?: CardLayout; @@ -52,6 +62,15 @@ export type ComponentRenderer = { Renderer?: (props: RendererProps) => JSX.Element; }; +// @public +export const ContentModal: (props: ContentModalProps) => JSX_2.Element; + +// @public +export type ContentModalProps = { + modalContent: JSX_3.Element; + linkContent: string | JSX_3.Element; +}; + // @public export function createCardExtension(options: { title?: string; @@ -62,6 +81,14 @@ export function createCardExtension(options: { settings?: CardSettings; }): Extension<(props: CardExtensionProps) => JSX_2.Element>; +// @public (undocumented) +export type PluginHomeComponentsNameToClassKey = { + PluginHomeContentModal: PluginHomeContentModalClassKey; +}; + +// @public (undocumented) +export type PluginHomeContentModalClassKey = 'contentModal' | 'linkText'; + // @public (undocumented) export type RendererProps = { title?: string; diff --git a/plugins/home/src/homePageComponents/QuickStart/ContentModal.tsx b/plugins/home-react/src/components/ContentModal.tsx similarity index 71% rename from plugins/home/src/homePageComponents/QuickStart/ContentModal.tsx rename to plugins/home-react/src/components/ContentModal.tsx index ff917f367c..cde317e248 100644 --- a/plugins/home/src/homePageComponents/QuickStart/ContentModal.tsx +++ b/plugins/home-react/src/components/ContentModal.tsx @@ -18,14 +18,43 @@ import { JSX, useState } from 'react'; import { Link } from '@backstage/core-components'; import Modal from '@material-ui/core/Modal'; import Box from '@material-ui/core/Box'; +import { makeStyles, Theme } from '@material-ui/core/styles'; -import { useStyles } from './styles'; +/** @public */ +export type PluginHomeContentModalClassKey = 'contentModal' | 'linkText'; +export const useStyles = makeStyles( + (theme: Theme) => ({ + contentModal: { + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: '80%', + height: 'auto', + }, + linkText: { + marginBottom: theme.spacing(1.5), + }, + }), + { name: 'PluginHomeContentModal' }, +); + +/** + * Props customizing the component. + * + * @public + */ export type ContentModalProps = { modalContent: JSX.Element; linkContent: string | JSX.Element; }; +/** + * A component to expand given content into a full screen modal. + * + * @public + */ export const ContentModal = (props: ContentModalProps) => { const { modalContent, linkContent } = props; const styles = useStyles(); diff --git a/plugins/home-react/src/components/index.ts b/plugins/home-react/src/components/index.ts index dce6968b36..8a982075eb 100644 --- a/plugins/home-react/src/components/index.ts +++ b/plugins/home-react/src/components/index.ts @@ -15,3 +15,7 @@ */ export { SettingsModal } from './SettingsModal'; +export { ContentModal } from './ContentModal'; + +export type { PluginHomeContentModalClassKey } from './ContentModal'; +export type { ContentModalProps } from './ContentModal'; diff --git a/plugins/home-react/src/index.ts b/plugins/home-react/src/index.ts index 1f02ded1c6..54602dc814 100644 --- a/plugins/home-react/src/index.ts +++ b/plugins/home-react/src/index.ts @@ -30,3 +30,4 @@ export type { CardSettings, CardConfig, } from './extensions'; +export * from './overridableComponents'; diff --git a/plugins/home-react/src/overridableComponents.ts b/plugins/home-react/src/overridableComponents.ts new file mode 100644 index 0000000000..8a88fd5c94 --- /dev/null +++ b/plugins/home-react/src/overridableComponents.ts @@ -0,0 +1,36 @@ +/* + * 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 { Overrides } from '@material-ui/core/styles/overrides'; +import { StyleRules } from '@material-ui/core/styles/withStyles'; +import { PluginHomeContentModalClassKey } from './'; + +/** @public */ +export type PluginHomeComponentsNameToClassKey = { + PluginHomeContentModal: PluginHomeContentModalClassKey; +}; + +/** @public */ +export type BackstageOverrides = Overrides & { + [Name in keyof PluginHomeComponentsNameToClassKey]?: Partial< + StyleRules + >; +}; + +declare module '@backstage/theme' { + interface OverrideComponentNameToClassKeys + extends PluginHomeComponentsNameToClassKey {} +} diff --git a/plugins/home/report.api.md b/plugins/home/report.api.md index 07e54757e6..61ce9a77f8 100644 --- a/plugins/home/report.api.md +++ b/plugins/home/report.api.md @@ -195,9 +195,10 @@ export const QuickStartCard: ( // @public export type QuickStartCardProps = { modalTitle?: string | JSX_3.Element; - docsLinkTitle?: string; + docsLinkTitle?: string | JSX_3.Element; docsLink?: string; video?: JSX_3.Element; + additionalContent?: JSX_3.Element; image: JSX_3.Element; cardDescription?: string; downloadImage?: JSX_3.Element; diff --git a/plugins/home/src/homePageComponents/QuickStart/Content.tsx b/plugins/home/src/homePageComponents/QuickStart/Content.tsx index 829b9ed191..b923970888 100644 --- a/plugins/home/src/homePageComponents/QuickStart/Content.tsx +++ b/plugins/home/src/homePageComponents/QuickStart/Content.tsx @@ -18,7 +18,7 @@ import { JSX } from 'react'; import { Link } from '@backstage/core-components'; import Typography from '@material-ui/core/Typography'; import Grid from '@material-ui/core/Grid'; -import { ContentModal } from './ContentModal'; +import { ContentModal } from '@backstage/plugin-home-react'; import { useStyles } from './styles'; /** @@ -30,11 +30,15 @@ export type QuickStartCardProps = { /** The modal link title */ modalTitle?: string | JSX.Element; /** The link to docs title */ - docsLinkTitle?: string; + docsLinkTitle?: string | JSX.Element; /** The link to docs */ docsLink?: string; - /** The video to play on the card */ + /** The video to play on the card + * @deprecated This will be removed in the future, please use `additionalContent` instead + */ video?: JSX.Element; + /** Additional card content */ + additionalContent?: JSX.Element; /** A quickstart image to display on the card */ image: JSX.Element; /** The card description*/ @@ -78,7 +82,8 @@ export const Content = (props: QuickStartCardProps): JSX.Element => { - {props.video && props.video} + {(props.additionalContent && props.additionalContent) || + (props.video && props.video)} ); }; diff --git a/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx b/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx index 18375c9c27..c0963b88a1 100644 --- a/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx +++ b/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx @@ -18,6 +18,7 @@ import { QuickStartCard } from '../../plugin'; import { ComponentType, PropsWithChildren } from 'react'; import { wrapInTestApp } from '@backstage/test-utils'; import Grid from '@material-ui/core/Grid'; +import OpenInNewIcon from '@material-ui/icons/OpenInNew'; import ContentImage from './static/backstageSystemModel.png'; export default { @@ -61,6 +62,40 @@ export const Customized = () => { /> } cardDescription="Backstage system model will help you create new entities" + additionalContent={ +

+ This is a custom description for the Quick Start card. It can be + used to provide additional information or context about the Quick + Start process. +

+ } + /> + + ); +}; + +export const CustomDocLink = () => { + return ( + + + + Learn more with getting started docs + + } + docsLink="https://backstage.io/docs/getting-started" + image={ + quick start + } + cardDescription="Backstage system model will help you create new entities" /> );