Skip to content

Commit

Permalink
feat(pages/home): refactor with additional reuseable components
Browse files Browse the repository at this point in the history
Signed-off-by: Lachlan Heywood <lachieh@users.noreply.github.com>
  • Loading branch information
lachieh committed Aug 1, 2024
1 parent a472770 commit 98dc0f3
Show file tree
Hide file tree
Showing 36 changed files with 679 additions and 516 deletions.
28 changes: 28 additions & 0 deletions src/pages/_components/decorate/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import SvgSparkles from './img/sparkles.svg';
import { SketchUnderline } from '@site/src/pages/_components/sketch-underline';
import styles from './styles.module.css';
import { SketchSparkles } from '../sketch-sparkles';

type Props = {
children: string;
};

/**
* tagged template function to decorate input with underline `_(.*?)_` and sparkles `\*(.*?)\*`
* @example decorate`Hello _world_ and *everyone*` => <>Hello <SketchUnderline>world</SketchUnderline> and <span>everyone<SvgSparkles /></span></>
* @returns ReactNode with heading decorated
*/
function DecorateText({ children }: Props): React.ReactNode {
const result = children.split(/(_.*?_|\*.*?\*)/).map((part, i) => {
if (part.startsWith('_')) {
return <SketchUnderline key={i}>{part.slice(1, -1)}</SketchUnderline>;
}
if (part.startsWith('*')) {
return <SketchSparkles>{part.slice(1, -1)}</SketchSparkles>;
}
return part;
});
return <>{result}</>;
}

export { DecorateText };
36 changes: 36 additions & 0 deletions src/pages/_components/grid/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { HTMLProps, PropsWithChildren } from 'react';
import styles from './styles.module.css';
import clsx from 'clsx';

type BaseProps = PropsWithChildren<HTMLProps<HTMLDivElement>>;

type GridProps = BaseProps & {
alignLast?: boolean;
center?: boolean;
};

type GridItemProps = BaseProps;

function Grid({ children, className, alignLast, center, ...props }: GridProps) {
return (
<div
className={clsx(styles.grid, className, {
[styles.alignLast]: alignLast,
[styles.center]: center,
})}
{...props}
>
{children}
</div>
);
}

function GridItem({ children, className, ...props }: GridItemProps) {
return (
<div className={clsx(styles.gridItem, className)} {...props}>
{children}
</div>
);
}

export { Grid, GridItem };
58 changes: 58 additions & 0 deletions src/pages/_components/grid/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
.grid {
display: flex;
flex-direction: column;
row-gap: 4rem;
column-gap: 2rem;
}

.gridItem {
display: flex;
flex-direction: column;
align-items: start;
justify-items: start;
gap: 1.25rem;
}

.grid.alignLast .gridItem > *:last-child {
margin-top: auto;
}

.grid.center .gridItem {
text-align: center;
align-items: center;
}

.gridItem:nth-child(1) {
grid-area: a;
}
.gridItem:nth-child(2) {
grid-area: b;
}
.gridItem:nth-child(3) {
grid-area: c;
}

.gridItem > * {
margin-top: 0;
margin-bottom: 0;
}

@media (min-width: 768px) {
.grid {
display: grid;
}
.grid:has(.gridItem:nth-child(2)) {
grid-template: 'a b' 1fr / 1fr 1fr;
}
.grid:has(.gridItem:nth-child(3)) {
grid-template:
'a a b b' 1fr
'. c c .' 1fr / 1fr 1fr 1fr 1fr;
}
}

@media (min-width: 997px) {
.grid:has(.gridItem:nth-child(3)) {
grid-template: 'a b c' 1fr / 1fr 1fr 1fr;
}
}
43 changes: 43 additions & 0 deletions src/pages/_components/section-content/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import clsx from 'clsx';
import styles from './section-content.module.css';
import React from 'react';

type Props = {
hasContainer?: boolean;
align?: 'start' | 'center';
aside?: React.ReactNode;
} & React.HTMLAttributes<HTMLDivElement>;

function SectionContent({
children,
className,
aside,
align = 'start',
hasContainer = true,
...props
}: Props) {
return (
<article
className={clsx(
{
[styles.content]: true,
[styles.alignCenter]: align === 'center',
container: hasContainer,
},
className,
)}
{...props}
>
{aside ? (
<>
<main className={styles.main}>{children}</main>
<aside className={styles.aside}>{aside}</aside>
</>
) : (
children
)}
</article>
);
}

export { SectionContent };
35 changes: 35 additions & 0 deletions src/pages/_components/section-content/section-content.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.content {
display: flex;
flex-direction: column;
align-items: start;
text-align: start;
width: 100%;
}

.content.alignCenter {
align-items: center;
text-align: center;
}

.content + .content {
margin-top: 2rem;
}

.main {
width: 100%;
grid-area: main;
}

.aside {
width: 100%;
max-width: 300px;
margin: 0 auto;
grid-area: aside;
}

@media screen and (min-width: 800px) {
.content:has(.aside) {
display: grid;
grid-template: 'main aside' auto / 2fr 1fr;
}
}
9 changes: 7 additions & 2 deletions src/pages/_components/section-heading/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import React from 'react';
import styles from './styles.module.css';
import { DecorateText } from '../decorate';

type Props = {
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
} & React.HTMLAttributes<HTMLHeadingElement>;

function SectionHeading({ as = 'h3', className, ...props }: Props) {
function SectionHeading({ as = 'h3', className, children, ...props }: Props) {
const Tag = as;
return <Tag className={[styles.heading, className].join(' ')} {...props} />;
return (
<Tag className={[styles.heading, className].join(' ')} {...props}>
{typeof children === 'string' ? <DecorateText>{children}</DecorateText> : children}
</Tag>
);
}

export { SectionHeading };
4 changes: 3 additions & 1 deletion src/pages/_components/section/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React, { PropsWithChildren } from 'react';
import styles from './styles.module.css';

export type SectionColor = 'dark-gray' | 'light-gray' | 'green' | 'space-blue' | 'yellow';

type Props = {
color?: 'dark-gray' | 'light-gray' | 'green' | 'space-blue' | 'yellow';
color?: SectionColor;
className?: string;
} & React.HTMLAttributes<HTMLDivElement>;

Expand Down
1 change: 1 addition & 0 deletions src/pages/_components/section/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from var(--section-button-background) calc(l * 0.9) c h / 1
);
--section-button-hover-color: var(--section-button-color);
--ifm-heading-color: var(--section-color-foreground);
background-color: var(--section-color-background);
color: var(--section-color-foreground);
}
Expand Down
15 changes: 15 additions & 0 deletions src/pages/_components/sketch-sparkles/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import styles from './sketch-sparkles.module.css';
import clsx from 'clsx';
import SvgSparkles from './img/sparkles.svg';

function SketchSparkles({ children, ...props }) {
return (
<span className={clsx(styles.sparkles, 'sketch sketch--sparkles')} {...props}>
{children}
<SvgSparkles className={clsx(styles.image, 'sketch__svg')} />
</span>
);
}

export { SketchSparkles };
12 changes: 12 additions & 0 deletions src/pages/_components/sketch-sparkles/sketch-sparkles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.underline {
position: relative;
color: inherit;
}

.image {
position: absolute;
color: var(--section-color-highlight);
width: 2.5rem;
right: 0;
bottom: 60%;
}
16 changes: 0 additions & 16 deletions src/pages/_index/_components/case-studies/case-studies.module.css
Original file line number Diff line number Diff line change
@@ -1,26 +1,10 @@
.studies {
display: flex;
flex-direction: column;
gap: 1rem;
margin-top: 3rem;
}

.study {
display: flex;
flex-direction: column;
}

.study h4 {
color: inherit;
font-size: 1.7rem;
font-family: var(--wasmcloud-font-heading);
font-weight: 500;
}

.study img :global(#alttext-image) {
display: none;
}

.study :last-child {
margin-top: auto;
}
Expand Down
43 changes: 30 additions & 13 deletions src/pages/_index/_components/case-studies/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { Section } from '@site/src/pages/_components/section';
import { Section, SectionColor } from '@site/src/pages/_components/section';
import { SectionHeading } from '@site/src/pages/_components/section-heading';
import { SectionTag } from '@site/src/pages/_components/section-tag';
import React from 'react';
import styles from './case-studies.module.css';
import { SectionContent } from '@site/src/pages/_components/section-content';
import { Grid, GridItem } from '@site/src/pages/_components/grid';

type Props = {};
type Props = {
color?: SectionColor;
tag?: React.ReactNode;
heading?: React.ReactNode;
content?: typeof CONTENT;
};

type CaseStudyContent = {
name: string;
Expand Down Expand Up @@ -47,15 +54,25 @@ const CONTENT: [CaseStudyContent, CaseStudyContent] = [
},
];

function CaseStudies({}: Props) {
const HEADING = 'Solving real problems for your business';
const TAG = 'Case Studies';

function CaseStudies({
color = 'light-gray',
tag = TAG,
heading = HEADING,
content = CONTENT,
}: Props) {
return (
<Section color="light-gray" id="case-studies">
<div className="container">
<SectionTag>Case Studies</SectionTag>
<SectionHeading>Solving real problems for your business</SectionHeading>
<div className={styles.studies}>
{CONTENT.map((study, i) => (
<div className={styles.study} key={i}>
<Section color={color} id="case-studies">
<SectionContent>
<SectionTag>{tag}</SectionTag>
<SectionHeading>{heading}</SectionHeading>
</SectionContent>
<SectionContent>
<Grid>
{content.map((study, i) => (
<GridItem className={styles.study} key={i}>
<h4>
<img src={study.logo} alt={study.name} />
</h4>
Expand All @@ -65,10 +82,10 @@ function CaseStudies({}: Props) {
View Case Study
</a>
</p>
</div>
</GridItem>
))}
</div>
</div>
</Grid>
</SectionContent>
</Section>
);
}
Expand Down
Loading

0 comments on commit 98dc0f3

Please sign in to comment.