feat: Extract reusable block & add catalog section to home page

Signed-off-by: Carlos Esteban Lopez <lcarlosesteb@vmware.com>
This commit is contained in:
Carlos Esteban Lopez
2023-02-06 22:01:49 -05:00
committed by Carlos Lopez
parent c0e0bcc137
commit 2c21d5f6c5
8 changed files with 360 additions and 46 deletions
@@ -0,0 +1,43 @@
.bannerSection {
display: block;
&:global(.greyBackground) {
background: linear-gradient(90.49deg, #121212 15.36%, #282828 70.44%);
}
&:global(.greenGradientBackground) {
background: linear-gradient(
178.64deg,
hsla(0, 0%, 100%, 0) 57.61%,
hsla(0, 0%, 100%, 0.17) 127.71%
),
linear-gradient(
144.35deg,
rgba(98, 197, 179, 0) 56.68%,
rgba(98, 197, 179, 0.59) 109.25%
),
linear-gradient(
192.29deg,
rgba(155, 240, 225, 0) 54.17%,
rgba(155, 240, 225, 0.67) 137.34%
);
}
&:global(.greenBottomGradientBackground) {
background: linear-gradient(
178.64deg,
hsla(0, 0%, 100%, 0) 57.61%,
hsla(0, 0%, 100%, 0.17) 127.71%
),
linear-gradient(
144.35deg,
rgba(98, 197, 179, 0) 56.68%,
rgba(98, 197, 179, 0.59) 109.25%
),
linear-gradient(
192.29deg,
rgba(155, 240, 225, 0) 54.17%,
rgba(155, 240, 225, 0.67) 137.34%
);
}
}
@@ -0,0 +1,34 @@
import clsx from 'clsx';
import React, { PropsWithChildren, ReactNode } from 'react';
import bannerColumnStyles from './banner-section-columns.module.scss';
export type IBannerSectionColumnsProps = PropsWithChildren<{
header?: ReactNode;
// children: ReactNode | ReactNode[];
}>;
export const BannerSectionColumns = ({
header,
children,
}: IBannerSectionColumnsProps) => (
<>
{header && (
<div className="row padding-vert--lg">
<div className="col">{header}</div>
</div>
)}
{Array.isArray(children) ? (
<div className="row">
{children.map((child, index) => (
<div key={index} className="col padding-bottom--lg">
{child}
</div>
))}
</div>
) : (
children
)}
</>
);
@@ -0,0 +1,29 @@
.bannerSection {
display: block;
&:global(.greyBackground) {
background: linear-gradient(90.49deg, #121212 15.36%, #282828 70.44%);
}
&:global(.greenGradientBackground) {
background: linear-gradient(70.44deg, #121212 55%, #5d817b);
}
&:global(.greenBottomGradientBackground) {
background: linear-gradient(
178.64deg,
hsla(0, 0%, 100%, 0) 57.61%,
hsla(0, 0%, 100%, 0.17) 127.71%
),
linear-gradient(
144.35deg,
rgba(98, 197, 179, 0) 56.68%,
rgba(98, 197, 179, 0.59) 109.25%
),
linear-gradient(
192.29deg,
rgba(155, 240, 225, 0) 54.17%,
rgba(155, 240, 225, 0.67) 137.34%
);
}
}
@@ -0,0 +1,27 @@
import clsx from 'clsx';
import React, { PropsWithChildren } from 'react';
import bannerStyles from './banner-section.module.scss';
export type IBannerSectionProps = PropsWithChildren<{
greyBackground?: boolean;
greenGradientBackground?: boolean;
greenBottomGradientBackground?: boolean;
}>;
export const BannerSection = ({
children,
greyBackground = false,
greenGradientBackground = false,
greenBottomGradientBackground = false,
}: IBannerSectionProps) => (
<section
className={clsx(bannerStyles.bannerSection, {
greyBackground,
greenGradientBackground,
greenBottomGradientBackground,
})}
>
<div className="container">{children}</div>
</section>
);
@@ -0,0 +1,22 @@
.contentBlock {
gap: 1.5rem;
display: grid;
> *,
h1,
h2 {
margin: 0;
padding: 0;
}
:global(.bulletLine) {
width: 50px;
margin-bottom: 0.5rem;
}
:global(.actionButtons) {
gap: 1rem;
display: grid;
grid-template-columns: repeat(2, auto);
}
}
@@ -0,0 +1,55 @@
import Link from '@docusaurus/Link';
import clsx from 'clsx';
import React, { FC, PropsWithChildren, ReactNode } from 'react';
import contentBlockStyles from './content-block.module.scss';
export interface ContentBlockActionButtonProps {
label: string;
link: string;
}
export type IContentBlockProps = PropsWithChildren<{
title?: ReactNode;
className?: string;
topImgSrc?: string;
hasBulletLine?: boolean;
actionButtons?: ContentBlockActionButtonProps[];
}>;
export const ContentBlock = ({
children,
title,
className,
topImgSrc,
hasBulletLine,
actionButtons,
}: IContentBlockProps) => {
return (
<div className={clsx(className, contentBlockStyles.contentBlock)}>
{topImgSrc && <img src={topImgSrc} alt={topImgSrc} />}
<div className="contentBlockTitle">
{hasBulletLine && <div className="bulletLine" />}
{title && React.isValidElement(title) ? title : <h2>{title}</h2>}
</div>
{children && <p>{children}</p>}
{actionButtons && (
<div className="actionButtons">
{actionButtons.map(({ link, label }, index) => (
<Link
key={index}
className="button button--primary button--lg"
to={link}
>
{label}
</Link>
))}
</div>
)}
</div>
);
};
+117 -35
View File
@@ -4,17 +4,20 @@ import Layout from '@theme/Layout';
import { clsx } from 'clsx';
import React from 'react';
import { BannerSection } from '../../components/banner-section/banner-section';
import homeStyles from './home.module.scss';
import { BannerSectionColumns } from '../../components/banner-section/banner-section-columns';
import { ContentBlock } from '@site/src/components/content-block/content-block';
export function Home() {
const { siteConfig } = useDocusaurusContext();
return (
<Layout>
<section className={homeStyles.homePage}>
<div className="container">
<div className="row padding-vert--lg">
<div className="col">
<div className={homeStyles.homePage}>
<BannerSection greyBackground>
<BannerSectionColumns
header={
<div
className={clsx(
'card',
@@ -35,36 +38,28 @@ export function Home() {
<div className="bannerCloseButton">X</div>
</div>
</div>
</div>
}
>
<ContentBlock
className={homeStyles.openPlatformBanner}
title={<h1> An open platform for building developer portals</h1>}
actionButtons={[
{
link: 'https://github.com/backstage/backstage#getting-started',
label: 'GITHUB',
},
{
link: 'https://info.backstage.spotify.com/office-hours',
label: 'OFFICE HOURS',
},
]}
>
Powered by a centralized software catalog, Backstage restores
order to your infrastructure and enables your product teams to
ship high-quality code quickly without compromising autonomy.
</ContentBlock>
<div className={clsx('row', homeStyles.openPlatformBanner)}>
<div className="col padding-bottom--lg">
<h1>An open platform for building developer portals</h1>
<p>
Powered by a centralized software catalog, Backstage restores
order to your infrastructure and enables your product teams to
ship high-quality code quickly without compromising autonomy.
</p>
<div className="buttonsContainer">
<Link
to="https://github.com/backstage/backstage#getting-started"
className="button button--primary"
>
GITHUB
</Link>
<Link
to="https://info.backstage.spotify.com/office-hours"
className="button button--primary"
>
OFFICE HOURS
</Link>
</div>
</div>
<div className="col padding-bottom--lg svgContainer">
<div className={homeStyles.svgContainer}>
<img
className="laptopSvg"
src={`${siteConfig.baseUrl}img/laptop.svg`}
@@ -74,9 +69,96 @@ export function Home() {
src={`${siteConfig.baseUrl}animations/backstage-logos-hero-8.gif`}
/>
</div>
</BannerSectionColumns>
</BannerSection>
<BannerSection>
<BannerSectionColumns>
<ContentBlock
title="The Speed Paradox"
topImgSrc={`${siteConfig.baseUrl}animations/backstage-speed-paradox-7.gif`}
>
At Spotify, we've always believed in the speed and ingenuity that
comes from having autonomous development teams. But as we learned
firsthand, the faster you grow, the more fragmented and complex
your software ecosystem becomes. And then everything slows down
again.
</ContentBlock>
<ContentBlock
title="The Standards Paradox"
topImgSrc={`${siteConfig.baseUrl}animations/backstage-standards-paradox-4.gif`}
>
By centralizing services and standardizing your tooling, Backstage
streamlines your development environment from end to end. Instead
of restricting autonomy, standardization frees your engineers from
infrastructure complexity. So you can return to building and
scaling, quickly and safely.
</ContentBlock>
</BannerSectionColumns>
</BannerSection>
<BannerSection greenGradientBackground>
<div className={homeStyles.catalogContainer}>
<div className="catalogTitle">
<img
src={`${siteConfig.baseUrl}animations/backstage-software-catalog-icon-1.gif`}
alt="Software Catalog Planet GIF"
/>
<h2 className="text--primary">Backstage Software Catalog</h2>
<h1>Build an ecosystem, not a wilderness</h1>
</div>
<picture className="catalogImg">
<source
srcSet={`${siteConfig.baseUrl}img/components-with-filter.png`}
media="(min-width: 997px)"
/>
<img
src={`${siteConfig.baseUrl}img/components-with-filter-small.png`}
alt=""
/>
</picture>
<ContentBlock
title="Manage all your software, all in one place"
hasBulletLine
>
Backstage makes it easy for one team to manage 10 services and
makes it possible for your company to manage thousands of them
</ContentBlock>
<ContentBlock
title="Backstage makes it easy for one team to manage 10 services — and makes it possible for your company to manage thousands of them"
hasBulletLine
>
Every team can see all the services they own and related resources
(deployments, data pipelines, pull request status, etc.)
</ContentBlock>
<ContentBlock title="Metadata on tap" hasBulletLine>
All that information can be shared with plugins inside Backstage
to enable other management features, like resource monitoring and
testing
</ContentBlock>
<ContentBlock title="Not just services" hasBulletLine>
Libraries, websites, ML models you name it, Backstage knows all
about it, including who owns it, dependencies, and more
</ContentBlock>
<ContentBlock
title="Discoverability & accountability"
hasBulletLine
>
No more orphan software hiding in the dark corners of your tech
stack
</ContentBlock>
</div>
</div>
</section>
</BannerSection>
</div>
</Layout>
);
}
+33 -11
View File
@@ -26,19 +26,41 @@
}
}
.openPlatformBanner {
:global(.svgContainer) {
position: relative;
.svgContainer {
position: relative;
:global(img.laptopSvg) {
width: 100%;
}
:global(img.laptopSvg) {
width: 100%;
}
:global(img.laptopScreenGif) {
position: absolute;
top: 3%;
left: 17%;
width: 70%;
:global(img.laptopScreenGif) {
position: absolute;
top: 3%;
left: 17%;
width: 70%;
}
}
.catalogContainer {
gap: 2rem;
display: grid;
align-items: center;
grid-template-columns: repeat(4, 1fr);
picture {
display: block;
grid-row: 1/3;
grid-column: 3/-1;
}
:global(.catalogTitle) {
grid-column: 1/3;
img {
max-width: 190px;
max-height: 190px;
}
}
}