fix: responsiveness when resizing window on web/desktop (#1637)
This commit is contained in:
@@ -62,7 +62,7 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
|
||||
<div
|
||||
id="navigation"
|
||||
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',
|
||||
)}
|
||||
ref={ref}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { MediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
|
||||
import { CSSProperties } from 'react'
|
||||
import { PopoverAlignment, PopoverSide } from './Types'
|
||||
import { OppositeSide, checkCollisions, getNonCollidingSide, getNonCollidingAlignment } from './Utils/Collisions'
|
||||
@@ -29,7 +30,7 @@ export const getPositionedPopoverStyles = ({
|
||||
return [null, side, align]
|
||||
}
|
||||
|
||||
const matchesMediumBreakpoint = matchMedia('(min-width: 768px)').matches
|
||||
const matchesMediumBreakpoint = matchMedia(MediaQueryBreakpoints.md).matches
|
||||
|
||||
if (!matchesMediumBreakpoint) {
|
||||
return [null, side, align]
|
||||
|
||||
@@ -9,8 +9,8 @@ import { getPositionedPopoverStyles } from './GetPositionedPopoverStyles'
|
||||
import { PopoverContentProps } from './Types'
|
||||
import { getPopoverMaxHeight, getAppRect } from './Utils/Rect'
|
||||
import { usePopoverCloseOnClickOutside } from './Utils/usePopoverCloseOnClickOutside'
|
||||
import { fitNodeToMobileScreen } from '@/Utils'
|
||||
import { useDisableBodyScrollOnMobile } from '@/Hooks/useDisableBodyScrollOnMobile'
|
||||
import { MediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
|
||||
|
||||
const PositionedPopoverContent = ({
|
||||
align = 'end',
|
||||
@@ -35,6 +35,7 @@ const PositionedPopoverContent = ({
|
||||
})
|
||||
const anchorRect = anchorPoint ? anchorPointRect : anchorElementRect
|
||||
const documentRect = useDocumentRect()
|
||||
const isDesktopScreen = useMediaQuery(MediaQueryBreakpoints.md)
|
||||
|
||||
const [styles, positionedSide, positionedAlignment] = getPositionedPopoverStyles({
|
||||
align,
|
||||
@@ -63,10 +64,10 @@ const PositionedPopoverContent = ({
|
||||
style={{
|
||||
...styles,
|
||||
maxHeight: getPopoverMaxHeight(getAppRect(documentRect), anchorRect, positionedSide, positionedAlignment),
|
||||
top: !isDesktopScreen ? `${document.documentElement.scrollTop}px` : '',
|
||||
}}
|
||||
ref={(node) => {
|
||||
setPopoverElement(node)
|
||||
fitNodeToMobileScreen(node)
|
||||
}}
|
||||
data-popover={id}
|
||||
>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { MediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
|
||||
import { PopoverSide, PopoverAlignment } from '../Types'
|
||||
|
||||
export const getPopoverMaxHeight = (
|
||||
@@ -6,7 +7,7 @@ export const getPopoverMaxHeight = (
|
||||
side: PopoverSide,
|
||||
alignment: PopoverAlignment,
|
||||
): number | 'none' => {
|
||||
const matchesMediumBreakpoint = matchMedia('(min-width: 768px)').matches
|
||||
const matchesMediumBreakpoint = matchMedia(MediaQueryBreakpoints.md).matches
|
||||
|
||||
if (!matchesMediumBreakpoint) {
|
||||
return 'none'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { MediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
type Options = {
|
||||
@@ -15,7 +16,7 @@ export const usePopoverCloseOnClickOutside = ({
|
||||
}: Options) => {
|
||||
useEffect(() => {
|
||||
const closeIfClickedOutside = (event: MouseEvent) => {
|
||||
const matchesMediumBreakpoint = matchMedia('(min-width: 768px)').matches
|
||||
const matchesMediumBreakpoint = matchMedia(MediaQueryBreakpoints.md).matches
|
||||
|
||||
if (!matchesMediumBreakpoint) {
|
||||
return
|
||||
|
||||
@@ -4,11 +4,14 @@ import { observer } from 'mobx-react-lite'
|
||||
import { PreferencesMenu } from './PreferencesMenu'
|
||||
import PreferencesCanvas from './PreferencesCanvas'
|
||||
import { PreferencesProps } from './PreferencesProps'
|
||||
import { fitNodeToMobileScreen, isIOS } from '@/Utils'
|
||||
import { isIOS } from '@/Utils'
|
||||
import { useDisableBodyScrollOnMobile } from '@/Hooks/useDisableBodyScrollOnMobile'
|
||||
import { classNames } from '@/Utils/ConcatenateClassNames'
|
||||
import { MediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
|
||||
|
||||
const PreferencesView: FunctionComponent<PreferencesProps> = (props) => {
|
||||
const isDesktopScreen = useMediaQuery(MediaQueryBreakpoints.md)
|
||||
|
||||
const menu = useMemo(
|
||||
() => new PreferencesMenu(props.application, props.viewControllerManager.enableUnfinishedFeatures),
|
||||
[props.viewControllerManager.enableUnfinishedFeatures, props.application],
|
||||
@@ -33,10 +36,12 @@ const PreferencesView: FunctionComponent<PreferencesProps> = (props) => {
|
||||
return (
|
||||
<div
|
||||
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',
|
||||
)}
|
||||
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="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 { IsDesktopPlatform, IsWebPlatform } from '@/Constants/Version'
|
||||
import { EMAIL_REGEX } from '../Constants/Constants'
|
||||
import { MediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
|
||||
|
||||
declare const process: {
|
||||
env: {
|
||||
@@ -202,13 +203,4 @@ export const disableIosTextFieldZoom = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export const isMobileScreen = () => !window.matchMedia('(min-width: 768px)').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`
|
||||
}
|
||||
export const isMobileScreen = () => !window.matchMedia(MediaQueryBreakpoints.md).matches
|
||||
|
||||
Reference in New Issue
Block a user