diff --git a/.changeset/chatty-weeks-impress.md b/.changeset/chatty-weeks-impress.md new file mode 100644 index 0000000000..21beb168e9 --- /dev/null +++ b/.changeset/chatty-weeks-impress.md @@ -0,0 +1,44 @@ +--- +'@backstage/plugin-home': patch +--- + +Added a new Quick Start Card to `plugin-home`, which can display basic info to get users the info they need to onboard to the Catalog. + +``` +import { QuickStartCard } from '@backstage/plugin-home'; + + } + cardDescription="Backstage system model will help you create new entities" + video={ + + } + downloadImage={ + + } +/> +``` + +See the [storybook examples](https://backstage.io/storybook/?path=/story/plugins-home-components-quickstartcard--default) diff --git a/plugins/home/report.api.md b/plugins/home/report.api.md index 023c649ab4..878d8ef646 100644 --- a/plugins/home/report.api.md +++ b/plugins/home/report.api.md @@ -187,6 +187,17 @@ export type LayoutConfiguration = { // @public export type Operators = '<' | '<=' | '==' | '!=' | '>' | '>=' | 'contains'; +// @public +export type QuickStartCardProps = { + modalTitle?: string | React_2.JSX.Element; + docsLinkTitle?: string; + docsLink?: string; + video?: React_2.JSX.Element; + image: React_2.JSX.Element; + cardDescription?: string; + downloadImage?: React_2.JSX.Element; +}; + // @public @deprecated (undocumented) export type RendererProps = RendererProps_2; diff --git a/plugins/home/src/homePageComponents/QuickStart/Content.test.tsx b/plugins/home/src/homePageComponents/QuickStart/Content.test.tsx new file mode 100644 index 0000000000..0acd44768f --- /dev/null +++ b/plugins/home/src/homePageComponents/QuickStart/Content.test.tsx @@ -0,0 +1,69 @@ +/* + * Copyright 2022 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 { Content } from './Content'; +import React from 'react'; +import userEvent from '@testing-library/user-event'; +import { renderInTestApp } from '@backstage/test-utils'; +import ContentImage from './static/backstageSystemModel.png'; + +describe('', () => { + const renderContent = async () => { + return await renderInTestApp( + + } + docsLinkTitle="Testing docs link" + />, + ); + }; + + it('should have expected card content', async () => { + const { getByTestId } = await renderContent(); + const docsLink = getByTestId('quick-start-link-to-docs'); + expect(docsLink).toHaveTextContent('Testing docs link'); + expect(docsLink).toHaveAttribute('target', '_blank'); + }); + + it('clicking the link opens the modal', async () => { + const { getByTestId, getByText } = await renderContent(); + // Find the link element + const link = getByText('Onboarding'); + // Simulate a click event on the link + await userEvent.click(link); + // Assert that the modal is visible + const modal = getByTestId('content-modal-open'); + expect(modal).toBeVisible(); + }); + + it('clicking the image opens the modal', async () => { + const { getByTestId } = await renderContent(); + // Find the link element + const link = getByTestId('quick-start-image'); + // Simulate a click event on the link + await userEvent.click(link); + // Assert that the modal is visible + const modal = getByTestId('content-modal-open'); + expect(modal).toBeVisible(); + }); +}); diff --git a/plugins/home/src/homePageComponents/QuickStart/Content.tsx b/plugins/home/src/homePageComponents/QuickStart/Content.tsx new file mode 100644 index 0000000000..998b1a1798 --- /dev/null +++ b/plugins/home/src/homePageComponents/QuickStart/Content.tsx @@ -0,0 +1,84 @@ +/* + * Copyright 2022 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 React 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 { useStyles } from './styles'; + +/** + * Props customizing the component. + * + * @public + */ +export type QuickStartCardProps = { + /** The modal link title */ + modalTitle?: string | React.JSX.Element; + /** The link to docs title */ + docsLinkTitle?: string; + /** The link to docs */ + docsLink?: string; + /** The video to play on the card */ + video?: React.JSX.Element; + /** A quickstart image to display on the card */ + image: React.JSX.Element; + /** The card description*/ + cardDescription?: string; + /** A component used to download a quickStart image*/ + downloadImage?: React.JSX.Element; +}; + +/** + * A component to display Quick Start info on the homepage. + * + * @public + */ +export const Content = (props: QuickStartCardProps): JSX.Element => { + const styles = useStyles(); + return ( + <> + + + {props.cardDescription || 'Get started with Backstage'} + + + + {props.downloadImage && {props.downloadImage}} + + + {props.docsLinkTitle || 'Learn more'} + + + + {props.video && props.video} + + ); +}; diff --git a/plugins/home/src/homePageComponents/QuickStart/ContentModal.tsx b/plugins/home/src/homePageComponents/QuickStart/ContentModal.tsx new file mode 100644 index 0000000000..a6e000dc42 --- /dev/null +++ b/plugins/home/src/homePageComponents/QuickStart/ContentModal.tsx @@ -0,0 +1,57 @@ +/* + * Copyright 2022 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 React, { useState } from 'react'; +import { Link } from '@backstage/core-components'; +import Modal from '@material-ui/core/Modal'; +import Box from '@material-ui/core/Box'; + +import { useStyles } from './styles'; + +export type ContentModalProps = { + modalContent: React.JSX.Element; + linkContent: string | React.JSX.Element; +}; + +export const ContentModal = (props: ContentModalProps) => { + const { modalContent, linkContent } = props; + const styles = useStyles(); + const [open, setOpen] = useState(false); + + return ( +
+ setOpen(true)} + > + {linkContent} + + setOpen(false)} + aria-labelledby="content-modal" + data-testid="content-modal" + > + + {modalContent} + + +
+ ); +}; diff --git a/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx b/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx new file mode 100644 index 0000000000..8d6e6d117e --- /dev/null +++ b/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx @@ -0,0 +1,67 @@ +/* + * Copyright 2022 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 { QuickStartCard } from '../../plugin'; +import React, { ComponentType, PropsWithChildren } from 'react'; +import { wrapInTestApp } from '@backstage/test-utils'; +import Grid from '@material-ui/core/Grid'; +import ContentImage from './static/backstageSystemModel.png'; + +export default { + title: 'Plugins/Home/Components/QuickStartCard', + decorators: [ + (Story: ComponentType>) => wrapInTestApp(), + ], +}; + +export const Default = () => { + return ( + + + } + /> + + ); +}; + +export const Customized = () => { + return ( + + + } + cardDescription="Backstage system model will help you create new entities" + /> + + ); +}; diff --git a/plugins/home/src/homePageComponents/QuickStart/index.ts b/plugins/home/src/homePageComponents/QuickStart/index.ts new file mode 100644 index 0000000000..2c2e0ed2f2 --- /dev/null +++ b/plugins/home/src/homePageComponents/QuickStart/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2022 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. + */ + +export { Content } from './Content'; +export type { QuickStartCardProps } from './Content'; +export type { QuickStartCardClassKey } from './styles'; diff --git a/plugins/home/src/homePageComponents/QuickStart/static/backstageSystemModel.png b/plugins/home/src/homePageComponents/QuickStart/static/backstageSystemModel.png new file mode 100644 index 0000000000..ad784060bb Binary files /dev/null and b/plugins/home/src/homePageComponents/QuickStart/static/backstageSystemModel.png differ diff --git a/plugins/home/src/homePageComponents/QuickStart/styles.ts b/plugins/home/src/homePageComponents/QuickStart/styles.ts new file mode 100644 index 0000000000..f6f93f7070 --- /dev/null +++ b/plugins/home/src/homePageComponents/QuickStart/styles.ts @@ -0,0 +1,68 @@ +/* + * Copyright 2022 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 { makeStyles, Theme } from '@material-ui/core/styles'; + +/** @public */ +export type QuickStartCardClassKey = + | 'cardTitleIcon' + | 'contentActionContainer' + | 'contentModal' + | 'imageSize' + | 'link' + | 'linkText' + | 'videoContainer'; + +export const useStyles = makeStyles( + (theme: Theme) => ({ + cardTitleIcon: { + verticalAlign: 'bottom', + marginLeft: '-4px', + }, + contentActionContainer: { + marginTop: theme.spacing(1.5), + marginBottom: theme.spacing(1.5), + }, + contentModal: { + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: '80%', + height: 'auto', + }, + imageSize: { width: '100%', height: '100%' }, + link: { + display: 'inline-flex', + alignItems: 'center', + textDecoration: 'none', + color: `${theme.palette.link}`, + '&:hover': { + background: 'transparent', + }, + }, + linkText: { + marginBottom: theme.spacing(1.5), + }, + videoContainer: { + borderRadius: '10px', + width: '100%', + height: 'auto', + background: `${theme.palette.background.default}`, + }, + }), + { name: 'HomeQuickStartCard' }, +); diff --git a/plugins/home/src/homePageComponents/index.ts b/plugins/home/src/homePageComponents/index.ts index e260982e8e..f2eb39b070 100644 --- a/plugins/home/src/homePageComponents/index.ts +++ b/plugins/home/src/homePageComponents/index.ts @@ -20,3 +20,4 @@ export type { WelcomeTitleLanguageProps } from './WelcomeTitle'; export type { VisitedByTypeProps, VisitedByTypeKind } from './VisitedByType'; export type { FeaturedDocsCardProps } from './FeaturedDocsCard'; export type { StarredEntitiesProps } from './StarredEntities'; +export type { QuickStartCardProps } from './QuickStart'; diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts index c3fa938197..6892db2231 100644 --- a/plugins/home/src/plugin.ts +++ b/plugins/home/src/plugin.ts @@ -27,6 +27,7 @@ import { ToolkitContentProps, VisitedByTypeProps, FeaturedDocsCardProps, + QuickStartCardProps, } from './homePageComponents'; import { rootRouteRef } from './routes'; import { VisitsStorageApi, visitsApiRef } from './api'; @@ -230,3 +231,16 @@ export const FeaturedDocsCard = homePlugin.provide( components: () => import('./homePageComponents/FeaturedDocsCard'), }), ); + +/** + * A component to display Quick Start information. + * + * @public + */ +export const QuickStartCard = homePlugin.provide( + createCardExtension({ + name: 'QuickStartCard', + title: 'Quick Start', + components: () => import('./homePageComponents/QuickStart'), + }), +);