Mp 2436 settings (#131)
* MP-2436: added Settings menu * tidy: refactor * fix: react to server side rendering * fix: fixed the background animations * fix: enableAnimations for bg classes * small merge fix * fix: fixed the animation less circular progress --------- Co-authored-by: Linkie Link <linkielink.dev@gmail.com>
This commit is contained in:
parent
740e982956
commit
c3b1550452
@ -63,14 +63,15 @@ export const AccountNavigation = () => {
|
||||
className='flex flex-1 flex-nowrap'
|
||||
leftIcon={<Account />}
|
||||
onClick={() => setShowMenu(!showMenu)}
|
||||
hasFocus={showMenu}
|
||||
hasSubmenu
|
||||
>
|
||||
<span>{accountSelected ? `Account ${selectedAccount}` : 'Select Account'}</span>
|
||||
</Button>
|
||||
<Overlay className='l-0 mt-2 w-[274px]' show={showMenu} setShow={setShowMenu}>
|
||||
<Overlay className='left-0 mt-2 w-[274px]' show={showMenu} setShow={setShowMenu}>
|
||||
{accountSelected && (
|
||||
<div className='flex w-full flex-wrap'>
|
||||
<Text size='sm' uppercase={true} className='w-full justify-center px-4 pt-4'>
|
||||
<Text size='sm' uppercase={true} className='w-full px-4 pt-4'>
|
||||
Manage Account {selectedAccount}
|
||||
</Text>
|
||||
<div className='flex w-full justify-between p-4'>
|
||||
@ -133,7 +134,7 @@ export const AccountNavigation = () => {
|
||||
)}
|
||||
{creditAccounts.length > 1 && (
|
||||
<div className='flex w-full flex-wrap border-t border-t-white/10 p-4'>
|
||||
<Text size='sm' uppercase={true} className='w-full justify-center pb-2'>
|
||||
<Text size='sm' uppercase={true} className='w-full pb-2'>
|
||||
Select Account
|
||||
</Text>
|
||||
{creditAccounts.map((account) =>
|
||||
|
@ -1,6 +1,12 @@
|
||||
'use client'
|
||||
|
||||
import classNames from 'classnames'
|
||||
|
||||
import useStore from 'store'
|
||||
|
||||
export default function Background() {
|
||||
const enableAnimations = useStore((s) => s.enableAnimations)
|
||||
|
||||
return (
|
||||
<div className='background pointer-events-none fixed inset-0 h-full w-full overflow-hidden bg-body'>
|
||||
<div
|
||||
@ -12,7 +18,7 @@ export default function Background() {
|
||||
'top-[-10vw] left-[-10vw]',
|
||||
'bg-orb-primary blur-orb-primary ',
|
||||
'translate-x-0 translate-y-0 rounded-full opacity-20',
|
||||
'animate-[float_120s_ease_in_out_infinite_2s]',
|
||||
enableAnimations && 'animate-[float_120s_ease-in-out_infinite_2s]',
|
||||
)}
|
||||
/>
|
||||
<div
|
||||
@ -24,7 +30,7 @@ export default function Background() {
|
||||
'bottom-[-10vw] right-[-8vw]',
|
||||
'bg-orb-secondary blur-orb-secondary',
|
||||
'translate-x-0 translate-y-0 rounded-full opacity-30',
|
||||
'animate-[float_150s_bounce_out_infinite_1s]',
|
||||
enableAnimations && 'animate-[float_150s_ease-in-out_infinite_1s]',
|
||||
)}
|
||||
/>
|
||||
<div
|
||||
@ -36,7 +42,7 @@ export default function Background() {
|
||||
'top-[-10vw] right-[-4vw]',
|
||||
'bg-orb-tertiary blur-orb-tertiary ',
|
||||
'translate-x-0 translate-y-0 rounded-full opacity-20',
|
||||
'animate-[float_180s_ease_in_infinite]',
|
||||
enableAnimations && 'animate-[float_180s_ease-in_infinite]',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
@ -20,7 +20,10 @@ export const CircularProgress = ({ color = '#FFFFFF', size = 20, className }: Pr
|
||||
|
||||
if (!enableAnimations)
|
||||
return (
|
||||
<div className={loaderClasses} style={{ width: `${size}px`, height: `${size}px` }}>
|
||||
<div
|
||||
className={classNames('flex items-center', loaderClasses)}
|
||||
style={{ width: `${size}px`, height: `${size}px` }}
|
||||
>
|
||||
<Text className='text-center' uppercase size='lg'>
|
||||
...
|
||||
</Text>
|
||||
|
6
src/components/Icons/Gear.svg
Normal file
6
src/components/Icons/Gear.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<path
|
||||
d='M9.99996 13.5C9.0717 13.5 8.18147 13.1313 7.52509 12.4749C6.86871 11.8185 6.49996 10.9283 6.49996 10C6.49996 9.07174 6.86871 8.18151 7.52509 7.52513C8.18147 6.86875 9.0717 6.5 9.99996 6.5C10.9282 6.5 11.8185 6.86875 12.4748 7.52513C13.1312 8.18151 13.5 9.07174 13.5 10C13.5 10.9283 13.1312 11.8185 12.4748 12.4749C11.8185 13.1313 10.9282 13.5 9.99996 13.5M17.43 10.97C17.47 10.65 17.5 10.33 17.5 10C17.5 9.67 17.47 9.34 17.43 9L19.54 7.37C19.73 7.22 19.78 6.95 19.66 6.73L17.66 3.27C17.54 3.05 17.27 2.96 17.05 3.05L14.56 4.05C14.04 3.66 13.5 3.32 12.87 3.07L12.5 0.420002C12.4796 0.302219 12.4183 0.195429 12.3268 0.118553C12.2353 0.0416778 12.1195 -0.000319774 12 1.83347e-06H7.99996C7.74996 1.83347e-06 7.53996 0.180002 7.49996 0.420002L7.12996 3.07C6.49996 3.32 5.95996 3.66 5.43996 4.05L2.94996 3.05C2.72996 2.96 2.45996 3.05 2.33996 3.27L0.339961 6.73C0.209961 6.95 0.269962 7.22 0.459962 7.37L2.56996 9C2.52996 9.34 2.49996 9.67 2.49996 10C2.49996 10.33 2.52996 10.65 2.56996 10.97L0.459962 12.63C0.269962 12.78 0.209961 13.05 0.339961 13.27L2.33996 16.73C2.45996 16.95 2.72996 17.03 2.94996 16.95L5.43996 15.94C5.95996 16.34 6.49996 16.68 7.12996 16.93L7.49996 19.58C7.53996 19.82 7.74996 20 7.99996 20H12C12.25 20 12.46 19.82 12.5 19.58L12.87 16.93C13.5 16.67 14.04 16.34 14.56 15.94L17.05 16.95C17.27 17.03 17.54 16.95 17.66 16.73L19.66 13.27C19.78 13.05 19.73 12.78 19.54 12.63L17.43 10.97V10.97Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
@ -25,6 +25,7 @@ export { default as Edit } from 'components/Icons/Edit.svg'
|
||||
export { default as Ellipsis } from 'components/Icons/Ellipsis.svg'
|
||||
export { default as ExternalLink } from 'components/Icons/ExternalLink.svg'
|
||||
export { default as Failed } from 'components/Icons/Failed.svg'
|
||||
export { default as Gear } from 'components/Icons/Gear.svg'
|
||||
export { default as Github } from 'components/Icons/Github.svg'
|
||||
export { default as Heart } from 'components/Icons/Heart.svg'
|
||||
export { default as Info } from 'components/Icons/Info.svg'
|
||||
|
@ -1,13 +1,15 @@
|
||||
'use client'
|
||||
|
||||
import classNames from 'classnames'
|
||||
import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import { AccountNavigation } from 'components/Account/AccountNavigation'
|
||||
import { Logo } from 'components/Icons'
|
||||
import { NavLink } from 'components/Navigation/NavLink'
|
||||
import Settings from 'components/Settings'
|
||||
import Wallet from 'components/Wallet/Wallet'
|
||||
import { useAnimations } from 'hooks/data/useAnimations'
|
||||
import { getRoute } from 'utils/route'
|
||||
|
||||
export const menuTree: { href: RouteSegment; label: string }[] = [
|
||||
@ -47,6 +49,7 @@ export default function DesktopNavigation() {
|
||||
<div className='flex gap-4'>
|
||||
<AccountNavigation />
|
||||
<Wallet />
|
||||
<Settings />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
61
src/components/Settings.tsx
Normal file
61
src/components/Settings.tsx
Normal file
@ -0,0 +1,61 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
|
||||
import { Button } from 'components/Button'
|
||||
import { Gear } from 'components/Icons'
|
||||
import { Overlay } from 'components/Overlay/Overlay'
|
||||
import Switch from 'components/Switch'
|
||||
import { Text } from 'components/Text'
|
||||
import { Tooltip } from 'components/Tooltip'
|
||||
import { ENABLE_ANIMATIONS_KEY } from 'constants/localStore'
|
||||
import { useAnimations } from 'hooks/data/useAnimations'
|
||||
import useStore from 'store'
|
||||
|
||||
export default function Settings() {
|
||||
useAnimations()
|
||||
|
||||
const [showMenu, setShowMenu] = useState(false)
|
||||
const enableAnimations = useStore((s) => s.enableAnimations)
|
||||
|
||||
function handleReduceMotion(val: boolean) {
|
||||
useStore.setState({ enableAnimations: !val })
|
||||
if (typeof window !== 'undefined')
|
||||
window.localStorage.setItem(ENABLE_ANIMATIONS_KEY, val ? 'false' : 'true')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='relative'>
|
||||
<Button
|
||||
variant='solid'
|
||||
color='tertiary'
|
||||
icon={<Gear />}
|
||||
onClick={() => setShowMenu(!showMenu)}
|
||||
hasFocus={showMenu}
|
||||
/>
|
||||
<Overlay className='right-0 mt-2 w-[240px]' show={showMenu} setShow={setShowMenu}>
|
||||
<div className='flex w-full flex-wrap p-4'>
|
||||
<Text size='sm' uppercase={true} className='w-full pb-4'>
|
||||
Settings
|
||||
</Text>
|
||||
<div className='flex w-full'>
|
||||
<div className='flex flex-1'>
|
||||
<Text size='sm' className='mr-2'>
|
||||
Reduce Motion
|
||||
</Text>
|
||||
<Tooltip
|
||||
content={
|
||||
<Text size='sm'>
|
||||
Turns off all animations inside the dApp. Turning animations off can increase
|
||||
the overall performance on lower-end hardware.
|
||||
</Text>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<Switch name='reduceMotion' checked={!enableAnimations} onChange={handleReduceMotion} />
|
||||
</div>
|
||||
</div>
|
||||
</Overlay>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -89,6 +89,7 @@ export default function ConnectedButton() {
|
||||
onClick={() => {
|
||||
setShowDetails(!showDetails)
|
||||
}}
|
||||
hasFocus={showDetails}
|
||||
>
|
||||
<span>{truncate(address, [2, 4])}</span>
|
||||
<div
|
||||
|
2
src/constants/localStore.ts
Normal file
2
src/constants/localStore.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const DISPLAY_CURRENCY_KEY = 'displayCurrency'
|
||||
export const ENABLE_ANIMATIONS_KEY = 'enableAnimations'
|
@ -1,23 +1,33 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useCallback, useEffect } from 'react'
|
||||
|
||||
import { ENABLE_ANIMATIONS_KEY } from 'constants/localStore'
|
||||
import useStore from 'store'
|
||||
|
||||
export const useAnimations = () => {
|
||||
const enableAnimations = useStore((s) => s.enableAnimations)
|
||||
const enableAnimationsLocalStorage =
|
||||
typeof window !== 'undefined' ? window.localStorage.getItem(ENABLE_ANIMATIONS_KEY) : false
|
||||
|
||||
const queryChangeHandler = (event: MediaQueryListEvent) => {
|
||||
useStore.setState({ enableAnimations: !event?.matches ?? true })
|
||||
}
|
||||
const queryChangeHandler = useCallback(
|
||||
(event: MediaQueryListEvent) => {
|
||||
if (enableAnimationsLocalStorage) return
|
||||
useStore.setState({ enableAnimations: !event?.matches ?? true })
|
||||
},
|
||||
[enableAnimationsLocalStorage],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const mediaQuery: MediaQueryList = window.matchMedia('(prefers-reduced-motion: reduce)')
|
||||
const storeSetting = enableAnimationsLocalStorage === 'true'
|
||||
useStore.setState({ enableAnimations: storeSetting })
|
||||
|
||||
if (mediaQuery) {
|
||||
if (enableAnimationsLocalStorage) return
|
||||
useStore.setState({ enableAnimations: !mediaQuery.matches })
|
||||
mediaQuery.addEventListener('change', queryChangeHandler)
|
||||
return () => mediaQuery.removeEventListener('change', queryChangeHandler)
|
||||
}
|
||||
}, [])
|
||||
}, [enableAnimations, enableAnimationsLocalStorage, queryChangeHandler])
|
||||
|
||||
return enableAnimations
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user