mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Improve settings layout
This commit is contained in:
parent
47277b63ee
commit
56d79580e2
4 changed files with 29 additions and 277 deletions
|
|
@ -1,243 +0,0 @@
|
|||
import { Box, HStack, SpanBox } from '../elements/LayoutPrimitives'
|
||||
import { OmnivoreNameLogo } from './../elements/images/OmnivoreNameLogo'
|
||||
import { DropdownMenu, HeaderDropdownAction } from './../patterns/DropdownMenu'
|
||||
import { updateTheme } from '../../lib/themeUpdater'
|
||||
import { AvatarDropdown } from './../elements/AvatarDropdown'
|
||||
import { ThemeId } from './../tokens/stitches.config'
|
||||
import { useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { UserBasicData } from '../../lib/networking/queries/useGetViewerQuery'
|
||||
|
||||
type HeaderProps = {
|
||||
user?: UserBasicData
|
||||
userInitials: string
|
||||
hideHeader?: boolean
|
||||
profileImageURL?: string
|
||||
isTransparent: boolean
|
||||
toolbarControl?: JSX.Element
|
||||
alwaysDisplayToolbar?: boolean
|
||||
setShowLogoutConfirmation: (showShareModal: boolean) => void
|
||||
setShowKeyboardCommandsModal: (showShareModal: boolean) => void
|
||||
}
|
||||
|
||||
export function PrimaryHeader(props: HeaderProps): JSX.Element {
|
||||
const router = useRouter()
|
||||
const [isScrolled, setIsScrolled] = useState(false)
|
||||
|
||||
function headerDropdownActionHandler(action: HeaderDropdownAction): void {
|
||||
switch (action) {
|
||||
case 'apply-darker-theme':
|
||||
updateTheme(ThemeId.Darker)
|
||||
break
|
||||
case 'apply-dark-theme':
|
||||
updateTheme(ThemeId.Dark)
|
||||
break
|
||||
case 'apply-lighter-theme':
|
||||
updateTheme(ThemeId.Lighter)
|
||||
break
|
||||
case 'apply-light-theme':
|
||||
updateTheme(ThemeId.Light)
|
||||
break
|
||||
case 'increaseFontSize':
|
||||
document.dispatchEvent(new Event('increaseFontSize'))
|
||||
break
|
||||
case 'decreaseFontSize':
|
||||
document.dispatchEvent(new Event('decreaseFontSize'))
|
||||
break
|
||||
case 'navigate-to-install':
|
||||
router.push('/settings/installation')
|
||||
break
|
||||
case 'navigate-to-emails':
|
||||
router.push('/settings/emails')
|
||||
break
|
||||
case 'navigate-to-labels':
|
||||
router.push('/settings/labels')
|
||||
break
|
||||
case 'navigate-to-profile':
|
||||
if (props.user) {
|
||||
router.push(`/${props.user.profile.username}`)
|
||||
}
|
||||
break
|
||||
case 'navigate-to-subscriptions':
|
||||
router.push('/settings/subscriptions')
|
||||
break
|
||||
case 'navigate-to-api':
|
||||
router.push('/settings/api')
|
||||
break
|
||||
case 'navigate-to-integrations':
|
||||
router.push('/settings/integrations')
|
||||
break
|
||||
case 'logout':
|
||||
props.setShowLogoutConfirmation(true)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<SpanBox
|
||||
css={{
|
||||
display: props.alwaysDisplayToolbar ? 'none' : 'flex',
|
||||
'@lgDown': {
|
||||
display: 'none',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<FloatingNavHeader
|
||||
{...props}
|
||||
isVisible={true}
|
||||
username={props.user?.profile.username}
|
||||
actionHandler={headerDropdownActionHandler}
|
||||
isDisplayingShadow={isScrolled}
|
||||
toolbarControl={props.toolbarControl}
|
||||
alwaysDisplayToolbar={props.alwaysDisplayToolbar}
|
||||
/>
|
||||
</SpanBox>
|
||||
<SpanBox
|
||||
css={{
|
||||
'@lg': {
|
||||
display: props.alwaysDisplayToolbar ? 'flex' : 'none',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<NavHeader
|
||||
{...props}
|
||||
isVisible={true}
|
||||
username={props.user?.profile.username}
|
||||
actionHandler={headerDropdownActionHandler}
|
||||
isDisplayingShadow={isScrolled}
|
||||
toolbarControl={props.toolbarControl}
|
||||
alwaysDisplayToolbar={props.alwaysDisplayToolbar}
|
||||
/>
|
||||
</SpanBox>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
// Separating out component so we can extract to design system
|
||||
type NavHeaderProps = {
|
||||
username?: string
|
||||
userInitials: string
|
||||
actionHandler: (action: HeaderDropdownAction) => void
|
||||
profileImageURL?: string
|
||||
isDisplayingShadow?: boolean
|
||||
isVisible?: boolean
|
||||
isTransparent: boolean
|
||||
toolbarControl?: JSX.Element
|
||||
alwaysDisplayToolbar?: boolean
|
||||
}
|
||||
|
||||
function NavHeader(props: NavHeaderProps): JSX.Element {
|
||||
return (
|
||||
<nav>
|
||||
<HStack
|
||||
alignment="center"
|
||||
distribution="between"
|
||||
css={{
|
||||
zIndex: 5,
|
||||
width: '100%',
|
||||
boxShadow: props.isDisplayingShadow ? '$panelShadow' : 'unset',
|
||||
p: '0px $3 0px $3',
|
||||
height: '48px',
|
||||
position: 'fixed',
|
||||
bg: props.isTransparent ? 'transparent' : '$grayBase',
|
||||
'@smDown': {
|
||||
p: '0px 18px 0px 16px',
|
||||
},
|
||||
'@lgDown': {
|
||||
bg: '$grayBase',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<HStack alignment="center" distribution="start">
|
||||
<Box
|
||||
css={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
paddingRight: '10px',
|
||||
}}
|
||||
>
|
||||
<OmnivoreNameLogo href={props.username ? '/home' : '/login'} />
|
||||
</Box>
|
||||
</HStack>
|
||||
|
||||
{props.toolbarControl && (
|
||||
<HStack
|
||||
distribution="end"
|
||||
alignment="center"
|
||||
css={{
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
mr: '16px',
|
||||
display: props.alwaysDisplayToolbar ? 'flex' : 'none',
|
||||
'@lgDown': {
|
||||
display: 'flex',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{props.toolbarControl}
|
||||
</HStack>
|
||||
)}
|
||||
|
||||
{props.username && (
|
||||
<HStack
|
||||
alignment="center"
|
||||
css={{ display: 'flex', alignItems: 'center' }}
|
||||
>
|
||||
<DropdownMenu
|
||||
username={props.username}
|
||||
triggerElement={
|
||||
<AvatarDropdown userInitials={props.userInitials} />
|
||||
}
|
||||
actionHandler={props.actionHandler}
|
||||
/>
|
||||
</HStack>
|
||||
)}
|
||||
</HStack>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
|
||||
function FloatingNavHeader(props: NavHeaderProps): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<HStack alignment="center" distribution="start">
|
||||
<Box
|
||||
css={{
|
||||
top: '13px',
|
||||
left: '18px',
|
||||
position: 'fixed',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
zIndex: 5,
|
||||
}}
|
||||
>
|
||||
<OmnivoreNameLogo href={props.username ? '/home' : '/login'} />
|
||||
</Box>
|
||||
</HStack>
|
||||
|
||||
{props.username && (
|
||||
<HStack
|
||||
alignment="center"
|
||||
css={{
|
||||
top: '13px',
|
||||
right: '18px',
|
||||
position: 'fixed',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<DropdownMenu
|
||||
username={props.username}
|
||||
triggerElement={
|
||||
<AvatarDropdown userInitials={props.userInitials} />
|
||||
}
|
||||
actionHandler={props.actionHandler}
|
||||
/>
|
||||
</HStack>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { Box } from '../elements/LayoutPrimitives'
|
||||
import { Box, VStack } from '../elements/LayoutPrimitives'
|
||||
import { useGetViewerQuery } from '../../lib/networking/queries/useGetViewerQuery'
|
||||
import { PrimaryHeader } from '../patterns/PrimaryHeader'
|
||||
import { SettingsHeader } from '../patterns/SettingsHeader'
|
||||
import { navigationCommands } from '../../lib/keyboardShortcuts/navigationShortcuts'
|
||||
import { useKeyboardShortcuts } from '../../lib/keyboardShortcuts/useKeyboardShortcuts'
|
||||
import { useRouter } from 'next/router'
|
||||
|
|
@ -10,6 +10,7 @@ import { useState } from 'react'
|
|||
import { ConfirmationModal } from '../patterns/ConfirmationModal'
|
||||
import { KeyboardShortcutListModal } from './KeyboardShortcutListModal'
|
||||
import { PageMetaData } from '../patterns/PageMetaData'
|
||||
import { HeaderSpacer, MOBILE_HEADER_HEIGHT } from './homeFeed/HeaderSpacer'
|
||||
|
||||
type SettingsLayoutProps = {
|
||||
title?: string
|
||||
|
|
@ -20,7 +21,8 @@ export function SettingsLayout(props: SettingsLayoutProps): JSX.Element {
|
|||
const { viewerData } = useGetViewerQuery()
|
||||
const router = useRouter()
|
||||
const [showLogoutConfirmation, setShowLogoutConfirmation] = useState(false)
|
||||
const [showKeyboardCommandsModal, setShowKeyboardCommandsModal] = useState(false)
|
||||
const [showKeyboardCommandsModal, setShowKeyboardCommandsModal] =
|
||||
useState(false)
|
||||
|
||||
useKeyboardShortcuts(navigationCommands(router))
|
||||
applyStoredTheme(false)
|
||||
|
|
@ -41,39 +43,30 @@ export function SettingsLayout(props: SettingsLayoutProps): JSX.Element {
|
|||
|
||||
return (
|
||||
<>
|
||||
<PageMetaData path='settings' title='Settings' />
|
||||
<PrimaryHeader
|
||||
user={viewerData?.me}
|
||||
isTransparent={false}
|
||||
userInitials={viewerData?.me?.name.charAt(0) ?? ''}
|
||||
profileImageURL={viewerData?.me?.profile.pictureUrl}
|
||||
setShowLogoutConfirmation={setShowLogoutConfirmation}
|
||||
setShowKeyboardCommandsModal={setShowKeyboardCommandsModal}
|
||||
/>
|
||||
<PageMetaData path="settings" title="Settings" />
|
||||
<SettingsHeader user={viewerData?.me} />
|
||||
<VStack css={{ width: '100%', height: '100%' }}>
|
||||
<Box
|
||||
css={{
|
||||
top: '48px',
|
||||
position: 'fixed',
|
||||
overflowY: 'auto',
|
||||
height: '100%',
|
||||
width: '100vw',
|
||||
height: MOBILE_HEADER_HEIGHT,
|
||||
bg: '$grayBase',
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
{showLogoutConfirmation ? (
|
||||
<ConfirmationModal
|
||||
message={'Are you sure you want to log out?'}
|
||||
onAccept={logout}
|
||||
onOpenChange={() => setShowLogoutConfirmation(false)}
|
||||
/>
|
||||
) : null}
|
||||
{showKeyboardCommandsModal ? (
|
||||
<KeyboardShortcutListModal
|
||||
onOpenChange={() => setShowKeyboardCommandsModal(false)}
|
||||
/>
|
||||
) : null}
|
||||
</Box>
|
||||
></Box>
|
||||
{props.children}
|
||||
<Box css={{ height: '120px', width: '100%' }} />
|
||||
</VStack>
|
||||
{showLogoutConfirmation ? (
|
||||
<ConfirmationModal
|
||||
message={'Are you sure you want to log out?'}
|
||||
onAccept={logout}
|
||||
onOpenChange={() => setShowLogoutConfirmation(false)}
|
||||
/>
|
||||
) : null}
|
||||
{showKeyboardCommandsModal ? (
|
||||
<KeyboardShortcutListModal
|
||||
onOpenChange={() => setShowKeyboardCommandsModal(false)}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ export default function Integrations(): JSX.Element {
|
|||
top: '5rem',
|
||||
}}
|
||||
/>
|
||||
<Header css={{ textAlign: 'center' }}>Integrations</Header>
|
||||
<Header css={{ textAlign: 'center', width: '100%' }}>Integrations</Header>
|
||||
<Subheader>
|
||||
Connect with other applications can help enhance and streamline your
|
||||
experience with Omnivore, below are some useful apps to connect your
|
||||
|
|
@ -142,7 +142,7 @@ export default function Integrations(): JSX.Element {
|
|||
css={{
|
||||
width: '80%',
|
||||
margin: '0 auto',
|
||||
height: '500px',
|
||||
height: '100%',
|
||||
'@smDown': {
|
||||
width: '100%',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { deleteWebhookMutation } from '../../lib/networking/mutations/deleteWebh
|
|||
import { FormModal } from '../../components/patterns/FormModal'
|
||||
import { setWebhookMutation } from '../../lib/networking/mutations/setWebhookMutation'
|
||||
import { FormInputProps } from '../../components/elements/FormElements'
|
||||
import { Box } from '../../components/elements/LayoutPrimitives'
|
||||
|
||||
interface Webhook {
|
||||
id?: string
|
||||
|
|
@ -207,6 +208,7 @@ export default function Webhooks(): JSX.Element {
|
|||
setOnEditWebhook(webhook)
|
||||
}}
|
||||
/>
|
||||
<Box css={{ height: '120px' }} />
|
||||
</SettingsLayout>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue