diff --git a/packages/web/components/elements/DropdownElements.tsx b/packages/web/components/elements/DropdownElements.tsx index 7916b3bce..f3b4f5e04 100644 --- a/packages/web/components/elements/DropdownElements.tsx +++ b/packages/web/components/elements/DropdownElements.tsx @@ -9,7 +9,6 @@ import { Label, } from '@radix-ui/react-dropdown-menu' import { styled } from './../tokens/stitches.config' -import { Button } from './Button' const itemStyles = { fontSize: 13, @@ -46,10 +45,11 @@ const StyledTriggerItem = styled(TriggerItem, { const DropdownContent = styled(Content, { minWidth: 130, - backgroundColor: '$grayBase', + backgroundColor: '$grayBg', borderRadius: '0.5em', padding: 5, border: '1px solid $grayBorder', + boxShadow: '$cardBoxShadow', }) const StyledArrow = styled(Arrow, { @@ -63,17 +63,14 @@ const StyledLabel = styled(Label, { cursor: 'default', }) -export type DropdownAlignment = - | 'start' - | 'end' - | 'center' +export type DropdownAlignment = 'start' | 'end' | 'center' type DropdownProps = { labelText?: string + showArrow?: boolean triggerElement: React.ReactNode children: React.ReactNode - styledArrow?: boolean - align?: DropdownAlignment + align?: DropdownAlignment } export const DropdownSeparator = styled(Separator, { @@ -98,22 +95,26 @@ export function DropdownOption(props: DropdownOptionProps): JSX.Element { ) } -export function Dropdown(props: DropdownProps): JSX.Element { +export function Dropdown({ + children, + align, + triggerElement, + labelText, + showArrow = true, +}: DropdownProps): JSX.Element { return ( - - {props.triggerElement} - + {triggerElement} { + onInteractOutside={() => { // remove focus from dropdown ;(document.activeElement as HTMLElement).blur() }} - align={props.align ? props.align : 'center'} + align={align ? align : 'center'} > - {props.labelText && {props.labelText}} - {props.children} - {props.styledArrow && } + {labelText && {labelText}} + {children} + {showArrow && } ) diff --git a/packages/web/components/elements/ExtensionsInstallHelp.tsx b/packages/web/components/elements/ExtensionsInstallHelp.tsx index b88fd5e70..3fc1fbb6d 100644 --- a/packages/web/components/elements/ExtensionsInstallHelp.tsx +++ b/packages/web/components/elements/ExtensionsInstallHelp.tsx @@ -1,121 +1,289 @@ -import { useCallback, useState } from 'react' -import { SettingsLayout } from '../templates/SettingsLayout' -import { - Box, - VStack, - HStack, -} from './LayoutPrimitives' -import { StyledText } from './StyledText' -import { Button } from './Button' -import Router from 'next/router' -import { - Dropdown, - DropdownOption, -} from './DropdownElements' -import { ChromeIcon } from './images/ChromeIcon' -import { SafariIcon } from './images/SafariIcon' -import { FirefoxIcon } from './images/FirefoxIcon' -import { EdgeIcon } from './images/EdgeIcon' +import React from 'react' +import { Box, HStack } from '../elements/LayoutPrimitives' +import { StyledText, StyledAnchor } from '../elements/StyledText' import { AngleDownIcon } from '../tokens/icons/AngleDownIcon' -import { theme } from '../tokens/stitches.config' +import { Button } from './Button' +import { Dropdown, DropdownOption, DropdownSeparator } from './DropdownElements' +import { ChromeIcon } from './images/ChromeIcon' +import { EdgeIcon } from './images/EdgeIcon' +import { FirefoxIcon } from './images/FirefoxIcon' +import { SafariIcon } from './images/SafariIcon' +import Link from 'next/link' +import { SaveArticleIcon } from './images/SaveArticleIcon' -export default function ExtensionInstallHelp(): JSX.Element { - return ( - - - - ) +const icons = { + 'Google Chrome': , + 'Microsoft Edge': , + Firefox: , + Safari: , } const extensionDownloadLinks = { - chrome: 'https://omnivore.app/install/chrome', - safari: 'https://omnivore.app/install/mac', - edge: 'https://omnivore.app/install/edge', - firefox: 'https://omnivore.app/install/firefox', + 'Google Chrome': 'https://omnivore.app/install/chrome', + Safari: 'https://omnivore.app/install/mac', + 'Microsoft Edge': 'https://omnivore.app/install/edge', + Firefox: 'https://omnivore.app/install/firefox', } -export type Browser = 'chrome' | 'safari' | 'firefox' | 'edge' +const browserOptions = [ + 'Google Chrome', + 'Firefox', + 'Microsoft Edge', + 'Safari', +] as const -const browserInfo = (browser: Browser): { title: string, icon: JSX.Element } => { - const fillColor = theme.colors.grayText.toString() - switch (browser) { - case 'chrome': - return { title: 'Chrome', icon: } - case 'safari': - return { title: 'Safari', icon: } - case 'firefox': - return { title: 'FireFox', icon: } - case 'edge': - return { title: 'Edge', icon: } - } -} - -function ExtensionSelector(): JSX.Element { - const [browser, setBrowser] = useState('chrome') - - const selectBrowser = useCallback(() => { - window.location.href = extensionDownloadLinks[browser] - }, [browser]) +type browserType = typeof browserOptions[number] +const BrowserOption: React.FC<{ + browser: browserType +}> = ({ browser }) => { return ( - - Install Browser Extensions - - Installing the Omnivore browser extension is the best way to save pages to - Omnivore from your computer. Learn more about the browser extensions here. - - - Save articles - - - - - Download for a different browser}> - setBrowser('chrome')}> - - - setBrowser('safari')}> - - - setBrowser('firefox')}> - - - setBrowser('edge')} hideSeparator> - - - - - - - ) -} - -type BrowserOptionProps = { - browser: Browser -} - -function BrowserOption(props: BrowserOptionProps): JSX.Element { - const info = browserInfo(props.browser) - return ( - - {info.icon} - - {info.title} + {icons[browser as browserType]} + + {browser} ) } + +export default function ExtensionsInstallHelp(): JSX.Element { + const [browserValue, setBrowserValue] = React.useState( + browserOptions[0] + ) + + return ( + + + + + + + + + + Learn more + + + + Install Browser Extensions + + + + Installing the Omnivore browser extension is the best way to save pages + to Omnivore from your computer. +
+ + + Learn more about the browser extension here. + + +
+ + + + {icons[browserValue]} + + {browserValue} + + + + + + + } + > + {browserOptions.map((item, idx) => ( +
+ setBrowserValue(item)}> + + + {idx !== browserOptions.length - 1 && ( + + )} +
+ ))} + + + +
+ ) +} diff --git a/packages/web/components/elements/MobileInstallHelp.tsx b/packages/web/components/elements/MobileInstallHelp.tsx index 09c8b6ff0..b2c4b5bdf 100644 --- a/packages/web/components/elements/MobileInstallHelp.tsx +++ b/packages/web/components/elements/MobileInstallHelp.tsx @@ -1,25 +1,249 @@ -import { Box, VStack } from '../elements/LayoutPrimitives' -import { StyledText } from '../elements/StyledText' +import React from 'react' +import { + Desktop, + DeviceTabletSpeaker, + DeviceMobileCamera, +} from 'phosphor-react' +import { Box, HStack } from '../elements/LayoutPrimitives' +import { StyledText, StyledImg, StyledAnchor } from '../elements/StyledText' +import { TooltipWrapped } from './Tooltip' +import Link from 'next/link' +import { InstallationIcon } from './images/InstallationIcon' + +const TooltipStyle = { + backgroundColor: '#F9D354', + color: '#0A0806', +} export default function MobileInstallHelp(): 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: , + }, + ] return ( - - Install Omnivore for iOS - - With the Omnivore iOS app installed you can save any link using our share extension. - Learn more about the share extension here. + + + + + + + + + Learn more + + + + Install Omnivore for iOS + + + + With the Omnivore iOS app installed you can save any link using our + share extension. +
+ + + Learn more about the share extension here. + +
- - - Download on the App Store + + + + Download on the App Store - -
+ + + {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: '$tooltipIcons', + ...(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/StyledText.tsx b/packages/web/components/elements/StyledText.tsx index a36e41911..af008f21c 100644 --- a/packages/web/components/elements/StyledText.tsx +++ b/packages/web/components/elements/StyledText.tsx @@ -151,3 +151,10 @@ export const StyledList = styled('ul', { lineHeight: '1.35', color: '$grayTextContrast', }) + +export const StyledImg = styled('img', { +}) + +export const StyledAnchor = styled('a', { + textDecoration: 'none' +}) diff --git a/packages/web/components/elements/Tooltip.tsx b/packages/web/components/elements/Tooltip.tsx index 3af1b84c4..465c76a7c 100644 --- a/packages/web/components/elements/Tooltip.tsx +++ b/packages/web/components/elements/Tooltip.tsx @@ -1,26 +1,26 @@ -import React, { FC } from 'react'; -import { styled, keyframes } from '@stitches/react'; -import * as TooltipPrimitive from '@radix-ui/react-tooltip'; +import React, { FC } from 'react' +import { styled, keyframes } from '@stitches/react' +import * as TooltipPrimitive from '@radix-ui/react-tooltip' const slideUpAndFade = keyframes({ '0%': { opacity: 0, transform: 'translateY(2px)' }, '100%': { opacity: 1, transform: 'translateY(0)' }, -}); +}) const slideRightAndFade = keyframes({ '0%': { opacity: 0, transform: 'translateX(-2px)' }, '100%': { opacity: 1, transform: 'translateX(0)' }, -}); +}) const slideDownAndFade = keyframes({ '0%': { opacity: 0, transform: 'translateY(-2px)' }, '100%': { opacity: 1, transform: 'translateY(0)' }, -}); +}) const slideLeftAndFade = keyframes({ '0%': { opacity: 0, transform: 'translateX(2px)' }, '100%': { opacity: 1, transform: 'translateX(0)' }, -}); +}) const StyledContent = styled(TooltipPrimitive.Content, { borderRadius: 4, @@ -40,37 +40,41 @@ const StyledContent = styled(TooltipPrimitive.Content, { '&[data-side="left"]': { animationName: slideRightAndFade }, }, }, -}); +}) const StyledArrow = styled(TooltipPrimitive.Arrow, { fill: '#1C1C1E', -}); - -export const TooltipProvider = TooltipPrimitive.Provider; -export const Tooltip = TooltipPrimitive.Root; -export const TooltipTrigger = TooltipPrimitive.Trigger; -export const TooltipContent = StyledContent; -export const TooltipArrow = StyledArrow; +}) +export const TooltipProvider = TooltipPrimitive.Provider +export const Tooltip = TooltipPrimitive.Root +export const TooltipTrigger = TooltipPrimitive.Trigger +export const TooltipContent = StyledContent +export const TooltipArrow = StyledArrow type TooltipWrappedProps = { - tooltipContent: string, - tooltipSide ?: TooltipPrimitive.TooltipContentProps['side'], - align?: TooltipPrimitive.TooltipContentProps['align'], + tooltipContent: string; + active?: boolean; + tooltipSide?: TooltipPrimitive.TooltipContentProps['side'] + align?: TooltipPrimitive.TooltipContentProps['align'] alignOffset?: TooltipPrimitive.TooltipContentProps['alignOffset'] arrowStyles?: TooltipPrimitive.TooltipArrowProps['style'] style?: TooltipPrimitive.TooltipContentProps['style'] } -export const TooltipWrapped: FC = ({children, tooltipContent, tooltipSide, ...props}) => { +export const TooltipWrapped: FC = ({ + children, + active, + tooltipContent, + tooltipSide, + ...props +}) => { return ( - - - {children} - - + + {children} + {tooltipContent} - + ) diff --git a/packages/web/components/elements/images/ChromeIcon.tsx b/packages/web/components/elements/images/ChromeIcon.tsx index 09483304e..234c823b7 100644 --- a/packages/web/components/elements/images/ChromeIcon.tsx +++ b/packages/web/components/elements/images/ChromeIcon.tsx @@ -1,31 +1,35 @@ type ChromeIconProps = { - fillColor: string + fillColor?: string } export function ChromeIcon(props: ChromeIconProps): JSX.Element { return ( + ) diff --git a/packages/web/components/elements/images/EdgeIcon.tsx b/packages/web/components/elements/images/EdgeIcon.tsx index c00cfa691..991b73d2d 100644 --- a/packages/web/components/elements/images/EdgeIcon.tsx +++ b/packages/web/components/elements/images/EdgeIcon.tsx @@ -1,22 +1,127 @@ type EdgeIconProps = { - fillColor: string + fillColor?: string } export function EdgeIcon(props: EdgeIconProps): JSX.Element { return ( - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) } diff --git a/packages/web/components/elements/images/FirefoxIcon.tsx b/packages/web/components/elements/images/FirefoxIcon.tsx index 20abdd544..7453e0722 100644 --- a/packages/web/components/elements/images/FirefoxIcon.tsx +++ b/packages/web/components/elements/images/FirefoxIcon.tsx @@ -1,20 +1,232 @@ type FirefoxIconProps = { - fillColor: string + fillColor?: string } export function FirefoxIcon(props: FirefoxIconProps): JSX.Element { return ( - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) } diff --git a/packages/web/components/elements/images/InstallationIcon.tsx b/packages/web/components/elements/images/InstallationIcon.tsx new file mode 100644 index 000000000..26f9f24c1 --- /dev/null +++ b/packages/web/components/elements/images/InstallationIcon.tsx @@ -0,0 +1,461 @@ +type CrossIconProps = { + width?: number + height?: number + strokeColor?: string +} + +export function InstallationIcon({ + width = 151, + height = 130, +}: CrossIconProps): JSX.Element { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/packages/web/components/elements/images/SafariIcon.tsx b/packages/web/components/elements/images/SafariIcon.tsx index 8ce01df82..c40b04861 100644 --- a/packages/web/components/elements/images/SafariIcon.tsx +++ b/packages/web/components/elements/images/SafariIcon.tsx @@ -1,30 +1,50 @@ type SafariIconProps = { - fillColor: string + fillColor?: string } export function SafariIcon(props: SafariIconProps): JSX.Element { return ( - - - + + + + + + + + + + + ) } diff --git a/packages/web/components/elements/images/SaveArticleIcon.tsx b/packages/web/components/elements/images/SaveArticleIcon.tsx new file mode 100644 index 000000000..59e605d73 --- /dev/null +++ b/packages/web/components/elements/images/SaveArticleIcon.tsx @@ -0,0 +1,41 @@ +type CrossIconProps = { + width?: number + height?: number + strokeColor?: string +} + +export function SaveArticleIcon({ + width = 170, + height = 130, +}: CrossIconProps): JSX.Element { + return ( + + + + + + + + + + ) +} diff --git a/packages/web/components/patterns/DropdownMenu.tsx b/packages/web/components/patterns/DropdownMenu.tsx index ff5689b8d..ea879282e 100644 --- a/packages/web/components/patterns/DropdownMenu.tsx +++ b/packages/web/components/patterns/DropdownMenu.tsx @@ -41,7 +41,7 @@ export function DropdownMenu(props: DropdownMenuProps): JSX.Element { Theme