gluestack / gluestack-ui

React & React Native Components & Patterns (import from library & copy-paste styles all the way to victory)
https://gluestack.io/
MIT License
1.77k stars 89 forks source link

css and js breakpoints don't match when the "show scroll bars" setting set to "always" on MacOS #1418

Open hamsterhomka opened 7 months ago

hamsterhomka commented 7 months ago

Description

css and js breakpoints don't match when the "show scroll bars" setting set to "always" on MacOS. It happens because css counts the actual 1264px browser's window width as 1280px, whereas js useMedia() hook counts 1280px as 1280px. We can see that the issue is exactly in the 16px width scrollbar.

CodeSandbox/Snack link

No response

Steps to reproduce

Here's the example repo with the issue. https://github.com/hamsterhomka/gluestack-issue-breakpoints

  1. Set "show scroll bars" setting to "always" in Appearance settings on MacOs
  2. Start the dev server
  3. Try to change the window width
  4. See that the breakpoints don't match

gluestack-ui Version

1.0.0

Platform

Other Platform

No response

Additional Information

js box is not visible (1279px)

xl-js-not-visible

js box is visible (1282px)

xl-js-visible

css box is not visible (1264px)

xl-css-not-visible

css box is visible (1266px)

xl-css-visible

Here is a simple patch to fix it. I created a hook useInnerWidth() that returns window.innerWidth on web (that matches css breakpoints) and used it in useMedia() gluestack hook

@gluestack-style-react-npm-1.0.11-e64493965f.patch

diff --git a/lib/module/hooks/useMedia.js b/lib/module/hooks/useMedia.js
index 89d163981c9d889a3623a6826721dd3f9ab7f910..3aaedc0a00ffd4e7a2c208851ca194a1b3de925b 100644
--- a/lib/module/hooks/useMedia.js
+++ b/lib/module/hooks/useMedia.js
@@ -1,17 +1,45 @@
-import { useWindowDimensions } from 'react-native';
-import { isValidBreakpoint } from '../generateStylePropsFromCSSIds';
-import { useStyled } from '../StyledProvider';
-export const useMedia = () => {
-  var _theme$config;
-  const theme = useStyled();
+import { Platform, useWindowDimensions } from 'react-native'
+import { isValidBreakpoint } from '../generateStylePropsFromCSSIds'
+import { useStyled } from '../StyledProvider'
+import { useEffect, useState } from 'react'
+
+const useInnerWidth = () => {
   const {
     width
-  } = useWindowDimensions();
-  const mediaQueries = theme === null || theme === void 0 || (_theme$config = theme.config) === null || _theme$config === void 0 || (_theme$config = _theme$config.tokens) === null || _theme$config === void 0 ? void 0 : _theme$config.mediaQueries;
-  const breakpoints = {};
+  } = useWindowDimensions()
+
+  const initialWidth = Platform.OS === 'web' && typeof window !== 'undefined' ? window.innerWidth : width
+  const [innerWidth, setInnerWidth] = useState(initialWidth)
+
+  const handleResize = () => {
+    setInnerWidth(window.innerWidth)
+  }
+
+  useEffect(() => {
+    if (Platform.OS === 'web') {
+      setInnerWidth(window.innerWidth);
+
+      window.addEventListener('resize', handleResize);
+    }
+
+    return () => {
+      window.removeEventListener('resize', handleResize);
+    };
+  }, [])
+
+  return innerWidth
+}
+
+export const useMedia = () => {
+  var _theme$config
+  const theme = useStyled()
+  const width = useInnerWidth()
+
+  const mediaQueries = theme === null || theme === void 0 || (_theme$config = theme.config) === null || _theme$config === void 0 || (_theme$config = _theme$config.tokens) === null || _theme$config === void 0 ? void 0 : _theme$config.mediaQueries
+  const breakpoints = {}
   Object.keys(mediaQueries).forEach(currentBreakPoint => {
-    breakpoints[currentBreakPoint] = isValidBreakpoint(theme === null || theme === void 0 ? void 0 : theme.config, mediaQueries[currentBreakPoint], width);
-  });
-  return breakpoints;
-};
+    breakpoints[currentBreakPoint] = isValidBreakpoint(theme === null || theme === void 0 ? void 0 : theme.config, mediaQueries[currentBreakPoint], width)
+  })
+  return breakpoints
+}
 //# sourceMappingURL=useMedia.js.map
Gluant101 commented 7 months ago

Hey, our Devs will look into this. Thanks!

ankit-tailor commented 6 months ago

Hey @hamsterhomka, Thanks for reporting the issue. We'll look into it.

hamsterhomka commented 5 months ago

Any updates on fixing this?

surajahmed commented 1 month ago

@hamsterhomka We're internally using useWindowDimensions hook from react-native-web, which returns window viewport width. This causes the difference when scrollbar is rendered. We're going to use window.innerWidth instead of useWindowDimenstions. Thanks for reporting this. Hopefully we'll fix this in the coming release.