Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(code-samples): add code samples page to showcase boilerplate rep… #461

Merged
merged 11 commits into from
Nov 8, 2023
Binary file added public/images/codesamples.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 8 additions & 1 deletion public/navigation.json
Original file line number Diff line number Diff line change
Expand Up @@ -10060,6 +10060,13 @@
"type": "markdown",
"children": []
},
{
"name": "Code samples and templates",
"slug": "code-samples",
"origin": "",
"type": "markdown",
"children": []
},
{
"name": "Getting Started",
"slug": "vtex-io-getting-started",
Expand Down Expand Up @@ -14998,4 +15005,4 @@
]
}
]
}
}
58 changes: 58 additions & 0 deletions src/components/code-sample-card/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Box, Flex, Text, IconCaret, Link } from '@vtex/brand-ui'

import type { CodeSamplesElement } from 'utils/typings/types'

import styles from './styles'

const CodeSampleCard = ({
title,
description,
builders,
linkTo,
repoLink,
category,
}: CodeSamplesElement) => {
return (
<Flex sx={styles.container}>
<Box sx={styles.innerContent}>
{category && <Text sx={styles.category}>{category}</Text>}
<Text sx={styles.title} className="title">
{title}
</Text>
<Text sx={styles.description} className="description">
{description}
</Text>
<Box sx={styles.builderList}>
{builders.map((builder) => (
<Text sx={styles.builderListItem}>{builder}</Text>
))}
</Box>
<Link href={repoLink} target="_blank">
<Text sx={styles.link} className="link">
View GitHub repository
</Text>
</Link>
</Box>

{linkTo && (
<Flex sx={styles.ctaLink}>
<Link href={linkTo}>
<Flex sx={styles.linkContainer}>
<Text sx={styles.ctaLinkText} className="ctaLinkText">
View documentation
</Text>
<IconCaret
className="caret"
color="#A1A8B3"
direction="right"
size={20}
/>
</Flex>
</Link>
</Flex>
)}
</Flex>
)
}

export default CodeSampleCard
124 changes: 124 additions & 0 deletions src/components/code-sample-card/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import type { SxStyleProp } from '@vtex/brand-ui'

const container: SxStyleProp = {
flexDirection: 'column',
justifyContent: 'space-between',
fontSize: '14px',
mt: '16px',
borderRadius: '4px',
border: '1px solid #E7E9EE',
width: ['100%', '49%'],
transition: 'all 0.3s ease-out',
':active, :hover': {
borderColor: 'muted.2',
boxShadow: '0px 0px 16px rgba(0, 0, 0, 0.1)',
transition: 'all 0.3 ease-out',

'.title, .description': {
transition: 'all 0.3s ease-out',
color: '#000711',
},

'.link, .caret': {
transition: 'all 0.3s ease-out',
color: 'muted.0',
},
},
}

const innerContent: SxStyleProp = {
padding: '16px',
}

const category: SxStyleProp = {
textTransform: 'uppercase',
fontWeight: '600',
fontSize: '12px',
letterSpacing: '0.8px',
color: '#a1a8b3',
mb: '10px',
}

const title: SxStyleProp = {
mb: '6px',
fontSize: '16px',
fontWeight: 'bold',
lineHeight: '22px',
color: 'muted.0',
}

const description: SxStyleProp = {
fontSize: '1.05em',
fontWeight: '400',
color: 'muted.0',
maxHeight: '82px',
}

const ctaLink: SxStyleProp = {
padding: '12px 0',
maxHeight: '56px',
justifyContent: 'center',
alignItems: 'center',
borderTop: '1px solid #E7E9EE',
borderBottomLeftRadius: '8px',
borderBottomRightRadius: '8px',
transition: 'all 0.3s ease-out',
'.ctaLinkText': {
transition: 'all 0.3s ease-out',
},
':active, :hover': {
backgroundColor: '#F8F7FC',
transition: 'all 0.3s ease-out',
'.ctaLinkText': {
color: '#000711',
transition: 'all 0.3s ease-out',
},
},
}

const ctaLinkText: SxStyleProp = {
fontSize: '1.1em',
fontWeight: '400',
color: 'muted.0',
}

const linkContainer: SxStyleProp = {
alignItems: 'center',
}

const link: SxStyleProp = {
mt: '10px',
color: 'muted.1',
textDecoration: 'underline',
':hover': {
color: '#e31d58 !important',
},
}

const builderList: SxStyleProp = {
display: 'flex',
gap: '8px',
mt: '10px',
flexWrap: 'wrap',
}

const builderListItem: SxStyleProp = {
bg: 'muted.3',
px: '6px',
borderRadius: '4px',
display: 'inline',
}

export default {
container,
innerContent,
title,
description,
link,
linkContainer,
builderList,
builderListItem,
ctaLink,
ctaLinkText,
category,
}
40 changes: 40 additions & 0 deletions src/components/code-sample-section/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useState } from 'react'
import { Box, Flex } from '@vtex/brand-ui'

import { codeSamples } from 'utils/constants'

import styles from 'styles/documentation-landing-page'
import Multiselect from 'components/multiselect'
import { SelectOption } from 'utils/typings/types'
import CodeSampleCard from 'components/code-sample-card'

interface ICodeSamplesSection {
builders: SelectOption[]
}

const CodeSamplesSection = ({ builders }: ICodeSamplesSection) => {
const [filter, setFilter] = useState<SelectOption[]>([])
const filteredCodeSamples = codeSamples.filter(
(codeSampleItem) =>
filter.length === 0 ||
filter.some((option) => codeSampleItem.builders.includes(option.label))
)
return (
<Box sx={styles.contentContainer}>
<Multiselect
title={'All builders'}
options={builders}
onSelect={(selection) => {
setFilter(selection)
}}
/>
<Flex sx={styles.cardsContainer}>
{filteredCodeSamples.map((codeSample) => (
<CodeSampleCard {...codeSample} key={codeSample.title} />
))}
</Flex>
</Box>
)
}

export default CodeSamplesSection
2 changes: 1 addition & 1 deletion src/components/icons/github-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const GithubIcon = (props: IconProps) => (
fillRule="evenodd"
clipRule="evenodd"
d="M14.4 16.7314C10.6667 20.7314 8 26.3314 8 33.5314C8 38.8647 9.86667 43.9314 12.8 47.9314C16.2667 52.4647 21.3333 55.1314 24 56.198V54.3314C24 54.3314 24 50.0647 26.4 46.3314C21.0667 46.0647 16.8 40.998 16.8 35.1314C16.8 32.998 17.6 31.1314 18.9333 29.5314L19.2 24.4647C19.2 23.1314 20.5333 22.3314 21.8667 22.598L27.4667 24.7314C29.0667 24.4647 30.6667 24.198 32.5333 24.198C34.4 24.198 36 24.4647 37.6 24.7314L42.4 22.3314C43.7333 21.798 45.0667 22.8647 45.0667 24.198L45.3333 29.2647C46.6667 30.8647 47.4667 32.998 47.4667 34.8647C47.4667 40.7314 43.2 45.5314 37.8667 46.0647C40.2667 49.798 40.2667 54.0647 40.2667 54.0647V55.9314C42.9333 54.8647 48 52.198 51.4667 47.6647C54.4 43.9314 56.2667 38.598 56.2667 33.2647C56.2667 26.0647 53.6 20.4647 49.8667 16.4647C44.8 11.398 37.8667 8.99805 32 8.99805C26.1333 8.99805 19.2 11.398 14.4 16.7314V16.7314Z"
stroke="#4A596B"
stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
Expand Down
12 changes: 9 additions & 3 deletions src/components/multiselect/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ const multiselect: SxStyleProp = {
}

const input: SxStyleProp = {
padding: '8px 12px 7px',
fontSize: '15px',
padding: '8px 12px 4px',
background: '#F4F4F4',
borderRadius: '4px',
justifyContent: 'space-between',
width: '230px',
width: '150px',
cursor: 'pointer',
}

Expand All @@ -38,6 +39,9 @@ const dropdown: SxStyleProp = {

const optionsContainer: SxStyleProp = {
flexDirection: 'column',
overflowY: 'auto',
maxHeight: '35vh',
width: '256px',
}

const checkbox: SxStyleProp = {
Expand All @@ -48,12 +52,14 @@ const checkbox: SxStyleProp = {
}

const option: SxStyleProp = {
fontSize: '15px',
columnGap: '8px',
padding: '8px 0px',
}

const buttonsContainer: SxStyleProp = {
marginTop: '10px',
marginTop: '14px',
justifyContent: 'flex-end',
}

export default {
Expand Down
89 changes: 89 additions & 0 deletions src/pages/docs/guides/code-samples.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import PageHeader from 'components/page-header'
import { getMessages } from 'utils/get-messages'
import image from '../../../../public/images/codesamples.png'
import Head from 'next/head'
import CodeSamplesSection from 'components/code-sample-section'
import getNavigation from 'utils/getNavigation'
import { codeSamples } from 'utils/constants'
import { CodeSamplesElement, SelectOption } from 'utils/typings/types'
import { GetStaticProps, NextPage } from 'next'
import { PreviewContext } from 'utils/contexts/preview'
import { useContext } from 'react'
import { DocumentationTitle, UpdatesTitle } from 'utils/typings/unionTypes'

interface Props {
sidebarfallback: any //eslint-disable-line
sectionSelected?: DocumentationTitle | UpdatesTitle | ''
builders: SelectOption[]
branch: string
}

const AppDevelopmentPage: NextPage<Props> = ({ builders, branch }) => {
const { setBranchPreview } = useContext(PreviewContext)
setBranchPreview(branch)
const messages = getMessages()
return (
<>
<Head>
<title>Code Samples</title>
<meta
property="og:title"
content={messages['app_development_page.subtitle']}
key="title"
/>
<meta
name="docsearch:doctitle"
content={messages['app_development_page.title']}
/>
<meta name="docsearch:doctype" content="App Development" />
</Head>
<>
<PageHeader
title="Code samples and templates"
description="Simplify your development process with ready-to-use code templates"
imageUrl={image}
imageAlt={messages['app_development_page.title']}
/>
<CodeSamplesSection builders={builders} />
</>
</>
)
}

export const getStaticProps: GetStaticProps = async ({
preview,
previewData,
}) => {
const sidebarfallback = await getNavigation()
const sectionSelected = 'App Development'
const previewBranch =
preview && JSON.parse(JSON.stringify(previewData)).hasOwnProperty('branch')
? JSON.parse(JSON.stringify(previewData)).branch
: 'main'
const branch = preview ? previewBranch : 'main'

function getBuilders(samples: CodeSamplesElement[]) {
const uniqueBuilders: Map<string, string> = new Map()

for (const sample of samples) {
sample.builders.forEach((builder) => {
uniqueBuilders.set(builder, builder) // Using Map to ensure uniqueness
})
}

return Array.from(uniqueBuilders, ([id, label]) => ({ id, label }))
}

const builders: SelectOption[] = getBuilders(codeSamples)

return {
props: {
sidebarfallback,
sectionSelected,
builders,
branch,
},
}
}

export default AppDevelopmentPage
Loading
Loading