fix: responsiveness when resizing window on web/desktop (#1637)
This commit is contained in:
@@ -62,7 +62,7 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
|
|||||||
<div
|
<div
|
||||||
id="navigation"
|
id="navigation"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'sn-component section app-column h-screen max-h-screen w-[220px] overflow-hidden pt-safe-top md:h-full md:min-h-0 md:py-0 xsm-only:!w-full sm-only:!w-full',
|
'sn-component section app-column h-screen max-h-screen w-[220px] overflow-hidden pt-safe-top md:h-full md:max-h-full md:min-h-0 md:py-0 xsm-only:!w-full sm-only:!w-full',
|
||||||
isIOS() ? 'pb-safe-bottom' : 'pb-2.5',
|
isIOS() ? 'pb-safe-bottom' : 'pb-2.5',
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { MediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
|
||||||
import { CSSProperties } from 'react'
|
import { CSSProperties } from 'react'
|
||||||
import { PopoverAlignment, PopoverSide } from './Types'
|
import { PopoverAlignment, PopoverSide } from './Types'
|
||||||
import { OppositeSide, checkCollisions, getNonCollidingSide, getNonCollidingAlignment } from './Utils/Collisions'
|
import { OppositeSide, checkCollisions, getNonCollidingSide, getNonCollidingAlignment } from './Utils/Collisions'
|
||||||
@@ -29,7 +30,7 @@ export const getPositionedPopoverStyles = ({
|
|||||||
return [null, side, align]
|
return [null, side, align]
|
||||||
}
|
}
|
||||||
|
|
||||||
const matchesMediumBreakpoint = matchMedia('(min-width: 768px)').matches
|
const matchesMediumBreakpoint = matchMedia(MediaQueryBreakpoints.md).matches
|
||||||
|
|
||||||
if (!matchesMediumBreakpoint) {
|
if (!matchesMediumBreakpoint) {
|
||||||
return [null, side, align]
|
return [null, side, align]
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import { getPositionedPopoverStyles } from './GetPositionedPopoverStyles'
|
|||||||
import { PopoverContentProps } from './Types'
|
import { PopoverContentProps } from './Types'
|
||||||
import { getPopoverMaxHeight, getAppRect } from './Utils/Rect'
|
import { getPopoverMaxHeight, getAppRect } from './Utils/Rect'
|
||||||
import { usePopoverCloseOnClickOutside } from './Utils/usePopoverCloseOnClickOutside'
|
import { usePopoverCloseOnClickOutside } from './Utils/usePopoverCloseOnClickOutside'
|
||||||
import { fitNodeToMobileScreen } from '@/Utils'
|
|
||||||
import { useDisableBodyScrollOnMobile } from '@/Hooks/useDisableBodyScrollOnMobile'
|
import { useDisableBodyScrollOnMobile } from '@/Hooks/useDisableBodyScrollOnMobile'
|
||||||
|
import { MediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
|
||||||
|
|
||||||
const PositionedPopoverContent = ({
|
const PositionedPopoverContent = ({
|
||||||
align = 'end',
|
align = 'end',
|
||||||
@@ -35,6 +35,7 @@ const PositionedPopoverContent = ({
|
|||||||
})
|
})
|
||||||
const anchorRect = anchorPoint ? anchorPointRect : anchorElementRect
|
const anchorRect = anchorPoint ? anchorPointRect : anchorElementRect
|
||||||
const documentRect = useDocumentRect()
|
const documentRect = useDocumentRect()
|
||||||
|
const isDesktopScreen = useMediaQuery(MediaQueryBreakpoints.md)
|
||||||
|
|
||||||
const [styles, positionedSide, positionedAlignment] = getPositionedPopoverStyles({
|
const [styles, positionedSide, positionedAlignment] = getPositionedPopoverStyles({
|
||||||
align,
|
align,
|
||||||
@@ -63,10 +64,10 @@ const PositionedPopoverContent = ({
|
|||||||
style={{
|
style={{
|
||||||
...styles,
|
...styles,
|
||||||
maxHeight: getPopoverMaxHeight(getAppRect(documentRect), anchorRect, positionedSide, positionedAlignment),
|
maxHeight: getPopoverMaxHeight(getAppRect(documentRect), anchorRect, positionedSide, positionedAlignment),
|
||||||
|
top: !isDesktopScreen ? `${document.documentElement.scrollTop}px` : '',
|
||||||
}}
|
}}
|
||||||
ref={(node) => {
|
ref={(node) => {
|
||||||
setPopoverElement(node)
|
setPopoverElement(node)
|
||||||
fitNodeToMobileScreen(node)
|
|
||||||
}}
|
}}
|
||||||
data-popover={id}
|
data-popover={id}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { MediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
|
||||||
import { PopoverSide, PopoverAlignment } from '../Types'
|
import { PopoverSide, PopoverAlignment } from '../Types'
|
||||||
|
|
||||||
export const getPopoverMaxHeight = (
|
export const getPopoverMaxHeight = (
|
||||||
@@ -6,7 +7,7 @@ export const getPopoverMaxHeight = (
|
|||||||
side: PopoverSide,
|
side: PopoverSide,
|
||||||
alignment: PopoverAlignment,
|
alignment: PopoverAlignment,
|
||||||
): number | 'none' => {
|
): number | 'none' => {
|
||||||
const matchesMediumBreakpoint = matchMedia('(min-width: 768px)').matches
|
const matchesMediumBreakpoint = matchMedia(MediaQueryBreakpoints.md).matches
|
||||||
|
|
||||||
if (!matchesMediumBreakpoint) {
|
if (!matchesMediumBreakpoint) {
|
||||||
return 'none'
|
return 'none'
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { MediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
@@ -15,7 +16,7 @@ export const usePopoverCloseOnClickOutside = ({
|
|||||||
}: Options) => {
|
}: Options) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const closeIfClickedOutside = (event: MouseEvent) => {
|
const closeIfClickedOutside = (event: MouseEvent) => {
|
||||||
const matchesMediumBreakpoint = matchMedia('(min-width: 768px)').matches
|
const matchesMediumBreakpoint = matchMedia(MediaQueryBreakpoints.md).matches
|
||||||
|
|
||||||
if (!matchesMediumBreakpoint) {
|
if (!matchesMediumBreakpoint) {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ import { observer } from 'mobx-react-lite'
|
|||||||
import { PreferencesMenu } from './PreferencesMenu'
|
import { PreferencesMenu } from './PreferencesMenu'
|
||||||
import PreferencesCanvas from './PreferencesCanvas'
|
import PreferencesCanvas from './PreferencesCanvas'
|
||||||
import { PreferencesProps } from './PreferencesProps'
|
import { PreferencesProps } from './PreferencesProps'
|
||||||
import { fitNodeToMobileScreen, isIOS } from '@/Utils'
|
import { isIOS } from '@/Utils'
|
||||||
import { useDisableBodyScrollOnMobile } from '@/Hooks/useDisableBodyScrollOnMobile'
|
import { useDisableBodyScrollOnMobile } from '@/Hooks/useDisableBodyScrollOnMobile'
|
||||||
import { classNames } from '@/Utils/ConcatenateClassNames'
|
import { classNames } from '@/Utils/ConcatenateClassNames'
|
||||||
|
import { MediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
|
||||||
|
|
||||||
const PreferencesView: FunctionComponent<PreferencesProps> = (props) => {
|
const PreferencesView: FunctionComponent<PreferencesProps> = (props) => {
|
||||||
|
const isDesktopScreen = useMediaQuery(MediaQueryBreakpoints.md)
|
||||||
|
|
||||||
const menu = useMemo(
|
const menu = useMemo(
|
||||||
() => new PreferencesMenu(props.application, props.viewControllerManager.enableUnfinishedFeatures),
|
() => new PreferencesMenu(props.application, props.viewControllerManager.enableUnfinishedFeatures),
|
||||||
[props.viewControllerManager.enableUnfinishedFeatures, props.application],
|
[props.viewControllerManager.enableUnfinishedFeatures, props.application],
|
||||||
@@ -33,10 +36,12 @@ const PreferencesView: FunctionComponent<PreferencesProps> = (props) => {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'absolute top-0 left-0 z-preferences flex h-full max-h-screen w-full flex-col bg-default pt-safe-top',
|
'absolute top-0 left-0 z-preferences flex h-screen max-h-screen w-full flex-col bg-default pt-safe-top md:h-full md:max-h-full',
|
||||||
isIOS() ? 'pb-safe-bottom' : 'pb-2 md:pb-0',
|
isIOS() ? 'pb-safe-bottom' : 'pb-2 md:pb-0',
|
||||||
)}
|
)}
|
||||||
ref={fitNodeToMobileScreen}
|
style={{
|
||||||
|
top: !isDesktopScreen ? `${document.documentElement.scrollTop}px` : '',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex w-full flex-row items-center justify-between border-b border-solid border-border bg-default px-3 py-2 md:p-3">
|
<div className="flex w-full flex-row items-center justify-between border-b border-solid border-border bg-default px-3 py-2 md:p-3">
|
||||||
<div className="hidden h-8 w-8 md:block" />
|
<div className="hidden h-8 w-8 md:block" />
|
||||||
|
|||||||
26
packages/web/src/javascripts/Hooks/useMediaQuery.tsx
Normal file
26
packages/web/src/javascripts/Hooks/useMediaQuery.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
// Follows https://tailwindcss.com/docs/responsive-design
|
||||||
|
export const MediaQueryBreakpoints = {
|
||||||
|
sm: '(min-width: 640px)',
|
||||||
|
md: '(min-width: 768px)',
|
||||||
|
lg: '(min-width: 1024px)',
|
||||||
|
xl: '(min-width: 1280px)',
|
||||||
|
'2xl': '(min-width: 1536px)',
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export const useMediaQuery = (mediaQuery: string) => {
|
||||||
|
const [matches, setMatches] = useState(() => window.matchMedia(mediaQuery).matches)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = (event: MediaQueryListEvent) => {
|
||||||
|
setMatches(event.matches)
|
||||||
|
}
|
||||||
|
|
||||||
|
window.matchMedia(mediaQuery).addEventListener('change', handler)
|
||||||
|
|
||||||
|
return () => window.matchMedia(mediaQuery).removeEventListener('change', handler)
|
||||||
|
}, [mediaQuery])
|
||||||
|
|
||||||
|
return matches
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Platform, platformFromString } from '@standardnotes/snjs'
|
import { Platform, platformFromString } from '@standardnotes/snjs'
|
||||||
import { IsDesktopPlatform, IsWebPlatform } from '@/Constants/Version'
|
import { IsDesktopPlatform, IsWebPlatform } from '@/Constants/Version'
|
||||||
import { EMAIL_REGEX } from '../Constants/Constants'
|
import { EMAIL_REGEX } from '../Constants/Constants'
|
||||||
|
import { MediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
|
||||||
|
|
||||||
declare const process: {
|
declare const process: {
|
||||||
env: {
|
env: {
|
||||||
@@ -202,13 +203,4 @@ export const disableIosTextFieldZoom = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isMobileScreen = () => !window.matchMedia('(min-width: 768px)').matches
|
export const isMobileScreen = () => !window.matchMedia(MediaQueryBreakpoints.md).matches
|
||||||
|
|
||||||
export const fitNodeToMobileScreen = (node: HTMLElement | null) => {
|
|
||||||
if (!node || !isMobileScreen()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
node.style.height = `${visualViewport.height}px`
|
|
||||||
node.style.position = 'absolute'
|
|
||||||
node.style.top = `${document.documentElement.scrollTop}px`
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user