diff --git a/packages/web/components/elements/AndroidInstallHelp.tsx b/packages/web/components/elements/AndroidInstallHelp.tsx new file mode 100644 index 000000000..f8acd5ece --- /dev/null +++ b/packages/web/components/elements/AndroidInstallHelp.tsx @@ -0,0 +1,198 @@ +import React from 'react' +import { + Desktop, + DeviceTabletSpeaker, + DeviceMobileCamera, +} from 'phosphor-react' +import { Box, HStack } from './LayoutPrimitives' +import { StyledText, StyledAnchor } from './StyledText' + +type MobileInstallHelpProps = { + onboarding?: boolean +} + +export default function AndroidInstallHelp({ + onboarding = false, +}: MobileInstallHelpProps): JSX.Element { + const iosContainerStyles = { + marginTop: '12px', + width: '100%', + height: '40px', + display: 'flex', + justifyContent: !onboarding ? 'flex-end' : 'initial', + } + + return ( + + + + + + + + + Install Omnivore for Android + + + + Use our native Android app (currently a preview release), to save any + link, access your full library, and read offline. +
+
+ + + + Get it on Google Play + + + + +
+ ) +} diff --git a/packages/web/components/elements/Button.tsx b/packages/web/components/elements/Button.tsx index cb88f527d..d682ea3fd 100644 --- a/packages/web/components/elements/Button.tsx +++ b/packages/web/components/elements/Button.tsx @@ -18,6 +18,22 @@ export const Button = styled('button', { border: '1px solid $grayBorderHover', }, }, + ctaOmnivoreYellow: { + borderRadius: '5px', + px: '20px', + py: '8px', + fontSize: '14px', + fontWeight: '500', + cursor: 'pointer', + border: '0px solid $yellow3', + bg: '$omnivoreYellow', + color: '#2A2A2A', + '&:hover': { + opacity: 1.0, + border: '0px solid #FFD800', + background: `#FFD800`, + }, + }, ctaBlue: { borderRadius: '5px', px: '20px', @@ -25,12 +41,12 @@ export const Button = styled('button', { fontSize: '14px', fontWeight: '500', cursor: 'pointer', - border: '1px solid $yellow3', + border: '0px solid $yellow3', bg: '$ctaBlue', color: 'white', '&:hover': { - opacity: '0.6', - border: '0px solid $ctaBlue', + border: '0px solid #0056D2', + background: `#0056D2`, }, }, tldr: { @@ -69,6 +85,38 @@ export const Button = styled('button', { outline: '1px solid $omnivoreCtaYellow', }, }, + landingCta: { + borderRadius: 10, + backgroundColor: '#1A1A1A', + padding: '12px 100px', + color: '#FFFFFF', + font: '$inter', + fontSize: '20px', + fontWeight: '500', + textDecoration: 'none', + transition: 'background-color ease-out 50ms', + boxShadow: `0px 4px 4px 0px rgba(0, 0, 0, 0.15)`, + '&:hover': { + backgroundColor: '#3D3D3D', + outline: '0px solid #1A1A1A', + }, + }, + landingSimple: { + borderRadius: 10, + backgroundColor: '#1A1A1A', + padding: '10px 20px', + color: '#FFFFFF', + font: '$inter', + fontSize: '20px', + fontWeight: '500', + textDecoration: 'none', + transition: 'background-color ease-out 50ms', + '&:hover': { + backgroundColor: '#1A1A1A', + outline: '0px solid #1A1A1A', + boxShadow: `0px 4px 4px 0px rgba(0, 0, 0, 0.15)`, + }, + }, cancelGeneric: { fontSize: '13px', fontWeight: 500, @@ -84,6 +132,21 @@ export const Button = styled('button', { outline: '1px solid $omnivoreCtaYellow', }, }, + cancelAuth: { + fontSize: '13px', + fontWeight: 500, + fontFamily: 'Inter', + cursor: 'pointer', + color: '#6A6968', + borderRadius: '5px', + border: '1px solid transparent', + p: '10px 15px', + bg: 'transparent', + '&:hover': { + backgroundColor: '#2A2A2A', + outline: '0px solid #2A2A2A', + }, + }, ctaOutlineYellow: { boxSizing: 'border-box', borderColor: 'unset', diff --git a/packages/web/components/elements/MobileInstallHelp.tsx b/packages/web/components/elements/IOSInstallHelp.tsx similarity index 66% rename from packages/web/components/elements/MobileInstallHelp.tsx rename to packages/web/components/elements/IOSInstallHelp.tsx index 1aa9736ac..5eb96fc36 100644 --- a/packages/web/components/elements/MobileInstallHelp.tsx +++ b/packages/web/components/elements/IOSInstallHelp.tsx @@ -4,38 +4,16 @@ import { DeviceTabletSpeaker, DeviceMobileCamera, } from 'phosphor-react' -import { Box, HStack } from '../elements/LayoutPrimitives' -import { StyledText, StyledAnchor } from '../elements/StyledText' - -const TooltipStyle = { - backgroundColor: '#F9D354', - color: '#0A0806', -} +import { Box, HStack } from './LayoutPrimitives' +import { StyledText, StyledAnchor } from './StyledText' type MobileInstallHelpProps = { onboarding?: boolean } -export default function MobileInstallHelp({ +export default function IOSInstallHelp({ onboarding = false, }: MobileInstallHelpProps): JSX.Element { - const [selectedTooltip, setSelectedTooltip] = - React.useState('Available for Mac') - const platformSizes = [ - { - label: 'Available for Mac', - icon: , - }, - { - label: 'Available for iPad', - icon: , - }, - { - label: 'Available for iPhone', - icon: , - }, - ] - const iosContainerStyles = { marginTop: '12px', width: '100%', @@ -143,24 +121,9 @@ export default function MobileInstallHelp({ }, }} > - With the Omnivore for iOS and macOS app installed you can save any link - using our Share extension. -
- {!onboarding && ( - - Learn more about the iOS and macOS app -> - - )} + With the native Omnivore for iOS and macOS app installed you can save + any link, read offline, and listen to your saved items using + text-to-speech. - {platformSizes.map((item, idx) => ( - - setSelectedTooltip(item.label)} - css={{ - mx: 'auto', - borderRadius: '50%', - display: 'inline-flex', - alignItems: 'center', - justifyContent: 'center', - height: 35, - width: 35, - cursor: 'pointer', - backgroundColor: '$labelButtonsBg', - ...(selectedTooltip !== item.label && { - filter: 'grayscale(1)', - }), - '&:focus': { - filter: 'grayscale(0)', - }, - '&:active': { - filter: 'grayscale(0)', - }, - '@lg': { - transition: 'filter .3s linear', - '&:hover': { - filter: 'grayscale(0)', - }, - }, - }} - > - {item.icon} - - - ))} - + > ) diff --git a/packages/web/components/elements/Recaptcha.tsx b/packages/web/components/elements/Recaptcha.tsx index 193ada581..1f071410d 100644 --- a/packages/web/components/elements/Recaptcha.tsx +++ b/packages/web/components/elements/Recaptcha.tsx @@ -9,6 +9,7 @@ export const Recaptcha = (props: RecaptchaProps): JSX.Element => { <> { console.log('recaptcha: ', token) props.setRecaptchaToken(token) diff --git a/packages/web/components/elements/SplitButton.tsx b/packages/web/components/elements/SplitButton.tsx index fca43c9d5..74253c606 100644 --- a/packages/web/components/elements/SplitButton.tsx +++ b/packages/web/components/elements/SplitButton.tsx @@ -45,9 +45,8 @@ export const SplitButton = (props: SplitButtonProps): JSX.Element => { - @@ -151,7 +156,7 @@ export function EmailLogin(): JSX.Element { > Don't have an account?{' '} - + Sign up @@ -169,7 +174,10 @@ export function EmailLogin(): JSX.Element { > Forgot your password?{' '} - + Click here diff --git a/packages/web/components/templates/auth/EmailSignup.tsx b/packages/web/components/templates/auth/EmailSignup.tsx index 92a4527c6..678a41054 100644 --- a/packages/web/components/templates/auth/EmailSignup.tsx +++ b/packages/web/components/templates/auth/EmailSignup.tsx @@ -39,7 +39,9 @@ const SignUpForm = (): JSX.Element => { return ( - Email + + Email + { name="email" defaultValue={email} placeholder="Email" - css={{ backgroundColor: 'white', color: 'black' }} + css={{ backgroundColor: '#2A2A2A', color: 'white', border: 'unset' }} onChange={(e) => { e.preventDefault() setEmail(e.target.value) @@ -56,40 +58,46 @@ const SignUpForm = (): JSX.Element => { /> - Password + + Password + setPassword(e.target.value)} required /> - Full Name + + Full Name + setFullname(e.target.value)} required /> - Username + + Username + @@ -145,16 +153,16 @@ export function EmailSignup(): JSX.Element { alignment="center" css={{ padding: '16px', - background: 'white', minWidth: '340px', width: '70vw', maxWidth: '576px', borderRadius: '8px', - border: '1px solid #3D3D3D', - boxShadow: '#B1B1B1 9px 9px 9px -9px', + background: '#343434', + border: '1px solid #6A6968', + boxShadow: '0px 4px 4px 0px rgba(0, 0, 0, 0.15)', }} > - + Sign Up @@ -204,11 +212,7 @@ export function EmailSignup(): JSX.Element { }} > - @@ -238,10 +248,7 @@ export function EmailSignup(): JSX.Element { > Already have an account?{' '} - + Login instead diff --git a/packages/web/components/templates/auth/ResetSent.tsx b/packages/web/components/templates/auth/ResetSent.tsx index 3f0f2776a..77ce76845 100644 --- a/packages/web/components/templates/auth/ResetSent.tsx +++ b/packages/web/components/templates/auth/ResetSent.tsx @@ -9,7 +9,8 @@ export function ResetSent(): JSX.Element { css={{ width: '100vw', height: '100vh', - bg: '$omnivoreYellow', + color: '#898989', + background: '#2A2A2A', overflowY: 'clip', }} > @@ -17,11 +18,11 @@ export function ResetSent(): JSX.Element { css={{ width: '100%', margin: '40px', - color: '$omnivoreGray', + color: '#898989', '@xl': { margin: '138px' }, }} > -

Reset email sent

+

Reset email sent

If there is an account associated with the email specified we sent a password reset link. Click the link to reset your password. You may diff --git a/packages/web/components/templates/auth/VerifyEmail.tsx b/packages/web/components/templates/auth/VerifyEmail.tsx index 7eedf9b60..32b5a2441 100644 --- a/packages/web/components/templates/auth/VerifyEmail.tsx +++ b/packages/web/components/templates/auth/VerifyEmail.tsx @@ -9,7 +9,8 @@ export function VerifyEmail(): JSX.Element { css={{ width: '100vw', height: '100vh', - bg: '$omnivoreYellow', + color: '#898989', + background: '#2A2A2A', overflowY: 'clip', }} > @@ -17,12 +18,11 @@ export function VerifyEmail(): JSX.Element { css={{ width: '100%', margin: '40px', - color: '$omnivoreGray', '@xl': { margin: '138px' }, }} > -

Verify your email address

- +

Verify your email address

+ We sent a verification link to the email you provided. Click the link to verify your email. You may need to check your spam folder. diff --git a/packages/web/components/templates/homeFeed/AddLinkModal.tsx b/packages/web/components/templates/homeFeed/AddLinkModal.tsx index 8abf6fec4..a4a6b0dce 100644 --- a/packages/web/components/templates/homeFeed/AddLinkModal.tsx +++ b/packages/web/components/templates/homeFeed/AddLinkModal.tsx @@ -240,9 +240,12 @@ const AddFromURL = (props: AddFromURLProps): JSX.Element => { )} diff --git a/packages/web/components/templates/landing/LandingHeader.tsx b/packages/web/components/templates/landing/LandingHeader.tsx index 5f91bf821..019186847 100644 --- a/packages/web/components/templates/landing/LandingHeader.tsx +++ b/packages/web/components/templates/landing/LandingHeader.tsx @@ -8,22 +8,8 @@ const LoginButton = (): JSX.Element => { @@ -48,7 +34,7 @@ export function LandingHeader(): JSX.Element { width: '100%', }} > - +
) diff --git a/packages/web/components/templates/landing/LandingSection.tsx b/packages/web/components/templates/landing/LandingSection.tsx index b8595b7f1..dd15fef6b 100644 --- a/packages/web/components/templates/landing/LandingSection.tsx +++ b/packages/web/components/templates/landing/LandingSection.tsx @@ -14,7 +14,8 @@ export function LandingSection(props: LandingSectionProps): JSX.Element { css={{ width: '100%', flexWrap: 'wrap', - flexDirection: (props?.imagePosition ?? 'left') === 'left' ? 'row-reverse' : 'row', + flexDirection: + (props?.imagePosition ?? 'left') === 'left' ? 'row-reverse' : 'row', marginBottom: 20, '@mdDown': { width: '100%', @@ -40,7 +41,7 @@ export function LandingSection(props: LandingSectionProps): JSX.Element { as="h2" css={{ fontWeight: '700', - color: '#3D3D3D', + color: '#FFFFFF', lineHeight: 1.25, '@mdDown': { fontSize: 24, @@ -58,7 +59,7 @@ export function LandingSection(props: LandingSectionProps): JSX.Element { {props.descriptionText} diff --git a/packages/web/components/templates/landing/LandingSectionsContainer.tsx b/packages/web/components/templates/landing/LandingSectionsContainer.tsx index a4ccf9399..5c46b4c7f 100644 --- a/packages/web/components/templates/landing/LandingSectionsContainer.tsx +++ b/packages/web/components/templates/landing/LandingSectionsContainer.tsx @@ -15,23 +15,7 @@ import Link from 'next/link' export function GetStartedButton(props: { lang: 'en' | 'zh' }): JSX.Element { return ( - ) @@ -43,8 +27,6 @@ const containerStyles = { pb: 100, width: '100%', maxWidth: '1224px', - 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, }, @@ -64,7 +46,7 @@ const sections = [ { en: { titleText: `Save it now. Read it later.`, - descriptionText: `Save articles, PDFs, and Twitter threads as you come across them + descriptionText: `Save articles and PDFs as you come across them using Omnivore's mobile apps and browser extensions. Read them later using our distraction free reader.`, }, @@ -77,7 +59,7 @@ const sections = [ }, { en: { - titleText: `Get all your newsletters in one place.`, + titleText: `Get all your RSS feeds and newsletters in one place.`, descriptionText: `Send newsletters directly to your Omnivore library rather than scattered across multiple inboxes. Read them on your own time, away from the constant distractions and interruptions of your email.`, @@ -93,7 +75,7 @@ const sections = [ en: { titleText: `Keep your reading organized, whatever that means to you.`, descriptionText: `Keep your reading organized and easily available with labels, - filters, rules, and fully indexed text searches. We're not here + filters, rules, and ful text searches. We're not here to tell you how to stay organized — our job is to give you the tools to build a system that works for you.`, }, @@ -107,8 +89,7 @@ const sections = [ { en: { titleText: `Add highlights and notes.`, - descriptionText: `Become a better reader — engage your brain and improve retention by - reading actively, not passively. Highlight key sections and add + descriptionText: `Highlight key sections and add notes as you read. You can access your highlights and notes any time — they stay with your articles forever.`, }, @@ -123,7 +104,7 @@ const sections = [ en: { titleText: `Sync with your second brain.`, descriptionText: `Omnivore syncs with popular Personal Knowledge Management systems - including Logseq and Obsidian, so you can pull all your saved + including Logseq, Obsidian, and Notion, so you can pull all your saved reading, highlights, and notes into your second brain.`, }, zh: { @@ -137,7 +118,7 @@ const sections = [ en: { titleText: `Listen to your reading with text-to-speech.`, descriptionText: `Work through your to-be-read list and give your eyes a break with - TTS, exclusively in the Omnivore app for iOS. Realistic, + text-to-speech, exclusively in the Omnivore app for iOS. Realistic, natural-sounding AI voices will read any saved article aloud.`, }, zh: { @@ -209,41 +190,6 @@ export function LandingSectionsContainer( /> ) })} - - - {props.lang == 'en' && ( - - Get Started With Omnivore Today - - )} - -
) } diff --git a/packages/web/components/templates/navMenu/Footer.tsx b/packages/web/components/templates/navMenu/Footer.tsx index f8b0a9804..d44bae039 100644 --- a/packages/web/components/templates/navMenu/Footer.tsx +++ b/packages/web/components/templates/navMenu/Footer.tsx @@ -16,7 +16,6 @@ export const NavMenuFooter = (props: NavMenuFooterProps): JSX.Element => { position: 'fixed', bottom: '0%', alignItems: 'center', - backgroundColor: '$thBackground2', width: LIBRARY_LEFT_MENU_WIDTH, overflowY: 'auto', diff --git a/packages/web/components/templates/navMenu/LibraryMenu.tsx b/packages/web/components/templates/navMenu/LibraryMenu.tsx index a2c5cbb05..e39923bca 100644 --- a/packages/web/components/templates/navMenu/LibraryMenu.tsx +++ b/packages/web/components/templates/navMenu/LibraryMenu.tsx @@ -1,4 +1,4 @@ -import { ReactNode, useEffect, useMemo, useRef, useState } from "react" +import { ReactNode, useEffect, useMemo, useRef, useState } from 'react' import { StyledText } from '../../elements/StyledText' import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives' import { Button } from '../../elements/Button' @@ -30,8 +30,8 @@ import { OutlinedLabelChip } from '../../elements/OutlinedLabelChip' import { NewsletterIcon } from '../../elements/icons/NewsletterIcon' import { Dropdown, DropdownOption } from '../../elements/DropdownElements' import { useRouter } from 'next/router' -import { DiscoverIcon } from "../../elements/icons/DiscoverIcon" -import { escapeQuotes } from "../../../utils/helper" +import { DiscoverIcon } from '../../elements/icons/DiscoverIcon' +import { escapeQuotes } from '../../../utils/helper' export const LIBRARY_LEFT_MENU_WIDTH = '275px' @@ -158,9 +158,6 @@ export function LibraryFilterMenu(props: LibraryFilterMenuProps): JSX.Element { - {/* - - */} diff --git a/packages/web/components/tokens/stitches.config.ts b/packages/web/components/tokens/stitches.config.ts index 27c95d158..db11183dc 100644 --- a/packages/web/components/tokens/stitches.config.ts +++ b/packages/web/components/tokens/stitches.config.ts @@ -145,7 +145,7 @@ export const { styled, css, theme, getCssText, globalCss, keyframes, config } = // Brand Colors omnivoreRed: '#FA5E4A;', omnivoreGray: '#3D3D3D', - omnivoreYellow: 'rgb(255, 234, 159)', + omnivoreYellow: '#FFEAA0', omnivoreLightGray: 'rgb(125, 125, 125)', omnivoreCtaYellow: 'rgb(255, 210, 52)', searchActiveOutline: 'rgb(255, 210, 52)', diff --git a/packages/web/lib/networking/networkHelpers.ts b/packages/web/lib/networking/networkHelpers.ts index 4e0c02e98..b70bd0015 100644 --- a/packages/web/lib/networking/networkHelpers.ts +++ b/packages/web/lib/networking/networkHelpers.ts @@ -12,24 +12,21 @@ export type RequestContext = { } } -type RequestHeaders = { - authorization?: string - pendingUserAuth?: string -} - -function requestHeaders(): RequestHeaders { +function requestHeaders(): Record { const authToken = window?.localStorage.getItem('authToken') || undefined const pendingAuthToken = window?.localStorage.getItem('pendingUserAuth') || undefined if (authToken) { return { + 'X-OmnivoreClient': 'web', authorization: authToken, } } if (pendingAuthToken) { return { + 'X-OmnivoreClient': 'web', pendingUserAuth: pendingAuthToken, } } diff --git a/packages/web/pages/login.tsx b/packages/web/pages/login.tsx index 955cb49ac..78c957f86 100644 --- a/packages/web/pages/login.tsx +++ b/packages/web/pages/login.tsx @@ -1,5 +1,4 @@ import { useRouter } from 'next/router' -import Script from 'next/script' import { useState, useEffect } from 'react' import { LoginLayout } from './../components/templates/LoginLayout' import { parseErrorCodes } from '../lib/queryParamParser' @@ -8,8 +7,9 @@ import { formatMessage } from '../locales/en/messages' export default function Login(): JSX.Element { const router = useRouter() - const [errorMessage, setErrorMessage] = - useState(undefined) + const [errorMessage, setErrorMessage] = useState( + undefined + ) useEffect(() => { if (!router.isReady) return @@ -30,10 +30,6 @@ export default function Login(): JSX.Element { return ( <> -