refactor: Improve grid components & replace them in community page

Signed-off-by: Carlos Esteban Lopez <lcarlosesteb@vmware.com>
This commit is contained in:
Carlos Esteban Lopez
2023-02-14 16:44:03 -05:00
committed by Carlos Lopez
parent 0a3024c9a6
commit 537b921b83
13 changed files with 325 additions and 395 deletions
@@ -1,43 +0,0 @@
.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%
);
}
}
@@ -1,34 +0,0 @@
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,20 @@
$desktopUpBreakpoint: 997px;
.sectionGridContainer {
gap: 2rem;
display: grid;
:global(.gridHeader) {
grid-column: 1 / -1;
}
}
.gridContainer {
gap: 2rem;
display: grid;
align-items: center;
@media (min-width: $desktopUpBreakpoint) {
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
}
@@ -0,0 +1,35 @@
import clsx from 'clsx';
import React, { PropsWithChildren, ReactNode } from 'react';
import bannerGridStyles from './banner-section-grid.module.scss';
export type IBannerSectionColumnsProps = PropsWithChildren<{
header?: ReactNode;
className?: string;
// children: ReactNode | ReactNode[];
}>;
export const BannerSectionGrid = ({
header,
children,
className,
}: IBannerSectionColumnsProps) => {
console.log('Header: ', header);
return (
<div className={clsx(bannerGridStyles.sectionGridContainer, className)}>
{header && <div className="gridHeader">{header}</div>}
<div className={bannerGridStyles.gridContainer}>
{Array.isArray(children)
? children.map((child, index) =>
React.cloneElement(child, {
key: index,
className: clsx(child.props.className),
}),
)
: children}
</div>
</div>
);
};
@@ -4,6 +4,7 @@ import React, { PropsWithChildren } from 'react';
import bannerStyles from './banner-section.module.scss';
export type IBannerSectionProps = PropsWithChildren<{
className?: string;
greyBackground?: boolean;
greenGradientBackground?: boolean;
greenBottomGradientBackground?: boolean;
@@ -12,19 +13,22 @@ export type IBannerSectionProps = PropsWithChildren<{
export const BannerSection = ({
children,
className,
greyBackground = false,
greenGradientBackground = false,
greenBottomGradientBackground = false,
greenCallToActionGradientBackground = false,
}: IBannerSectionProps) => (
<section
className={clsx(bannerStyles.bannerSection, {
className={clsx(bannerStyles.bannerSection, className, {
greyBackground,
greenGradientBackground,
greenBottomGradientBackground,
greenCallToActionGradientBackground,
})}
>
<div className="container padding-vert--lg">{children}</div>
<div className="container padding-horiz--lg padding-vert--xl">
{children}
</div>
</section>
);
@@ -1,6 +1,9 @@
.contentBlock {
height: 100%;
gap: 1.5rem;
display: grid;
align-items: center;
> *,
h1,
@@ -9,6 +12,10 @@
padding: 0;
}
:global(.contentBlockTitle) {
align-self: start;
}
:global(.bulletLine) {
width: 50px;
margin-bottom: 0.5rem;
@@ -17,6 +24,7 @@
:global(.actionButtons) {
gap: 1rem;
display: grid;
grid-template-columns: repeat(2, auto);
align-self: end;
grid-template-columns: repeat(auto-fit, minmax(100px, auto));
}
}
@@ -24,32 +24,30 @@ export const ContentBlock = ({
topImgSrc,
hasBulletLine,
actionButtons,
}: IContentBlockProps) => {
return (
<div className={clsx(className, contentBlockStyles.contentBlock)}>
{topImgSrc && <img src={topImgSrc} alt={topImgSrc} />}
}: IContentBlockProps) => (
<div className={clsx(className, contentBlockStyles.contentBlock)}>
{topImgSrc && <img src={topImgSrc} alt={topImgSrc} />}
<div className="contentBlockTitle">
{hasBulletLine && <div className="bulletLine" />}
<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>
)}
{title && React.isValidElement(title) ? title : <h2>{title}</h2>}
</div>
);
};
{children && React.isValidElement(children) ? 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>
);
+126 -141
View File
@@ -1,10 +1,13 @@
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import { BannerSection } from '@site/src/components/banner-section/banner-section';
import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid';
import Layout from '@theme/Layout';
import { clsx } from 'clsx';
import React from 'react';
import communityStyles from './community.module.scss';
import { ContentBlock } from '../../components/content-block/content-block';
interface ICollectionItem {
title?: string;
@@ -128,155 +131,137 @@ export function Community() {
return (
<Layout>
<div className={clsx(communityStyles.communityPage)}>
<section className={communityStyles.banner}>
<div className={clsx('container')}>
<div className="row">
<div
className={clsx('col', 'padding-vert--xl padding-right--xl')}
>
<h1 className={clsx('margin-bottom--lg')}>
Backstage Community
</h1>
<BannerSection greyBackground>
<BannerSectionGrid>
<ContentBlock
className="padding-right--xl"
title={<h1>Backstage Community</h1>}
>
Join the vibrant community around Backstage through social media
and different meetups. To ensure that you have a welcoming
environment, we follow the
<Link to="https://github.com/cncf/foundation/blob/master/code-of-conduct.md">
{' '}
CNCF Code of Conduct{' '}
</Link>
in everything we do.
</ContentBlock>
<p>
Join the vibrant community around Backstage through social
media and different meetups. To ensure that you have a
welcoming environment, we follow the
<Link to="https://github.com/cncf/foundation/blob/master/code-of-conduct.md">
{' '}
CNCF Code of Conduct{' '}
</Link>
in everything we do.
</p>
</div>
<div className={clsx('col', 'padding-vert--xl padding-left--xl')}>
<h2 className={clsx('margin-bottom--lg')}>
Get started in our community!
</h2>
<ul>
{communityListItems.map(
({ content: text, link, label }, index) => (
<li key={index}>
<p className="margin-bottom--none">
{text} <Link to={link}>{label}</Link>
</p>
</li>
),
)}
</ul>
</div>
</div>
</div>
</section>
<section className={communityStyles.officialInitiatives}>
<div className={clsx('container', 'padding-vert--xl')}>
<div className="padding-bottom--xl">
<h2 className="text--primary">Offical Backstage initiatives</h2>
<h1>Stay tuned to the latest developments</h1>
</div>
<div className="row">
{officialInitiatives.map(
({ title, content, link, label }, index) => (
<div className={clsx('col')} key={index}>
<div className="bulletLine"></div>
<h2>{title}</h2>
<p className="padding-bottom--lg">{content}</p>
<Link
className="button button--primary button--lg"
to={link}
>
{label}
</Link>
</div>
),
<ContentBlock
className={clsx(
'padding-left--xl',
communityStyles.listContainer,
)}
</div>
</div>
</section>
title="Get started in our community!"
>
<ul>
{communityListItems.map(
({ content: text, link, label }, index) => (
<li key={index}>
<p className="margin-bottom--none">
{text} <Link to={link}>{label}</Link>
</p>
</li>
),
)}
</ul>
</ContentBlock>
</BannerSectionGrid>
</BannerSection>
<section className={communityStyles.communityInitiatives}>
<div className={clsx('container', 'padding-vert--xl')}>
<div className="padding-bottom--xl">
<h2 className="text--primary">Community initiatives</h2>
</div>
<BannerSection greenBottomGradientBackground>
<BannerSectionGrid
header={
<>
<h2 className="text--primary">Offical Backstage initiatives</h2>
<div className="row">
{communityInitiatives.map(
({ title, content, link, label }, index) => (
<div className={clsx('col')} key={index}>
<div className="bulletLine"></div>
<h1>Stay tuned to the latest developments</h1>
</>
}
>
{officialInitiatives.map(
({ title, content, link, label }, index) => (
<ContentBlock
key={index}
title={title}
hasBulletLine
actionButtons={[
{
link,
label,
},
]}
>
{content}
</ContentBlock>
),
)}
</BannerSectionGrid>
</BannerSection>
<h2>{title}</h2>
<BannerSection greyBackground>
<BannerSectionGrid
header={<h2 className="text--primary">Community initiatives</h2>}
>
{communityInitiatives.map(
({ title, content, link, label }, index) => (
<ContentBlock
key={index}
title={title}
hasBulletLine
actionButtons={[
{
link,
label,
},
]}
>
<p>{content}</p>
</ContentBlock>
),
)}
</BannerSectionGrid>
</BannerSection>
<p className="padding-bottom--lg">{content}</p>
<Link
className="button button--primary button--lg"
to={link}
>
{label}
</Link>
</div>
),
)}
</div>
</div>
</section>
<section className={communityStyles.trainingNCertifications}>
<div className={clsx('container', 'padding-vert--xl')}>
<div className="padding-bottom--xl">
<BannerSection>
<BannerSectionGrid
header={
<h2 className="text--primary">Trainings and Certifications</h2>
</div>
}
>
{trainingNCertifications.map(
({ title, content, link, label }, index) => (
<ContentBlock
key={index}
title={title}
hasBulletLine
actionButtons={[
{
link,
label,
},
]}
>
<p>{content}</p>
</ContentBlock>
),
)}
</BannerSectionGrid>
</BannerSection>
<div className="row">
{trainingNCertifications.map(
({ title, content, link, label }, index) => (
<div className={clsx('col')} key={index}>
<div className="bulletLine"></div>
<h2>{title}</h2>
<p className="padding-bottom--lg">{content}</p>
<Link
className="button button--primary button--lg"
to={link}
>
{label}
</Link>
</div>
),
)}
</div>
</div>
</section>
<section className={communityStyles.commercialPartners}>
<div className={clsx('container', 'padding-vert--xl')}>
<div className="padding-bottom--xl">
<h2 className="text--primary">Commercial Partners</h2>
</div>
<div className="row">
{partners.map(({ name, url, logo }, index) => (
<div className={clsx('col')} key={index}>
<Link to={url}>
<img src={`${siteConfig.baseUrl}${logo}`} alt={name} />
</Link>
</div>
))}
</div>
</div>
</section>
<BannerSection greyBackground>
<BannerSectionGrid
header={<h2 className="text--primary">Commercial Partners</h2>}
>
{partners.map(({ name, url, logo }, index) => (
<div key={index}>
<Link to={url}>
<img src={`${siteConfig.baseUrl}${logo}`} alt={name} />
</Link>
</div>
))}
</BannerSectionGrid>
</BannerSection>
</div>
</Layout>
);
@@ -8,60 +8,21 @@
line-height: 56px;
word-break: break-word;
}
}
.banner,
.officialInitiatives,
.communityInitiatives,
.trainingNCertifications,
.commercialPartners {
:global(.row .col) {
max-width: 50%;
display: flex;
flex-direction: column;
:global(.bulletLine) {
width: 50px;
}
p {
text-align: justify;
flex: 1;
}
p {
text-align: justify;
}
}
.banner,
.communityInitiatives,
.commercialPartners {
background: linear-gradient(90.49deg, #121212 15.36%, #282828 70.44%);
// clip-path: polygon(0 0, 100% 0, 100% calc(100% - 2vw - 10px), 0 100%);
}
.listContainer {
height: 100%;
align-items: stretch !important;
grid-template-rows: auto 1fr;
.banner {
ul {
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
}
.officialInitiatives {
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%
);
}
+32 -41
View File
@@ -1,5 +1,8 @@
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import { BannerSection } from '@site/src/components/banner-section/banner-section';
import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid';
import { ContentBlock } from '@site/src/components/content-block/content-block';
import Layout from '@theme/Layout';
import { clsx } from 'clsx';
import React from 'react';
@@ -162,50 +165,38 @@ export function Demos() {
<Layout>
<div className={clsx(demosStyles.communityPage)}>
{demoItems.map((demoItem, index) => (
<section
className={clsx(
demosStyles.banner,
index % 2 === 0 && demosStyles.bannerGradient,
)}
<BannerSection
key={index}
greyBackground={index % 2 === 0}
className={demosStyles.banner}
>
<div className={clsx('container')}>
<div className="row">
<div className={clsx('col col--5', 'padding-vert--xl')}>
<h1 className={clsx('margin-bottom--lg')}>
{demoItem.title}
</h1>
<BannerSectionGrid>
<ContentBlock
title={<h1>{demoItem.title}</h1>}
actionButtons={[
{
link: demoItem.actionItemLink,
label: 'WATCH NOW',
},
]}
>
{demoItem.content}
</ContentBlock>
{React.isValidElement(demoItem.content) ? (
demoItem.content
) : (
<p>{demoItem.content}</p>
)}
{demoItem.actionItemLink && (
<Link
className="button button--primary button--lg"
to={demoItem.actionItemLink}
>
WATCH NOW
</Link>
)}
</div>
<div className={clsx('col col--7', 'padding-vert--xl')}>
{demoItem.media.type === 'image' ? (
<img src={demoItem.media.link} alt={demoItem.title} />
) : (
<iframe
src={demoItem.media.link}
title={demoItem.title}
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowFullScreen
></iframe>
)}
</div>
<div className={clsx()}>
{demoItem.media.type === 'image' ? (
<img src={demoItem.media.link} alt={demoItem.title} />
) : (
<iframe
src={demoItem.media.link}
title={demoItem.title}
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowFullScreen
></iframe>
)}
</div>
</div>
</section>
</BannerSectionGrid>
</BannerSection>
))}
</div>
</Layout>
@@ -22,7 +22,3 @@
min-height: 500px;
}
}
.bannerGradient {
background: linear-gradient(90.49deg, #121212 15.36%, #282828 70.44%);
}
+55 -56
View File
@@ -1,7 +1,8 @@
import BrowserOnly from '@docusaurus/BrowserOnly';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import { BannerSection } from '@site/src/components/banner-section/banner-section';
import { BannerSectionColumns } from '@site/src/components/banner-section/banner-section-columns';
import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid';
import { ContentBlock } from '@site/src/components/content-block/content-block';
import Layout from '@theme/Layout';
import { clsx } from 'clsx';
@@ -12,7 +13,7 @@ import { HubSpotNewAdoptersForm } from './_hub-spot-new-adopters-form';
const hiddenNewsletterBannerKey = 'hiddenNewsletterBanner';
export function Home() {
const HomePage = () => {
const { siteConfig } = useDocusaurusContext();
const [hiddenNewsletterBanner, setHideNewsletterBanner] = useState(() => {
@@ -28,47 +29,42 @@ export function Home() {
<Layout>
<div className={homeStyles.homePage}>
<BannerSection greyBackground>
<BannerSectionColumns
<BannerSectionGrid
header={
<>
{!hiddenNewsletterBanner && (
<div
className={clsx(
'card',
'padding--md',
homeStyles.newsletterBanner,
)}
>
<div className="text--left bannerContent">
🗞 Want to stay up to date with Backstage? Sign up for our{' '}
<Link
to="https://info.backstage.spotify.com/newsletter_subscribe"
className="text--secondary"
>
Newsletter
</Link>
!
</div>
<div
className={clsx(
'button button--link',
'bannerCloseButton',
)}
onClick={() => hideNewsletterBanner(true)}
!hiddenNewsletterBanner && (
<div
className={clsx(
'card',
'padding--md',
homeStyles.newsletterBanner,
)}
>
<div className="text--left bannerContent">
🗞 Want to stay up to date with Backstage? Sign up for our{' '}
<Link
to="https://info.backstage.spotify.com/newsletter_subscribe"
className="text--secondary"
>
<svg
className="text--secondary"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>
</div>
Newsletter
</Link>
!
</div>
)}
</>
<div
className={clsx('button button--link', 'bannerCloseButton')}
onClick={() => hideNewsletterBanner(true)}
>
<svg
className="text--secondary"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>
</div>
</div>
)
}
>
<ContentBlock
@@ -100,11 +96,11 @@ export function Home() {
src={`${siteConfig.baseUrl}animations/backstage-logos-hero-8.gif`}
/>
</div>
</BannerSectionColumns>
</BannerSectionGrid>
</BannerSection>
<BannerSection>
<BannerSectionColumns>
<BannerSectionGrid>
<ContentBlock
title="The Speed Paradox"
topImgSrc={`${siteConfig.baseUrl}animations/backstage-speed-paradox-7.gif`}
@@ -126,7 +122,7 @@ export function Home() {
infrastructure complexity. So you can return to building and
scaling, quickly and safely.
</ContentBlock>
</BannerSectionColumns>
</BannerSectionGrid>
</BannerSection>
<BannerSection greenGradientBackground>
@@ -386,20 +382,19 @@ export function Home() {
</BannerSection>
<BannerSection greenBottomGradientBackground>
<BannerSectionColumns
<BannerSectionGrid
className={homeStyles.kubernetesSectionContainer}
header={
<div className={homeStyles.softwareTemplatesContainer}>
<div className="softwareTemplatesTitle">
<img
src={`${siteConfig.baseUrl}animations/backstage-kubernetes-icon-1.gif`}
alt="Backstage Kubernetes Flag GIF"
/>
<>
<img
src={`${siteConfig.baseUrl}animations/backstage-kubernetes-icon-1.gif`}
alt="Backstage Kubernetes Flag GIF"
/>
<h2 className="text--primary">Backstage Kubernetes</h2>
<h2 className="text--primary">Backstage Kubernetes</h2>
<h1>Manage your services, not clusters</h1>
</div>
</div>
<h1>Manage your services, not clusters</h1>
</>
}
>
<ContentBlock
@@ -426,7 +421,7 @@ export function Home() {
Now you don't have to switch dashboards when you move from local
testing to production, or from one cloud provider to another
</ContentBlock>
</BannerSectionColumns>
</BannerSectionGrid>
</BannerSection>
<BannerSection greenCallToActionGradientBackground>
@@ -536,4 +531,8 @@ export function Home() {
</div>
</Layout>
);
}
};
export const Home = () => {
return <BrowserOnly>{() => <HomePage />}</BrowserOnly>;
};
+11 -1
View File
@@ -60,7 +60,8 @@ $desktopUpBreakpoint: 997px;
}
:global([class*='Title']),
:global([class*='title']) {
:global([class*='title']),
:global([class*='gridHeader']) {
img {
max-width: 190px;
max-height: 190px;
@@ -97,3 +98,12 @@ $desktopUpBreakpoint: 997px;
}
}
}
.kubernetesSectionContainer {
:global([class*='gridHeader']) {
img {
max-width: 190px;
max-height: 190px;
}
}
}