telekom / scale

Scale is the digital design system for Telekom products and experiences.
https://telekom.github.io/scale/
Other
370 stars 82 forks source link

Stacking modal dialog cause problem with scroll page #2272

Closed matandre1 closed 7 months ago

matandre1 commented 7 months ago

Scale Version 3.0.0-beta.147

Framework and version Angular 17

Current Behavior Trigger open modal dialog but for some reason e.g. error dialog appears and set on the top of all other modals. Problem is that active focused modal is behind error dialog. When I start close dialogs scroll bar on page start toggle and when I close all modals scroll bar is hidden.

Expected Behavior If one or more modals are opened, scrollbar is hidden for page. When all modals are close scrollbar are visible again.

Code Reproduction Scale and Angular17

Desktop (please complete the following information):

Additional context I am observed that property overflow: hidden is toggle on html body when trigger or close modals.

felix-ico commented 7 months ago

Hi @matandre1 I'm not really sure I understand the issue and unfortunately I can't access the codesandbox, could you check if the link is correct and publicly accessible?

matandre1 commented 7 months ago

Hello @felix-ico problem is that when two modals are open and focused modal is in background, then scrollbar for page disappear when I close all modals.

Here is updated codesandbox

felix-ico commented 7 months ago

@matandre1 do you need to have allow-injecting-style-to-body="true" in your code? Removing that seems to fix the issue, even removing it from just one of the modals fixes the isse.

https://codesandbox.io/p/sandbox/stack-modals-bug-forked-jc48j3?file=%2Fsrc%2Fapp%2Fmodal.component.html

matandre1 commented 7 months ago

@felix-ico, I am not sure if it is a good approach. I would like to hide the scrollbar on the page if any modal is open. I am unable to specify which modal should have the attribute allow-injecting-style-to-body="true" or not. Therefore, if modals are open, the scrollbar is hidden, if no modals open scrollbar is visible and working.

christopherGdynia commented 7 months ago

To be honest, i am not sure if it was feature or not, that the modal turns scrolling on or off, but nextjs uses a div wrapper which needs the styles.

I implemented a few workarounds:

This React Component is placed inside my ModalWrapper:

export const InFullscreen = () => {
  useEffectOnce(() => {
    const elem = document.querySelector('#__next') as HTMLElement;
    const count = +(elem.dataset.modalCount ?? 0);
    elem!.style.height = '100vh';
    elem.dataset.modalCount = count + 1 + '';
    return () => {
      const count = +(elem.dataset.modalCount ?? 0);
      elem.dataset.modalCount = count - 1 + '';

      if (count < 2) {
        elem!.style.height = 'auto';
      }
    };
  });
  return null;
};
const Modal: FC<{
  show?: boolean;
  setShow: Dispatch<SetStateAction<boolean>>;
  style?: CSSProperties;
  heading: string;
  className?: string;
  onClose?: () => void;
}> = ({ children, heading, setShow, style, className, show, onClose }) => {
  return (
    <ScaleModal
      className={className}
      heading={heading}
      opened={show}
      onScaleClose={(e) => {
        e.preventDefault();
        e.stopPropagation();
        onClose?.();
        setShow(false);
      }}
      style={style}
    >
      {show && (
        <>
          <InFullscreen />
          {children}
        </>
      )}
    </ScaleModal>
  );
};
export default Modal;

Maybe you can implement it like this in angular.

I dont know if they implement something like this, but using different frameworks and stacks, this will get horrible to maintain.

They implemented it for the body element, but for next js I need to handle the root element.

 @Watch('opened')
  openedChanged(newValue) {
    if (newValue === true) {
      this.open();
      if (this.allowInjectingStyleToBody) {
        this.bodyOverflowValue = document.body.style.overflow;
        // The following style will disable body from scrolling when modal is open
        document.body.style.setProperty('overflow', 'hidden');
      }
    } else {
      this.close();
      if (this.allowInjectingStyleToBody) {
        // remove injected overflow style or set it to original value
        document.body.style.setProperty('overflow', this.bodyOverflowValue);
      }
    }
  }

UPDATE:

I am currently using beta.126 for 11 month and this workaround exists for 14 month, I honestly dont know, if the prop allowInjectingStyleToBody existed, when I build it.

Anyway, thats how it works for my usecases

felix-ico commented 7 months ago

@matandre1 would it be possible for you to use javascript and set that attribute conditionally (i.e. set allow-injecting-style-to-body to false if there is already an open modal in the page)?

matandre1 commented 7 months ago

@felix-ico yes, for now it is enough. Thanks for the help.