Merge pull request #616 from omnivore-app/OMN-585

[Omn-585] - Onboarding Pages 1, 4, 5, and 6.
This commit is contained in:
Jackson Harper
2022-05-23 14:05:24 -07:00
committed by GitHub
25 changed files with 2007 additions and 69 deletions

View File

@ -5,7 +5,7 @@ import { OmnivoreNameLogo } from '../../components/elements/images/OmnivoreNameL
import { StyledText } from '../../components/elements/StyledText'
import { Button } from '../../components/elements/Button'
const TOTAL_ONBOARDING_PAGES = 3
const TOTAL_ONBOARDING_PAGES = 6
type OnboardingLayout2Props = {
pageNumber: number
@ -14,6 +14,8 @@ type OnboardingLayout2Props = {
description?: string
children: ReactNode
image?: ReactNode
nextPage?: string,
reduceSpace?: boolean,
}
const OnboardingLayout2 = ({
@ -23,7 +25,30 @@ const OnboardingLayout2 = ({
description,
image,
children,
nextPage,
reduceSpace
}: OnboardingLayout2Props) => {
const NextButton = () => (
<Button
style="ctaDarkYellow"
css={{
width: '111px',
height: '44px',
color: 'rgba(10, 8, 6, 0.8)',
fontWeight: 600,
fontSize: '16px',
textDecoration: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
as="a"
href={nextPage ? nextPage : `/onboarding/0${pageNumber+1}`}
>
Next
</Button>
)
return (
<>
<PageMetaData
@ -35,6 +60,9 @@ const OnboardingLayout2 = ({
display: 'grid',
gridTemplateColumns: '1fr',
minHeight: '100vh',
'@lgDown': {
gridTemplateRows: reduceSpace ? 0 : 'initial',
},
'@lg': {
gridTemplateColumns: '1fr 2fr',
},
@ -150,18 +178,7 @@ const OnboardingLayout2 = ({
>
Skip
</Button>
<Button
style="ctaDarkYellow"
css={{
width: '111px',
height: '44px',
color: 'rgba(10, 8, 6, 0.8)',
fontWeight: 600,
fontSize: '16px',
}}
>
Next
</Button>
<NextButton />
</HStack>
</VStack>
<VStack
@ -183,6 +200,7 @@ const OnboardingLayout2 = ({
{description && (
<Box
css={{
position: 'relative',
fontWeight: 600,
fontSize: 16,
color: 'rgba(10, 8, 6, 0.8)',
@ -220,18 +238,7 @@ const OnboardingLayout2 = ({
>
Skip
</Button>
<Button
style="ctaDarkYellow"
css={{
width: '111px',
height: '44px',
color: 'rgba(10, 8, 6, 0.8)',
fontWeight: 600,
fontSize: '16px',
}}
>
Next
</Button>
<NextButton />
</HStack>
</>
)

View File

@ -0,0 +1,81 @@
import { SelectionOptionCard } from './SelectOption'
import OnboardingLayout2 from '../OnboardingLayout2'
import { Box, HStack, VStack } from '../../elements/LayoutPrimitives'
const articleDetails = [
{
title: 'Winnebago Electric RV Concept',
author: 'Omnivore',
originText: 'wired.com',
description: "An incredible number of lines from William Shakespeare's plays have becomeso ingrained in modern vernacular …",
image: "https://images.hgmsites.net/sml/cadillac_100789665_s.jpg",
labels: []
},
{
title: 'Winnebago Electric RV Concept',
author: 'Omnivore',
originText: 'wired.com',
description: "An incredible number of lines from William Shakespeare's plays have becomeso ingrained in modern vernacular …",
image: "https://images.hgmsites.net/sml/cadillac_100789665_s.jpg",
labels: []
},
{
title: '21 Phrases You Use Without Realizin…',
author: 'Omnivore',
originText: 'wired.com',
description: "An incredible number of lines from William Shakespeare's plays have becomeso ingrained in modern vernacular …",
image: "",
labels: [],
},
{
title: '21 Phrases You Use Without Realizin…',
author: 'Omnivore',
originText: 'wired.com',
description: "An incredible number of lines from William Shakespeare's plays have becomeso ingrained in modern vernacular …",
image: "https://images.hgmsites.net/sml/cadillac_100789665_s.jpg",
labels: []
},
]
const OnboardingPage1 = () => {
return (
<OnboardingLayout2
pageNumber={1}
title="Read Distraction Free"
subTitle="Omnivore's distraction free reader gives you an uncluttered reading experience"
description='Add some great reads to your library now:'
image={
<img
src='/static/images/onboarding/expanded-controls.svg'
alt="Expanded control"
/>
}
>
<VStack css={{
marginTop: '$4',
marginBottom: '$6'
}}>
<HStack>
<Box css={{
display: 'grid',
gridTemplateColumns: '100%',
gridColumnGap: '$3',
gridRowGap: '$2',
'@md': {
gridTemplateColumns: '50% 50%',
},
}}>
{articleDetails.map(({ title, author, originText, description, image, labels }, idx) => (
<SelectionOptionCard
key={idx}
{...{ title, author, originText, description, image, labels }}
/>
))}
</Box>
</HStack>
</VStack>
</OnboardingLayout2>
)
}
export default OnboardingPage1

View File

@ -37,6 +37,7 @@ const OnboardingPage3 = () => {
description="Subscribe to some newsletters now"
title="Read all your Newsletters in Omnivore"
pageNumber={3}
nextPage={'/onboarding/05'}
>
<VStack css={{
marginTop: '$4',

View File

@ -0,0 +1,55 @@
import React from 'react'
import OnboardingLayout2 from '../OnboardingLayout2'
import { Box } from '../../elements/LayoutPrimitives'
import { styled } from '../../tokens/stitches.config'
const StyledImage = styled('img', {
position: 'relative',
})
const OnboardingPage4 = () => {
return (
<OnboardingLayout2
pageNumber={4}
title="Organize all your content"
subTitle="Information about archiving and tagging
Amet minim mollit non deserunt ullamco est sit aliqua dolor do amet sint. Velit officia consequat duis enim velit mollit. Exercitation veniam consequat sunt nostrud amet."
>
<Box css={{width: '100%', height: '100%'}}>
<StyledImage
src='/static/images/onboarding/organize-content.svg'
alt="Organize Content Desktop"
css={{
width: '100%',
height: '500px',
'@smDown': {
display: 'none',
},
'@lg': {
height: '75%',
},
'@xl': {
width: 'auto',
height: '95%',
}
}}
/>
<StyledImage
src='/static/images/onboarding/organize-content-mobile.svg'
alt="Organize Content Mobile"
css={{
mt: 10,
right: '1.6vh',
objectFit: 'contain',
width: '100%',
'@sm': {
display: 'none',
}
}}
/>
</Box>
</OnboardingLayout2>
)
}
export default OnboardingPage4

View File

@ -0,0 +1,41 @@
import React from 'react'
import OnboardingLayout2 from '../OnboardingLayout2'
import { Box } from '../../elements/LayoutPrimitives'
import { styled } from '../../tokens/stitches.config'
const StyledImage = styled('img', {
position: 'relative',
width: '100%',
height: '100%',
'@smDown': {
width: '160%',
height: 'auto',
}
})
const OnboardingPage5 = () => {
return (
<OnboardingLayout2
pageNumber={5}
title="Highlight and share"
subTitle="Information about creating and sharing highlights Amet minim mollit non deserunt ullamco est sit aliqua dolor do amet sint. Velit officia consequat duis enim velit mollit. Exercitation veniam consequat sunt nostrud amet."
>
<Box css={{
width: '100%',
height: '100%',
overflow: 'hidden',
'@smDown': {
width: '100%',
height: 'auto',
}
}}>
<StyledImage
src='/static/images/onboarding/highlight-and-share.svg'
alt="Highlight And Share"
/>
</Box>
</OnboardingLayout2>
)
}
export default OnboardingPage5

View File

@ -0,0 +1,74 @@
import React from 'react'
import OnboardingLayout2 from '../OnboardingLayout2'
import { Box, HStack, VStack } from '../../elements/LayoutPrimitives'
import { styled } from '../../tokens/stitches.config'
const IconContainer = styled(Box, {width: '30%', justifyContent: 'center', display: 'flex'})
const Icon = styled('img', {width: 100})
const Row = styled(HStack, {
width: '100%',
padding: 30,
borderBottom: '1px solid rgba(0, 0, 0, 0.06)',
'@smDown': {
padding: 20,
}
})
const Text = styled(Box, {
width: '65%',
alignSelf: 'center',
color: '#0A0806CC',
fontSize: 24,
fontWeight: '700',
'@smDown': {
fontSize: 16,
}
})
const Container = styled(Box, {
width: 523,
border: '1px solid #0000000F',
background: 'white',
'@smDown': {
width: '95%',
}
})
const OnboardingPage6 = () => {
return (
<OnboardingLayout2
pageNumber={6}
title="Join our Community"
subTitle='Omnivore is open source and open community, join us.'
nextPage='/home'
reduceSpace
>
<HStack distribution='center' alignment='center' css={{width: '100%', height: '100%'}}>
<Container>
<VStack>
<Row distribution='between'>
<IconContainer>
<Icon css={{height: 60}} src='/static/images/onboarding/github.svg' alt="Github Logo" />
</IconContainer>
<Text>Star us on Github</Text>
</Row>
<Row distribution='between'>
<IconContainer>
<Icon src='/static/images/onboarding/discord.svg' alt="Discrod Logo" />
</IconContainer>
<Text>Join us on Discord</Text>
</Row>
<Row distribution='between'>
<IconContainer>
<Icon css={{width: 74, height: 67}} src='/static/images/onboarding/producthunt.svg' alt="ProductHunt Logo" />
</IconContainer>
<Text>Like us on Product Hunt</Text>
</Row>
</VStack>
</Container>
</HStack>
</OnboardingLayout2>
)
}
export default OnboardingPage6

View File

@ -1,7 +1,11 @@
import React from 'react'
import Checkbox from '../../elements/Checkbox'
import { HStack } from '../../elements/LayoutPrimitives'
import { Box, VStack, HStack, SpanBox } from '../../elements/LayoutPrimitives'
import { CoverImage } from '../../elements/CoverImage'
import { StyledText } from '../../elements/StyledText'
import { authoredByText } from '../../patterns/ArticleSubtitle'
import { LabelChip } from '../../elements/LabelChip'
import { Label } from '../../../lib/networking/fragments/labelFragment'
export const SelectOption: React.FC<{
icon: string
@ -43,3 +47,179 @@ export const SelectOption: React.FC<{
</HStack>
)
}
export const SelectionOptionCard: React.FC <{
title: string,
author: string,
originText: string,
description: string,
image: string,
labels: Label[]
}> = ({title, author, originText, description, image, labels}) => {
const [checked, setChecked] = React.useState(false)
const toggleChecked = () => setChecked(!checked)
return (
<VStack
css={{
p: '$2',
pr: '8px',
height: '100%',
width: '100%',
maxWidth: '100%',
borderRadius: '6px',
cursor: 'pointer',
wordBreak: 'break-word',
overflow: 'clip',
boxShadow: '0px 3px 11px rgba(32, 31, 29, 0.04)',
position: 'relative',
marginRight: '$3',
border: checked ? '1px solid #F9D354' : '1px solid $grayBorder',
backgroundColor: checked ? '#FDFAEC' : '#FFFFFF',
}}
alignment="start"
distribution="start"
onClick={toggleChecked}
>
<Box
css={{
position: 'absolute',
top: '1px',
left: '1px',
width: 'calc(100% - 2px)',
'& > div': {
borderRadius: '100vmax 100vmax 0 0',
},
}}
>
</Box>
<VStack
distribution="start"
alignment="start"
css={{
px: '0px',
width: '100%',
pl: '$1',
}}
>
<HStack
alignment="start"
distribution="between"
css={{
width: '100%',
p: '0px',
mr: '-12px',
mt: '15px',
display: 'grid',
gridTemplateColumns: '1fr 24px',
gridTemplateRows: '1fr',
}}
>
<HStack css={{
alignItems: 'center'
}}>
<Checkbox {...{checked, setChecked}} />
<HStack css={{marginRight: '$2'}} />
<CardTitle title= {title} />
</HStack>
<Box
css={{ alignSelf: 'end', alignItems: 'start', height: '100%' }}
onClick={(e) => {
// This is here to prevent menu click events from bubbling
// up and causing us to "click" on the link item.
e.stopPropagation()
}}
>
</Box>
</HStack>
<HStack alignment="start" distribution="between">
<StyledText style="caption" css={{ my: '0' }}>
{author && (
<SpanBox css={{ mr: '8px' }}>
{authoredByText(author)}
</SpanBox>
)}
<SpanBox css={{ textDecorationLine: 'underline' }}>
{originText}
</SpanBox>
</StyledText>
</HStack>
</VStack>
<HStack
alignment="start"
distribution="between"
css={{
width: '100%',
pt: '$2',
px: '$1',
pr: '12px',
mt: '7px',
flexGrow: '1',
}}
>
<StyledText
css={{
m: 0,
py: '0px',
mr: '$2',
fontStyle: 'normal',
fontWeight: '400',
fontSize: '14px',
lineHeight: '125%',
color: '$grayTextContrast',
flexGrow: '4',
overflow: 'hidden',
display: '-webkit-box',
WebkitLineClamp: 5,
WebkitBoxOrient: 'vertical',
}}
data-testid="listDesc"
>
{description}
</StyledText>
{image && (
<CoverImage
src={image}
alt="Link Preview Image"
width={135}
height={90}
css={{ ml: '10px', mb: '8px', borderRadius: '3px' }}
onError={(e) => {
;(e.target as HTMLElement).style.display = 'none'
}}
/>
)}
</HStack>
<Box css={{ display: 'block', mt: '8px' }}>
{labels?.map(({ name, color }, index) => (
<LabelChip key={index} text={name || ''} color={color} />
))}
</Box>
</VStack>
)
}
type CardTitleProps = {
title: string
}
function CardTitle(props: CardTitleProps): JSX.Element {
return (
<StyledText
style="listTitle"
data-testid="listTitle"
css={{
mt: '0',
mb: '0',
fontWeight: '700',
textAlign: 'left',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
width: '100%',
overflow: 'hidden',
}}
>
{props.title}
</StyledText>
)
}

View File

@ -0,0 +1,5 @@
import OnboardingPage1 from "../../components/templates/onboarding/01";
export default function OnboardingPage01() {
return <OnboardingPage1 />
}

View File

@ -0,0 +1,5 @@
import OnboardingPage4 from "../../components/templates/onboarding/04";
export default function OnboardingPage04() {
return <OnboardingPage4 />
}

View File

@ -0,0 +1,5 @@
import OnboardingPage5 from "../../components/templates/onboarding/05";
export default function OnboardingPage05() {
return <OnboardingPage5 />
}

View File

@ -0,0 +1,5 @@
import OnboardingPage6 from "../../components/templates/onboarding/06";
export default function OnboardingPage06() {
return <OnboardingPage6 />
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 231 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.8 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 270 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.8 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,41 +1,44 @@
import { ComponentStory, ComponentMeta } from '@storybook/react'
import OnboardingLayout from '../components/templates/OnboardingLayout2'
export default {
title: 'Components/OnboardingLayout',
component: OnboardingLayout,
argTypes: {
pageNumber: {
description: 'The current page number of the onboarding process',
},
title: {
description: 'The title of the current onboading screen',
},
subTitle: {
description: 'The subtitle of the current onboading screen',
},
description: {
description: 'The description of the current onboading screen',
},
children: {
description: 'The right column on the page',
},
image: {
description: 'The image on the left column on the page',
},
},
} as ComponentMeta<typeof OnboardingLayout>
const Template: ComponentStory<typeof OnboardingLayout> = (args) => (
<OnboardingLayout {...args}>{args.children}</OnboardingLayout>
)
export const OnboardingLayoutStory = Template.bind({})
OnboardingLayoutStory.args = {
pageNumber: 2,
title: 'Save links to read later',
subTitle:
'Save any link to your library using our apps and browser extensions',
description: 'Install our apps and browser extensions',
children: <div>This is where the child is rendered.</div>
}
import { ComponentStory, ComponentMeta } from '@storybook/react'
import OnboardingLayout from '../components/templates/OnboardingLayout2'
export default {
title: 'Components/OnboardingLayout',
component: OnboardingLayout,
argTypes: {
pageNumber: {
description: 'The current page number of the onboarding process',
},
title: {
description: 'The title of the current onboading screen',
},
subTitle: {
description: 'The subtitle of the current onboading screen',
},
description: {
description: 'The description of the current onboading screen',
},
children: {
description: 'The right column on the page',
},
image: {
description: 'The image on the left column on the page',
},
nextPage: {
description: 'The link to which the user is sent when next button is pressed'
}
},
} as ComponentMeta<typeof OnboardingLayout>
const Template: ComponentStory<typeof OnboardingLayout> = (args) => (
<OnboardingLayout {...args}>{args.children}</OnboardingLayout>
)
export const OnboardingLayoutStory = Template.bind({})
OnboardingLayoutStory.args = {
pageNumber: 2,
title: 'Save links to read later',
subTitle:
'Save any link to your library using our apps and browser extensions',
description: 'Install our apps and browser extensions',
children: <div>This is where the child is rendered.</div>
}

View File

@ -0,0 +1,13 @@
import { ComponentStory, ComponentMeta } from '@storybook/react'
import OnboardingPage1 from '../components/templates/onboarding/01'
export default {
title: 'Onboarding-Pages/01',
component: OnboardingPage1,
} as ComponentMeta<typeof OnboardingPage1>
export const OnboardingPage1Story: ComponentStory<typeof OnboardingPage1> = (args: any) => {
return (
<OnboardingPage1 />
)
}

View File

@ -2,7 +2,7 @@ import { ComponentStory, ComponentMeta } from '@storybook/react'
import OnboardingPage2 from '../components/templates/onboarding/02'
export default {
title: 'Components/OnboardingPage2',
title: 'Onboarding-Pages/02',
component: OnboardingPage2,
} as ComponentMeta<typeof OnboardingPage2>

View File

@ -2,7 +2,7 @@ import { ComponentStory, ComponentMeta } from '@storybook/react'
import OnboardingPage3 from '../components/templates/onboarding/03'
export default {
title: 'Components/OnboardingPage3',
title: 'Onboarding-Pages/03',
component: OnboardingPage3,
} as ComponentMeta<typeof OnboardingPage3>

View File

@ -0,0 +1,13 @@
import { ComponentStory, ComponentMeta } from '@storybook/react'
import OnboardingPage4 from '../components/templates/onboarding/04'
export default {
title: 'Onboarding-Pages/04',
component: OnboardingPage4,
} as ComponentMeta<typeof OnboardingPage4>
export const OnboardingPage4Story: ComponentStory<typeof OnboardingPage4> = (args: any) => {
return (
<OnboardingPage4 />
)
}

View File

@ -0,0 +1,13 @@
import { ComponentStory, ComponentMeta } from '@storybook/react'
import OnboardingPage5 from '../components/templates/onboarding/05'
export default {
title: 'Onboarding-Pages/05',
component: OnboardingPage5,
} as ComponentMeta<typeof OnboardingPage5>
export const OnboardingPage5Story: ComponentStory<typeof OnboardingPage5> = (args: any) => {
return (
<OnboardingPage5 />
)
}

View File

@ -0,0 +1,13 @@
import { ComponentStory, ComponentMeta } from '@storybook/react'
import OnboardingPage6 from '../components/templates/onboarding/06'
export default {
title: 'Onboarding-Pages/06',
component: OnboardingPage6,
} as ComponentMeta<typeof OnboardingPage6>
export const OnboardingPage6Story: ComponentStory<typeof OnboardingPage6> = (args: any) => {
return (
<OnboardingPage6 />
)
}