Improve settings layout

This commit is contained in:
Jackson Harper 2023-03-10 11:03:30 +08:00
parent 47277b63ee
commit 56d79580e2
4 changed files with 29 additions and 277 deletions

View file

@ -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>
)}
</>
)
}

View file

@ -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}
</>
)
}

View file

@ -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%',
},

View file

@ -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>
)
}