Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SheetMobile: test2 #3768

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions packages/gestalt/src/SheetMobile/PartialPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ComponentProps, ReactNode, useCallback, useEffect, useId, useLayoutEffe
import classnames from 'classnames';
import ContentContainer from './ContentContainer';
import Header from './Header';
import useIsOnScreenKeyboardOpen from './useIsOnScreenKeyboardOpen';
import animation from '../animation/animation.css';
import { ANIMATION_STATE, useAnimation } from '../animation/AnimationContext';
import { useRequestAnimationFrame } from '../animation/RequestAnimationFrameContext';
Expand Down Expand Up @@ -107,6 +108,9 @@ export default function PartialPage({
// Consumes AnimationProvider & RequestAnimationFrameProvider
const { animationState, handleAnimationEnd } = useAnimation();
const { handleRequestAnimationFrame, onExternalDismiss } = useRequestAnimationFrame();
const isOnScreenKeyboardOpen = useIsOnScreenKeyboardOpen();
// eslint-disable-next-line no-console
console.log(isOnScreenKeyboardOpen);

const handleOnAnimationEnd = useCallback(() => {
handleAnimationEnd();
Expand Down Expand Up @@ -140,18 +144,49 @@ export default function PartialPage({
if (window && window.body?.style?.overflow) {
// @ts-expect-error - TS2339 - Property 'body' does not exist on type 'Window & typeof globalThis'.
prevOverflowStyle = window.body.style.overflow;
// @ts-expect-error - TS2339 - Property 'body' does not exist on type 'Window & typeof globalThis'.
prevHeightStyle = window.body.style.height;

// @ts-expect-error - TS2339 - Property 'body' does not exist on type 'Window & typeof globalThis'.
window.body.style.overflow = 'hidden';
// @ts-expect-error - TS2339 - Property 'body' does not exist on type 'Window & typeof globalThis'.
window.body.style.height = '100%';
}
return () => {
// @ts-expect-error - TS2339 - Property 'body' does not exist on type 'Window & typeof globalThis'.
if (window && window.body?.style?.overflow) {
// @ts-expect-error - TS2339 - Property 'body' does not exist on type 'Window & typeof globalThis'.
window.body.style.overflow = prevOverflowStyle;
// @ts-expect-error - TS2339 - Property 'body' does not exist on type 'Window & typeof globalThis'.
window.body.style.height = prevHeightStyle;
}
};
}, []);

// When SheetMobile is full page displayed in mobile browser, the body scroll is still accessible. Here we disable to just allow the scrolling within Modal
// useEffect(() => {
// const disableScroll = () => {
// // Get the current page scroll position
// const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
// const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
// // if any scroll is attempted,
// // set this to the previous value
// window.onscroll = () => {
// window.scrollTo(scrollLeft, scrollTop);
// };
// };

// const enableScroll = () => {
// window.onscroll = () => {};
// };

// if (isOnScreenKeyboardOpen) {
// disableScroll();
// } else {
// enableScroll();
// }
// }, [isOnScreenKeyboardOpen]);

// Use useLayoutEffect instead of useEffect as we need to close the component synchronously after all DOM mutations, useEffect was needed to prevent changing state while still rendering but useEffect will create a ms blink of the full OverlayPanel after closing which gets prevented with useLayoutEffect
useLayoutEffect(() => {
if (animationState === ANIMATION_STATE.unmount) {
Expand All @@ -170,6 +205,20 @@ export default function PartialPage({
},
[closeOnOutsideClick, onExternalDismiss, onOutsideClick],
);
// // @ts-expect-error - TS2339
// function findScroller(element) {
// // eslint-disable-next-line no-console
// console.log('scrollstart');
// // eslint-disable-next-line no-param-reassign, func-names
// element.onscroll = function () {
// // eslint-disable-next-line no-console
// console.log('scrolls', element);
// };

// Array.from(element.children).forEach(findScroller);
// }

// findScroller(document.body);

return (
<StopScrollBehavior>
Expand Down
57 changes: 57 additions & 0 deletions packages/gestalt/src/SheetMobile/useIsOnScreenKeyboardOpen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { useEffect, useState } from 'react';
import { useDeviceType } from '../contexts/DeviceTypeProvider';

const isKeyboardInput = (elem: HTMLElement) => {
// eslint-disable-next-line no-console
console.log(elem);
return (
(elem.tagName === 'INPUT' &&
['date', 'number', 'email', 'password', 'tel', 'text', 'url'].includes(
(elem as HTMLInputElement).type,
)) ||
elem.hasAttribute('contenteditable')
);
};

// This hooks detects the on-screen keyboard. In the future we can use the VirtualKeyboard API but it's still experimental and not supported in many browsers. https://developer.mozilla.org/en-US/docs/Web/API/VirtualKeyboard/geometrychange_event
const useIsOnScreenKeyboardOpen = () => {
const deviceType = useDeviceType();
const isMobile = deviceType === 'mobile';

const [isOpen, setOpen] = useState(false);

useEffect(() => {
const handleFocusIn = (e: FocusEvent) => {
if (!e.target) {
return;
}
const target = e.target as HTMLElement;
if (isMobile && isKeyboardInput(target)) {
setOpen(true);
}
};

document.addEventListener('focusin', handleFocusIn);

const handleFocusOut = (e: FocusEvent) => {
if (!e.target) {
return;
}
const target = e.target as HTMLElement;
if (isMobile && isKeyboardInput(target)) {
setOpen(false);
}
};

document.addEventListener('focusout', handleFocusOut);

return () => {
document.removeEventListener('focusin', handleFocusIn);
document.removeEventListener('focusout', handleFocusOut);
};
}, [isMobile]);

return isOpen;
};

export default useIsOnScreenKeyboardOpen;
Loading