mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Improve the help box
This commit is contained in:
parent
a329ae4cd3
commit
45b990b77d
12 changed files with 247 additions and 53 deletions
|
|
@ -20,7 +20,7 @@ export const Button = styled('button', {
|
|||
},
|
||||
ctaDarkYellow: {
|
||||
border: '1px solid transparent',
|
||||
fontSize: '13px',
|
||||
fontSize: '14px',
|
||||
fontWeight: 500,
|
||||
fontFamily: 'Inter',
|
||||
borderRadius: '5px',
|
||||
|
|
@ -77,8 +77,8 @@ export const Button = styled('button', {
|
|||
fontFamily: 'Inter',
|
||||
borderRadius: '8px',
|
||||
cursor: 'pointer',
|
||||
color: 'white',
|
||||
p: '10px 12px',
|
||||
color: '$thTextContrast2',
|
||||
bg: 'rgb(125, 125, 125, 0.3)',
|
||||
'&:hover': {
|
||||
bg: 'rgb(47, 47, 47, 0.1)',
|
||||
|
|
|
|||
118
packages/web/components/elements/FeatureHelpBox.tsx
Normal file
118
packages/web/components/elements/FeatureHelpBox.tsx
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
import { HStack, SpanBox, VStack } from './LayoutPrimitives'
|
||||
import { ArrowRightIcon } from './icons/ArrowRightIcon'
|
||||
import { theme } from '../tokens/stitches.config'
|
||||
import { Button } from './Button'
|
||||
import { CloseIcon } from './icons/CloseIcon'
|
||||
import { HelpfulOwlImage } from './images/HelpfulOwlImage'
|
||||
import { ArrowSquareOut } from 'phosphor-react'
|
||||
|
||||
type FeatureHelpBoxProps = {
|
||||
helpTitle: string
|
||||
helpMessage: string
|
||||
|
||||
helpCTAText?: string
|
||||
onClickCTA?: () => void
|
||||
|
||||
docsMessage: string
|
||||
docsDestination: string
|
||||
|
||||
onDismiss: () => void
|
||||
}
|
||||
|
||||
export const FeatureHelpBox = (props: FeatureHelpBoxProps) => {
|
||||
return (
|
||||
<HStack
|
||||
css={{
|
||||
gap: '10px',
|
||||
my: '40px',
|
||||
display: 'flex',
|
||||
width: 'fit-content',
|
||||
borderRadius: '5px',
|
||||
background: '$thBackground5',
|
||||
fontSize: '15px',
|
||||
fontFamily: '$inter',
|
||||
fontWeight: '500',
|
||||
color: '$grayText',
|
||||
px: '20px',
|
||||
py: '20px',
|
||||
justifyContent: 'flex-start',
|
||||
'@smDown': {
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
width: '100%',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<HStack css={{ gap: '30px' }}>
|
||||
<SpanBox css={{ pt: '7px', alignSelf: 'center' }}>
|
||||
<HelpfulOwlImage width={254} height={333} />
|
||||
</SpanBox>
|
||||
<HelpSection {...props} />
|
||||
</HStack>
|
||||
</HStack>
|
||||
)
|
||||
}
|
||||
|
||||
const HelpSection = (props: FeatureHelpBoxProps) => {
|
||||
return (
|
||||
<VStack css={{ gap: '20px' }}>
|
||||
<HStack css={{ width: '100%', gap: '20px' }} distribution="between">
|
||||
<SpanBox
|
||||
css={{
|
||||
fontSize: '22px',
|
||||
fontFamily: '$display',
|
||||
color: '$thTextContrast2',
|
||||
}}
|
||||
>
|
||||
{props.helpTitle}
|
||||
</SpanBox>
|
||||
<Button
|
||||
style="plainIcon"
|
||||
title="Hide this tip"
|
||||
css={{ pt: '7px' }}
|
||||
onClick={(event) => {
|
||||
props.onDismiss()
|
||||
event.preventDefault()
|
||||
}}
|
||||
>
|
||||
<CloseIcon
|
||||
size={25}
|
||||
color={theme.colors.thTextContrast2.toString()}
|
||||
/>
|
||||
</Button>
|
||||
</HStack>
|
||||
<SpanBox>{props.helpMessage}</SpanBox>
|
||||
<HStack css={{ gap: '20px' }}>
|
||||
{props.helpCTAText && props.onClickCTA && (
|
||||
<Button
|
||||
style="ctaDarkYellow"
|
||||
onClick={(event) => {
|
||||
if (props.onClickCTA) {
|
||||
props.onClickCTA()
|
||||
event.preventDefault()
|
||||
}
|
||||
}}
|
||||
>
|
||||
{props.helpCTAText}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
style="ctaLightGray"
|
||||
onClick={(event) => {
|
||||
window.open(props.docsDestination, '_blank', 'noreferrer')
|
||||
event.preventDefault()
|
||||
}}
|
||||
css={{ display: 'flex', flexDirection: 'row', gap: '10px' }}
|
||||
>
|
||||
{props.docsMessage}
|
||||
<SpanBox css={{ alignSelf: 'center' }}>
|
||||
<ArrowSquareOut
|
||||
size={12}
|
||||
color={theme.colors.thTextContrast2.toString()}
|
||||
/>
|
||||
</SpanBox>
|
||||
</Button>
|
||||
</HStack>
|
||||
</VStack>
|
||||
)
|
||||
}
|
||||
|
|
@ -85,7 +85,7 @@ export const SuggestionBox = (props: SuggestionBoxProps) => {
|
|||
fontWeight: '600',
|
||||
}}
|
||||
>
|
||||
<CloseIcon size={25} color="white" />
|
||||
<CloseIcon size={2} color="white" />
|
||||
</Button>
|
||||
</SpanBox>
|
||||
)}
|
||||
|
|
|
|||
39
packages/web/components/elements/icons/CloseIcon.tsx
Normal file
39
packages/web/components/elements/icons/CloseIcon.tsx
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* eslint-disable functional/no-class */
|
||||
/* eslint-disable functional/no-this-expression */
|
||||
import { IconProps } from './IconProps'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
export class CloseIcon extends React.Component<IconProps> {
|
||||
render() {
|
||||
const size = (this.props.size || 26).toString()
|
||||
const color = (this.props.color || '#2A2A2A').toString()
|
||||
|
||||
return (
|
||||
<svg
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox={`0 0 26 26`}
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g>
|
||||
<path
|
||||
d="M10.7441 10.9399L14.9108 15.1066M14.9108 10.9399L10.7441 15.1066"
|
||||
stroke={color}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M12.8281 3.64844C20.3281 3.64844 22.2031 5.52344 22.2031 13.0234C22.2031 20.5234 20.3281 22.3984 12.8281 22.3984C5.32813 22.3984 3.45312 20.5234 3.45312 13.0234C3.45312 5.52344 5.32813 3.64844 12.8281 3.64844Z"
|
||||
stroke={color}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
}
|
||||
17
packages/web/components/elements/images/HelpfulOwlImage.tsx
Normal file
17
packages/web/components/elements/images/HelpfulOwlImage.tsx
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import Image from 'next/image'
|
||||
|
||||
type HelpfulOwlImageProps = {
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
export const HelpfulOwlImage = (props: HelpfulOwlImageProps) => {
|
||||
return (
|
||||
<Image
|
||||
src="/static/images/helpful-owl@2x.png"
|
||||
width={200}
|
||||
height={200}
|
||||
alt="Picture of an owl reading"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import { theme } from '../../tokens/stitches.config'
|
|||
import { SettingsLayout } from '../SettingsLayout'
|
||||
import { SuggestionBox } from '../../elements/SuggestionBox'
|
||||
import { usePersistedState } from '../../../lib/hooks/usePersistedState'
|
||||
import { FeatureHelpBox } from '../../elements/FeatureHelpBox'
|
||||
|
||||
type SettingsTableProps = {
|
||||
pageId: string
|
||||
|
|
@ -57,9 +58,13 @@ type MoreOptionsProps = {
|
|||
}
|
||||
|
||||
type SuggestionInfo = {
|
||||
text: string
|
||||
title: string
|
||||
message: string
|
||||
docs: string
|
||||
key: string
|
||||
|
||||
CTAText?: string
|
||||
onClickCTA?: () => void
|
||||
}
|
||||
|
||||
const MoreOptions = (props: MoreOptionsProps) => (
|
||||
|
|
@ -315,19 +320,17 @@ export const SettingsTable = (props: SettingsTableProps): JSX.Element => {
|
|||
}}
|
||||
>
|
||||
{props.suggestionInfo && showSuggestion && (
|
||||
<Box css={{ my: '40px', width: '100%' }}>
|
||||
<SuggestionBox
|
||||
helpMessage={props.suggestionInfo.text}
|
||||
helpCTAText={'Read the Docs'}
|
||||
helpTarget={props.suggestionInfo.docs}
|
||||
size={'large'}
|
||||
background="$thBackground5"
|
||||
dismissible={true}
|
||||
onDismiss={() => {
|
||||
setShowSuggestion(false)
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<FeatureHelpBox
|
||||
helpTitle={props.suggestionInfo.title}
|
||||
helpMessage={props.suggestionInfo.message}
|
||||
docsMessage={'Read the Docs'}
|
||||
docsDestination={props.suggestionInfo.docs}
|
||||
onDismiss={() => {
|
||||
setShowSuggestion(false)
|
||||
}}
|
||||
helpCTAText={props.suggestionInfo.CTAText}
|
||||
onClickCTA={props.suggestionInfo.onClickCTA}
|
||||
/>
|
||||
)}
|
||||
<Box
|
||||
css={{
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ export default function Api(): JSX.Element {
|
|||
pageId="api-keys"
|
||||
pageInfoLink="https://docs.omnivore.app/integrations/api.html"
|
||||
headerTitle="API Keys"
|
||||
createTitle="Generate API Key"
|
||||
createTitle="Create an API Key"
|
||||
createAction={() => {
|
||||
onAdd()
|
||||
setName('')
|
||||
|
|
@ -122,9 +122,19 @@ export default function Api(): JSX.Element {
|
|||
setAddModalOpen(true)
|
||||
}}
|
||||
suggestionInfo={{
|
||||
text: 'Create API keys to connect Omnivore to other apps such as Logseq and Obsidian or to query the API. Check out the integrations page for more info on connecting to Omnivore via the API.',
|
||||
title:
|
||||
'Use API keys to Integrate Omnivore with other apps and services',
|
||||
message:
|
||||
'Create API keys to connect Omnivore to other apps such as Logseq and Obsidian or to query the API. Check out the integrations page for more info on connecting to Omnivore via the API.',
|
||||
docs: 'https://docs.omnivore.app/integrations/api.html',
|
||||
key: '--settings-apikeys-show-help',
|
||||
CTAText: 'Create an API Key',
|
||||
onClickCTA: () => {
|
||||
onAdd()
|
||||
setName('')
|
||||
setExpiresAt(neverExpiresDate)
|
||||
setAddModalOpen(true)
|
||||
},
|
||||
}}
|
||||
>
|
||||
{sortedApiKeys.length > 0 ? (
|
||||
|
|
@ -168,7 +178,7 @@ export default function Api(): JSX.Element {
|
|||
|
||||
{addModalOpen && (
|
||||
<FormModal
|
||||
title={'Generate API Key'}
|
||||
title={'Create an API Key'}
|
||||
onSubmit={onCreate}
|
||||
onOpenChange={setAddModalOpen}
|
||||
inputs={formInputs}
|
||||
|
|
|
|||
|
|
@ -123,9 +123,15 @@ export default function EmailsPage(): JSX.Element {
|
|||
createTitle="Create a new email address"
|
||||
createAction={createEmail}
|
||||
suggestionInfo={{
|
||||
text: 'Create an Omnivore email address and use it to subscribe to newsletters. The newsletters will be automatically added to your library.',
|
||||
title: 'Subscribe to newsletters with an Omnivore Email Address',
|
||||
message:
|
||||
'Create an Omnivore email address and use it to subscribe to newsletters or send yourself documents. Newsletters and documents will be categorized and added to your library when we receive a message. View all received emails with the "Recently Received Emails" link at the bottom of this page.',
|
||||
docs: 'https://docs.omnivore.app/using/inbox.html',
|
||||
key: '--settings-emails-show-help',
|
||||
CTAText: 'Create an email address',
|
||||
onClickCTA: () => {
|
||||
createEmail()
|
||||
},
|
||||
}}
|
||||
>
|
||||
{sortedEmailAddresses.length > 0 ? (
|
||||
|
|
|
|||
|
|
@ -172,7 +172,10 @@ export default function RecentEmails(): JSX.Element {
|
|||
pageInfoLink="https://docs.omnivore.app/using/inbox.html"
|
||||
headerTitle="Recently Received Emails"
|
||||
suggestionInfo={{
|
||||
text: 'View all the original content of emails that have been recently received in your Omnivore inbox. If an email was not correctly classified as an article you can mark it as an article.',
|
||||
title:
|
||||
'View original emails that have been recently received in your Omnivore inbox.',
|
||||
message:
|
||||
"Your 30 most recent emails are stored below. You can click on each email to view its original content or it's text content. If an email was not correctly classified as an article you can mark it as an article and it will be added to your library.",
|
||||
docs: 'https://docs.omnivore.app/using/inbox.html',
|
||||
key: '--settings-recent-emails-show-help',
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -92,14 +92,20 @@ export default function Rss(): JSX.Element {
|
|||
pageId={'feeds'}
|
||||
pageInfoLink="https://docs.omnivore.app/using/feeds.html"
|
||||
headerTitle="Subscribed feeds"
|
||||
createTitle="Add feed"
|
||||
createTitle="Add a feed"
|
||||
createAction={() => {
|
||||
router.push('/settings/feeds/add')
|
||||
}}
|
||||
suggestionInfo={{
|
||||
text: 'Add RSS and Atom feeds to your Omnivore account. When you add a new feed the last 24hrs of items, or at least one item will be added to your account.',
|
||||
title: 'Add RSS and Atom feeds to your Omnivore account',
|
||||
message:
|
||||
'When you add a new feed the last 24hrs of items, or at least one item will be added to your account. Feeds will be checked for updates every hour, and new items will be added to your library.',
|
||||
docs: 'https://docs.omnivore.app/using/feeds.html',
|
||||
key: '--settings-feeds-show-help',
|
||||
CTAText: 'Add a feed',
|
||||
onClickCTA: () => {
|
||||
router.push('/settings/feeds/add')
|
||||
},
|
||||
}}
|
||||
>
|
||||
{subscriptions.length === 0 ? (
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import { ConfirmationModal } from '../../components/patterns/ConfirmationModal'
|
|||
import { InfoLink } from '../../components/elements/InfoLink'
|
||||
import { SuggestionBox } from '../../components/elements/SuggestionBox'
|
||||
import { usePersistedState } from '../../lib/hooks/usePersistedState'
|
||||
import { FeatureHelpBox } from '../../components/elements/FeatureHelpBox'
|
||||
|
||||
const HeaderWrapper = styled(Box, {
|
||||
width: '100%',
|
||||
|
|
@ -277,19 +278,21 @@ export default function LabelsPage(): JSX.Element {
|
|||
/>
|
||||
) : null}
|
||||
{showLabelPageHelp && (
|
||||
<Box css={{ mt: '40px' }}>
|
||||
<SuggestionBox
|
||||
helpMessage="Use this page to view and edit all your labels. Labels can be attached to individual library items, or your highlights, and are used to keep your library organized."
|
||||
helpCTAText={'Read the Docs'}
|
||||
helpTarget="https://docs.omnivore.app/using/organizing.html"
|
||||
size={'large'}
|
||||
background="$thBackground5"
|
||||
dismissible={true}
|
||||
onDismiss={() => {
|
||||
setShowLabelPageHelp(false)
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<FeatureHelpBox
|
||||
helpTitle="Use labels to organize your library and optimize your workflow."
|
||||
helpMessage="Use this page to view and edit all your labels. Labels can be attached to individual library items, or your highlights, and are used to keep your library organized."
|
||||
docsMessage={'Read the Docs'}
|
||||
docsDestination="https://docs.omnivore.app/using/organizing.html#labels"
|
||||
onDismiss={() => {
|
||||
setShowLabelPageHelp(false)
|
||||
}}
|
||||
helpCTAText="Create a label"
|
||||
onClickCTA={() => {
|
||||
resetLabelState()
|
||||
handleGenerateRandomColor()
|
||||
setIsCreateMode(true)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<HeaderWrapper>
|
||||
<Box
|
||||
|
|
@ -326,24 +329,11 @@ export default function LabelsPage(): JSX.Element {
|
|||
>
|
||||
<SpanBox
|
||||
css={{
|
||||
display: 'none',
|
||||
'@md': {
|
||||
display: 'flex',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SpanBox>Add Label</SpanBox>
|
||||
</SpanBox>
|
||||
<SpanBox
|
||||
css={{
|
||||
p: '0',
|
||||
display: 'flex',
|
||||
'@md': {
|
||||
display: 'none',
|
||||
},
|
||||
'@md': {},
|
||||
}}
|
||||
>
|
||||
<Plus size={24} />
|
||||
<SpanBox>Create a label</SpanBox>
|
||||
</SpanBox>
|
||||
</Button>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,9 @@ export default function SubscriptionsPage(): JSX.Element {
|
|||
pageInfoLink="https://docs.omnivore.app/using/feeds.html"
|
||||
headerTitle="Subscriptions"
|
||||
suggestionInfo={{
|
||||
text: 'View and manage all your Feed and Newsletter subscriptions. You can add RSS or Atom subscriptions on the Feeds page and create emails to subscribe to newsletters',
|
||||
title: 'View and manage all your Feed and Newsletter subscriptions',
|
||||
message:
|
||||
'Use this page to view and manage all the Feeds (RSS & Atom) and Newsletters you have subscribed to.',
|
||||
docs: 'https://docs.omnivore.app/using/inbox.html',
|
||||
key: '--settings-recent-subscriptions-show-help',
|
||||
}}
|
||||
|
|
|
|||
Loading…
Reference in a new issue