SharePoint / sp-dev-docs

SharePoint & Viva Connections Developer Documentation
https://docs.microsoft.com/en-us/sharepoint/dev/
Creative Commons Attribution 4.0 International
1.23k stars 992 forks source link

ComboBox and PeoplePicker controls are not rendering properly in SPFx when rendered inside a dialog window #9515

Open PaoloPia opened 5 months ago

PaoloPia commented 5 months ago

Target SharePoint environment

SharePoint Online

What SharePoint development model, framework, SDK or API is this about?

đŸ’„ SharePoint Framework

Developer environment

None

What browser(s) / client(s) have you tested

Additional environment details

Describe the bug / error

Starting from yesterday's afternoon (Feb 12 2024 afternoon CET) we have been experiencing rendering issues on multiple customers (4 so far) while rendering PeoplePicker and ComboBox lists of suggested values inside dialog windows of SPFx dialog framework. When you open the ComboBox to see the available values or when you type a user name to get the "Suggested People" option, the callouts render in background of the dialog and grayed out, rather than in foreground and with regular colors. As such, users cannot select values and all the SPFx customizations are broken.

image

Steps to reproduce

  1. Create a SPFx web part with a modal dialog
  2. Render a ComboBox (Fluent UI) or a People Picker (PnP Control, which internally relies on Fluent UI) inside the dialog window
  3. Try to open the ComboBox or the PeoplePicker, you will see the callout in background of the dialog

Expected behavior

Having the callout rendered properly on top of the dialog, so that users can select the suggested values. Thanks!

ghost commented 5 months ago

Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible.

StfBauer commented 5 months ago

Which Dialog are you using? A regular HTML <dialog> perhaps.

In this case the Combobox gets added behind the dialog.

The reason for this is that both, the input and the callout are rendered in two completely different place with a z-index that will be always lower than the one of HTML Dialog.

The callout gets rendered right before the </body> and moved with CSS positioning to the <input> field.

This behaviour is the same for all Fluent UI elements that has flyouts / callouts. it's a common issue with Fluent UI which case personally me to abondon it.

It's not a bug - It's a feature with Fluent UI.

PaoloPia commented 5 months ago

Hi @StfBauer, thanks for sharing your insights. Unfortunately, the issue that I'm describing here is something that was working like charm until Monday. As such, it must be something that changed recently and I'd love to find the issue and address it, rather than moving away from Fluent UI and SPFx Dialog Framework.

PaoloPia commented 5 months ago

Quick update about this issue. After some investigation, we realized that it occurs when you show more than one dialog in the UI of your custom SPFx web parts or extensions. In fact, if you show one dialog just once, it works. Starting from the second dialog instance that you show, the issue occurs. You need to refresh (F5) the page to reset the behavior.

AJIXuMuK commented 5 months ago

We're looking into it. F5 is the current workaround.

necik11 commented 5 months ago

Hello, It seems to me that previously the div was rendered directly into the div and now it is rendering 2 separate divs.

Anyway, it happens both with the Dialog component and with the Modal component, and when I spent the whole day fixing it - removing the dialogs and modals / using BaseDialog + making my own styles (I was forced to because customers were concerned about this problem) and everything seemed to work, I found out that the ContextualMenu doesn't work either... image

I report even this issue at fluentUI.

I thought it might be this PR : adds a context for active descendant But it's probably not the right time when stop working.

necik11 commented 5 months ago

Quick help - workaround: I had components in the Command Set that were inherited from BaseDialog as described here. That didn't work, so I created my own SPFX dialog that uses the dialog from fluentUI and not using extends BaseDialog. Everything now works as expected/before.

Here is the code:

Component:

import { Dialog, ProgressIndicator } from '@fluentui/react';
import * as React from 'react';
import * as ReactDOM from 'react-dom';

interface SPFXDialogProps {
    onClose: () => void;
    text: string;
}

// This is your custom component do whatever you want
const SPFXDialog: React.FC<SPFXDialogProps> = (props: SPFXDialogProps) => {
    return (
        <Dialog hidden={false}>
            bla bla
            <ProgressIndicator label={props.text} />
            <button onClick={props.onClose}>Close</button>
        </Dialog>
    );
};

export class SPFXDialogManager {
    // this is dialog container
    private domElement: HTMLDivElement | null = null;

    public async close(): Promise<void> {
        if (this.domElement) {
            ReactDOM.unmountComponentAtNode(this.domElement);
            this.domElement.remove();
            this.domElement = null;
        }
    }

    public async show(): Promise<void> {
        this.domElement = document.createElement('div');
        document.body.appendChild(this.domElement);

        const close = async (): Promise<void> => {
            await this.close();
        };

        const whateverYouWantPass = "";

        ReactDOM.render(
            <SPFXDialog
                onClose={close}
                text={whateverYouWantPass}
            />, this.domElement);
    }
}

Then in CA:

  public async onExecute(event: IListViewCommandSetExecuteEventParameters): Promise<void> {
  ...
    const dialogManager = new SPFXDialogManager();
    dialogManager.show().then().catch((e) => { console.log("error", e) });
    // In case you need close from here - close is public 
    dialogManager.close().then().catch((e) => { console.log("error", e) });   
  ...
  }
cwdata commented 4 months ago

Hi, same problem here. Will there be any solution soon? We're evaluating if we should wait for a fix or if we need to rewrite all of our components using other ways to display a dialog. An expected timeline would help. Thanks.