Merge pull request #1410 from omnivore-app/feat/landingPages
Landing Page Updates - Desktop done
@ -2,11 +2,11 @@ import { HStack, VStack, Box } from '../../elements/LayoutPrimitives'
|
||||
import { CSS, styled } from '@stitches/react'
|
||||
|
||||
type LandingSectionProps = {
|
||||
titleText: string,
|
||||
descriptionText: React.ReactElement,
|
||||
icon: React.ReactElement,
|
||||
image: React.ReactElement,
|
||||
containerStyles?: CSS,
|
||||
titleText: string
|
||||
descriptionText: React.ReactElement
|
||||
icon?: React.ReactElement
|
||||
image: React.ReactElement
|
||||
containerStyles?: CSS
|
||||
}
|
||||
|
||||
const MainContainer = styled(HStack, {
|
||||
@ -25,66 +25,40 @@ const titleTextStyles = {
|
||||
},
|
||||
'@xl': {
|
||||
fontSize: 45,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const descriptionTextStyles = {
|
||||
color: 'rgb(125, 125, 125)',
|
||||
}
|
||||
|
||||
const iconContainerStyles = {
|
||||
width: 56,
|
||||
height: 56,
|
||||
background: 'white',
|
||||
border: '1px solid rgba(61, 61, 61, 0.08)',
|
||||
boxSizing: 'border-box',
|
||||
borderRadius: '50%',
|
||||
'@mdDown': {
|
||||
width: 32,
|
||||
height: 32,
|
||||
padding: 5,
|
||||
},
|
||||
}
|
||||
|
||||
const imageContainerStyles = {
|
||||
width: '50%',
|
||||
alignSelf: 'center',
|
||||
'@mdDown': {
|
||||
width: 0,
|
||||
display: 'none',
|
||||
}
|
||||
width: '100%',
|
||||
},
|
||||
}
|
||||
|
||||
const layoutStyles = {
|
||||
width: '50%',
|
||||
padding: 10,
|
||||
alignSelf: 'center',
|
||||
padding: 20,
|
||||
'@mdDown': {
|
||||
width: '100%',
|
||||
}
|
||||
}
|
||||
|
||||
const innerLayoutStyles = {
|
||||
maxWidth: 480,
|
||||
alignSelf: 'center',
|
||||
'@mdDown': {
|
||||
alignItems: 'center',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
export function LandingSection(props: LandingSectionProps): JSX.Element {
|
||||
return (
|
||||
<MainContainer distribution='start' alignment='center' css={props.containerStyles}>
|
||||
<VStack distribution='center' css={layoutStyles}>
|
||||
<VStack css={innerLayoutStyles}>
|
||||
<VStack distribution='center' alignment='center' css={iconContainerStyles}>
|
||||
{props.icon}
|
||||
</VStack>
|
||||
<Box css={titleTextStyles}>{props.titleText}</Box>
|
||||
<Box css={descriptionTextStyles}>{props.descriptionText}</Box>
|
||||
</VStack>
|
||||
return (
|
||||
<MainContainer css={{ flexWrap: 'wrap', ...props.containerStyles }}>
|
||||
<VStack distribution="center" alignment={'center'} css={layoutStyles}>
|
||||
<VStack>
|
||||
<Box css={titleTextStyles}>{props.titleText}</Box>
|
||||
<Box css={descriptionTextStyles}>{props.descriptionText}</Box>
|
||||
</VStack>
|
||||
<HStack distribution='center' css={imageContainerStyles}>
|
||||
{props.image}
|
||||
</HStack>
|
||||
</MainContainer>
|
||||
)
|
||||
</VStack>
|
||||
<Box css={imageContainerStyles}>{props.image}</Box>
|
||||
</MainContainer>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import Link from 'next/link'
|
||||
import { VStack, Box, SpanBox } from '../../elements/LayoutPrimitives'
|
||||
import { CurvedUnderlineIcon } from '../../elements/images/CurvedUnderlineIcon'
|
||||
import { VStack, Box } from '../../elements/LayoutPrimitives'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { MagnifyingGlass, Palette, EnvelopeSimple, FloppyDisk, ArrowRight } from 'phosphor-react'
|
||||
import { ArrowRight } from 'phosphor-react'
|
||||
import { LandingSection } from './LandingSection'
|
||||
|
||||
const buttonStyles = {
|
||||
@ -10,23 +9,30 @@ const buttonStyles = {
|
||||
borderRadius: 4,
|
||||
px: 30,
|
||||
background: 'rgb(255, 210, 52)',
|
||||
color: '#3D3D3D'
|
||||
color: '#3D3D3D',
|
||||
}
|
||||
|
||||
const arrowStyles = {
|
||||
marginLeft: 10,
|
||||
marginLeft: 10,
|
||||
padding: 2,
|
||||
}
|
||||
|
||||
export function GetStartedButton(): JSX.Element {
|
||||
return (
|
||||
<Button style='ctaDarkYellow' css={buttonStyles}>
|
||||
<Link passHref href='/login'>
|
||||
<a style={{textDecoration: 'none', color: '#3D3D3D'}}>
|
||||
Sign Up
|
||||
<Button style="ctaDarkYellow" css={buttonStyles}>
|
||||
<Link passHref href="/login">
|
||||
<a style={{ textDecoration: 'none', color: '#3D3D3D' }}>
|
||||
Sign Up for Free
|
||||
</a>
|
||||
</Link>
|
||||
<ArrowRight size={18} width={18} height={18} style={arrowStyles} color='white' fontWeight='700' />
|
||||
<ArrowRight
|
||||
size={18}
|
||||
width={18}
|
||||
height={18}
|
||||
style={arrowStyles}
|
||||
color="black"
|
||||
fontWeight="800"
|
||||
/>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
@ -36,7 +42,8 @@ const containerStyles = {
|
||||
pt: 32,
|
||||
pb: 100,
|
||||
width: '100%',
|
||||
background: 'linear-gradient(0deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2)), linear-gradient(0deg, rgba(253, 250, 236, 0.7), rgba(253, 250, 236, 0.7))',
|
||||
background:
|
||||
'linear-gradient(0deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2)), linear-gradient(0deg, rgba(253, 250, 236, 0.7), rgba(253, 250, 236, 0.7))',
|
||||
'@mdDown': {
|
||||
pt: 50,
|
||||
},
|
||||
@ -45,38 +52,15 @@ const containerStyles = {
|
||||
},
|
||||
'@xl': {
|
||||
px: '100px',
|
||||
}
|
||||
}
|
||||
|
||||
const titleStyles = {
|
||||
fontWeight: '600',
|
||||
fontSize: '24',
|
||||
textAlign: 'center',
|
||||
lineHeight: '36px',
|
||||
color: '#FF9B3E',
|
||||
'@mdDown': {
|
||||
fontSize: 16,
|
||||
letterSpacing: '0.02em'
|
||||
}
|
||||
}
|
||||
|
||||
const subTitleText = {
|
||||
fontSize: 64,
|
||||
maxWidth: 590,
|
||||
fontWeight: '700',
|
||||
textAlign: 'center',
|
||||
lineHeight: '70px',
|
||||
mb: 30,
|
||||
'@mdDown': {
|
||||
maxWidth: 295,
|
||||
fontSize: 32,
|
||||
lineHeight: '40px',
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const reversedSectionStyles = {
|
||||
flexDirection: 'row-reverse',
|
||||
marginBottom: 20
|
||||
marginBottom: 20,
|
||||
'@mdDown': {
|
||||
width: '100%',
|
||||
},
|
||||
}
|
||||
|
||||
const callToActionStyles = {
|
||||
@ -84,13 +68,13 @@ const callToActionStyles = {
|
||||
borderRadius: '24px',
|
||||
boxSizing: 'border-box',
|
||||
border: '1px solid #D8D7D5',
|
||||
boxShadow: '0px 7px 8px rgba(32, 31, 29, 0.03), 0px 18px 24px rgba(32, 31, 29, 0.03)',
|
||||
boxShadow:
|
||||
'0px 7px 8px rgba(32, 31, 29, 0.03), 0px 18px 24px rgba(32, 31, 29, 0.03)',
|
||||
padding: 40,
|
||||
marginTop: 64,
|
||||
height: 330,
|
||||
'@mdDown': {
|
||||
display: 'none',
|
||||
},
|
||||
minheight: 330,
|
||||
width: 'inherit',
|
||||
|
||||
'@md': {
|
||||
width: '100%',
|
||||
},
|
||||
@ -105,21 +89,14 @@ const callToActionText = {
|
||||
fontSize: 64,
|
||||
lineHeight: '70px',
|
||||
textAlign: 'center',
|
||||
maxWidth: 500
|
||||
}
|
||||
|
||||
const underlineIconStyles = {
|
||||
height: '5px',
|
||||
alignSelf: 'normal',
|
||||
position: 'relative',
|
||||
bottom: 20,
|
||||
padding: '20px',
|
||||
}
|
||||
|
||||
type LandingSectionsContainerProps = {
|
||||
hideFirst?: boolean,
|
||||
hideSecond?: boolean,
|
||||
hideThird?: boolean,
|
||||
hideFourth?: boolean,
|
||||
hideFirst?: boolean
|
||||
hideSecond?: boolean
|
||||
hideThird?: boolean
|
||||
hideFourth?: boolean
|
||||
}
|
||||
|
||||
export function LandingSectionsContainer({
|
||||
@ -128,110 +105,152 @@ export function LandingSectionsContainer({
|
||||
hideThird = false,
|
||||
hideFourth = false,
|
||||
}: LandingSectionsContainerProps): JSX.Element {
|
||||
const iconColor = 'rgb(255, 210, 52)'
|
||||
// const iconColor = 'rgb(255, 210, 52)'
|
||||
return (
|
||||
<VStack alignment='center' distribution='start' css={containerStyles}>
|
||||
<VStack alignment="center" distribution="start" css={containerStyles}>
|
||||
<Box
|
||||
css={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
// margin: '40px',
|
||||
'@mdDown': {
|
||||
margin: '0 0 10px 0',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<img
|
||||
srcSet="/static/landing/landingPage-1.png"
|
||||
alt="landingHero-1"
|
||||
style={{
|
||||
width: '70%',
|
||||
maxWidth: '70%',
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{!hideFirst && (
|
||||
<LandingSection
|
||||
titleText='Unclutter your reading.'
|
||||
titleText="Unclutter your reading."
|
||||
descriptionText={
|
||||
<p>
|
||||
Omnivore strips away the ads, trackers, and clutter and
|
||||
formats pages for easy reading without distractions. The
|
||||
text-focused view also makes articles smaller and quicker
|
||||
to load.
|
||||
Omnivore strips away the ads, trackers, and clutter and formats
|
||||
pages for easy reading without distractions. The text-focused view
|
||||
also makes articles smaller and quicker to load.
|
||||
</p>
|
||||
}
|
||||
image={
|
||||
<img
|
||||
srcSet="/static/landing/landing-1.png, /static/landing/landing-1@2x.png 2x"
|
||||
alt='landing-1'
|
||||
style={{height: '50vw', maxHeight: 560}}
|
||||
sizes="auto 50vw, auto 50vw"
|
||||
srcSet="/static/landing/landingPage-2.png"
|
||||
alt="landing-2"
|
||||
style={{ maxHeight: 400 }}
|
||||
/>
|
||||
}
|
||||
icon={<MagnifyingGlass size={32} color={iconColor} weight='duotone' />}
|
||||
/>
|
||||
)}
|
||||
{!hideSecond && (
|
||||
<LandingSection
|
||||
titleText='Go ahead, mark it up.'
|
||||
descriptionText={
|
||||
<>
|
||||
<p>
|
||||
Read actively, not passively. Highlight key sections and add
|
||||
notes as you read. You can access your highlights and notes any
|
||||
time — they stay with your articles forever.
|
||||
</p>
|
||||
<p>
|
||||
Fun fact: research shows that highlighting while you read
|
||||
improves retention and makes you a more effective reader.
|
||||
</p>
|
||||
</>
|
||||
}
|
||||
image={
|
||||
<img
|
||||
srcSet="/static/landing/landing-2.png, /static/landing/landing-2@2x.png 2x"
|
||||
alt='landing-2'
|
||||
style={{width: '100%', marginRight: 40}}
|
||||
sizes="auto 50vw, auto 50vw"
|
||||
/>
|
||||
}
|
||||
icon={<Palette size={32} color={iconColor} weight='duotone' />}
|
||||
containerStyles={reversedSectionStyles}
|
||||
/>
|
||||
)}
|
||||
{!hideThird && (
|
||||
<LandingSection
|
||||
titleText='All your newsletters in one place.'
|
||||
descriptionText={
|
||||
<p>
|
||||
Send subscriptions directly to your Omnivore library, and
|
||||
read them on your own time, away from the constant distractions
|
||||
and interruptions of your email inbox.
|
||||
</p>
|
||||
}
|
||||
image={
|
||||
<img
|
||||
srcSet="/static/landing/landing-4.png, /static/landing/landing-4@2x.png 2x"
|
||||
alt='landing-3'
|
||||
style={{height: '38vw', maxHeight: 480}}
|
||||
sizes="auto 50vw, auto 50vw"
|
||||
/>
|
||||
}
|
||||
icon={<EnvelopeSimple size={32} color={iconColor} weight='duotone' />}
|
||||
/>
|
||||
)}
|
||||
{!hideFourth && (
|
||||
<LandingSection
|
||||
titleText='Save links from anywhere. Forever.'
|
||||
titleText="Save links from anywhere. Forever."
|
||||
descriptionText={
|
||||
<>
|
||||
<p>With the Omnivore app for iOS and Android and extensions for all
|
||||
<p>
|
||||
With the Omnivore app for iOS and Android and extensions for all
|
||||
major web browsers, you can add to your reading list any time.
|
||||
</p>
|
||||
<p>Saved articles remain in your Omnivore library forever — even if the
|
||||
site where you found them goes away. Access them any time in our reader
|
||||
view or in their original format.
|
||||
<p>
|
||||
Saved articles remain in your Omnivore library forever — even if
|
||||
the site where you found them goes away. Access them any time in
|
||||
our reader view or in their original format.
|
||||
</p>
|
||||
</>
|
||||
}
|
||||
image={
|
||||
<img
|
||||
srcSet="/static/landing/landing-3.png, /static/landing/landing-3@2x.png 2x"
|
||||
alt='landing-4'
|
||||
style={{width: '100%', marginRight: 40}}
|
||||
sizes="auto 50vw, auto 50vw"
|
||||
srcSet="/static/landing/landingPage-3.png"
|
||||
alt="landing-3"
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
}
|
||||
icon={<FloppyDisk size={32} color={iconColor} weight='duotone' />}
|
||||
containerStyles={reversedSectionStyles}
|
||||
/>
|
||||
)}
|
||||
<VStack alignment='center' css={callToActionStyles}>
|
||||
<Box css={callToActionText}>
|
||||
Sign up for free
|
||||
</Box>
|
||||
{!hideThird && (
|
||||
<LandingSection
|
||||
titleText="All your newsletters in one place."
|
||||
descriptionText={
|
||||
<p>
|
||||
Send subscriptions directly to your Omnivore library, and read
|
||||
them on your own time, away from the constant distractions and
|
||||
interruptions of your email inbox.
|
||||
</p>
|
||||
}
|
||||
image={
|
||||
<img
|
||||
srcSet="/static/landing/landingPage-4.png"
|
||||
alt="landing-4"
|
||||
style={{ maxHeight: 400, width: '100%' }}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{!hideFourth && (
|
||||
<LandingSection
|
||||
titleText="Stay organized and in control."
|
||||
descriptionText={
|
||||
<p>
|
||||
Read what you want, not what some algorithm says you should. Keep
|
||||
your reading organized and easily available with labels, filters,
|
||||
and fully indexed text searches.
|
||||
</p>
|
||||
}
|
||||
image={
|
||||
<img
|
||||
srcSet="/static/landing/landingPage-5.png"
|
||||
alt="landing-5"
|
||||
style={{ maxHeight: 400 }}
|
||||
/>
|
||||
}
|
||||
containerStyles={reversedSectionStyles}
|
||||
/>
|
||||
)}
|
||||
<LandingSection
|
||||
titleText="Built for advanced users."
|
||||
descriptionText={
|
||||
<p>
|
||||
The intuitive command palette puts basic and advanced functionality
|
||||
at your fingertips. Keyboard shortcuts for all features mean your
|
||||
hands never have to leave the keyboard. Our open-source app allows
|
||||
integrations with knowledge bases and note-taking apps, using
|
||||
plug-ins or by triggering webhooks.
|
||||
</p>
|
||||
}
|
||||
image={
|
||||
<img
|
||||
srcSet="/static/landing/landingPage-6.png"
|
||||
alt="landing-6"
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<LandingSection
|
||||
titleText="Listen to what you're reading."
|
||||
descriptionText={
|
||||
<p>
|
||||
Lorem IpsumRead what you want, not what some algorithm says you
|
||||
should. Keep your reading organized and easily available with
|
||||
labels, filters, and fully indexed text searches.
|
||||
</p>
|
||||
}
|
||||
image={
|
||||
<img
|
||||
srcSet="/static/landing/landingPage-7.png"
|
||||
alt="landing-7"
|
||||
style={{ maxHeight: 400}}
|
||||
/>
|
||||
}
|
||||
containerStyles={reversedSectionStyles}
|
||||
/>
|
||||
<VStack alignment="center" css={callToActionStyles}>
|
||||
<Box css={callToActionText}>Get Started With Omnivore Today</Box>
|
||||
<GetStartedButton />
|
||||
</VStack>
|
||||
</VStack>
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
import { VStack, Box } from './../components/elements/LayoutPrimitives'
|
||||
import { LandingSectionsContainer, GetStartedButton } from '../components/templates/landing/LandingSectionsContainer'
|
||||
import {
|
||||
LandingSectionsContainer,
|
||||
GetStartedButton,
|
||||
} from '../components/templates/landing/LandingSectionsContainer'
|
||||
import { LandingHeader } from '../components/templates/landing/LandingHeader'
|
||||
import { LandingFooter } from '../components/templates/landing/LandingFooter'
|
||||
|
||||
@ -7,14 +10,13 @@ const mobileContainerStyles = {
|
||||
alignSelf: 'center',
|
||||
marginTop: 80,
|
||||
maxWidth: 960,
|
||||
|
||||
px: '2vw',
|
||||
'@md': {
|
||||
px: '6vw',
|
||||
},
|
||||
'@xl': {
|
||||
px: '120px',
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const headingStyles = {
|
||||
@ -24,12 +26,15 @@ const headingStyles = {
|
||||
lineHeight: '53px',
|
||||
padding: '10px',
|
||||
paddingBottom: '0px',
|
||||
textAlign: 'center',
|
||||
}
|
||||
|
||||
|
||||
const subHeadingStyles = {
|
||||
color: 'rgb(125, 125, 125)',
|
||||
padding: '10px',
|
||||
textAlign: 'center',
|
||||
width: '100%',
|
||||
fontWeight: '600',
|
||||
}
|
||||
|
||||
export default function LandingPage(): JSX.Element {
|
||||
@ -38,18 +43,34 @@ export default function LandingPage(): JSX.Element {
|
||||
<LandingHeader />
|
||||
<VStack css={{ background: '#FEFCF5', color: '#3D3D3D' }}>
|
||||
<VStack css={mobileContainerStyles}>
|
||||
<Box css={headingStyles}>Omnivore is the read-it-later app for serious readers.</Box>
|
||||
<Box css={subHeadingStyles}>
|
||||
Distraction free. Privacy focused. Open source.
|
||||
<Box css={headingStyles}>
|
||||
Omnivore is the read-it-later app for serious readers.
|
||||
</Box>
|
||||
|
||||
<Box css={subHeadingStyles}>
|
||||
Save interesting articles, newsletter subscriptions, and documents and
|
||||
read them later — focused and distraction free. Add notes and highlights.
|
||||
Organize your reading list the way you want and sync it across all your
|
||||
devices.
|
||||
Distraction free. Privacy focused. Open source.
|
||||
</Box>
|
||||
<Box css={{ mb: 40, padding: '10px' }}>
|
||||
|
||||
<Box
|
||||
css={{
|
||||
color: 'rgb(125, 125, 125)',
|
||||
padding: '10px',
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
Save interesting articles, newsletter subscriptions, and documents
|
||||
and read them later — focused and distraction free. Add notes and
|
||||
highlights. Organize your reading list the way you want and sync it
|
||||
across all your devices.
|
||||
</Box>
|
||||
<Box
|
||||
css={{
|
||||
mb: 40,
|
||||
padding: '10px',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<GetStartedButton />
|
||||
</Box>
|
||||
</VStack>
|
||||
@ -59,5 +80,3 @@ export default function LandingPage(): JSX.Element {
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
BIN
packages/web/public/static/landing/landingPage-1.png
Normal file
|
After Width: | Height: | Size: 328 KiB |
BIN
packages/web/public/static/landing/landingPage-2.png
Normal file
|
After Width: | Height: | Size: 161 KiB |
BIN
packages/web/public/static/landing/landingPage-3.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
packages/web/public/static/landing/landingPage-4.png
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
packages/web/public/static/landing/landingPage-5.png
Normal file
|
After Width: | Height: | Size: 213 KiB |
BIN
packages/web/public/static/landing/landingPage-6.png
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
packages/web/public/static/landing/landingPage-7.png
Normal file
|
After Width: | Height: | Size: 204 KiB |