microsoft / fluentui-blazor

Microsoft Fluent UI Blazor components library. For use with ASP.NET Core Blazor applications
https://www.fluentui-blazor.net
MIT License
3.63k stars 349 forks source link

feat: Add support for setting FluentDialog width as the max of two values #2456

Closed bitheadkdg closed 2 weeks ago

bitheadkdg commented 1 month ago

🙋 Feature Request

The goal of this feature is to allow a FluentDialog to be set to the maximum of two values. There are situations where we want the dialog to fill a majority of the width of the current browser window (ex: 95%), but not have the dialog be wider than some maximum value to improve readability of the contained dialog information (ex: no wider than 1300px).

🤔 Expected Behavior

For example, it should be possible to set the width of the dialog to be 95% or 1300px, whichever is less.

There are several possible ways this could be accomplished. Currently, if you set the width to 95% and then manually apply a style to the resulting div fluent-dialog[b-dsxskpj5rr]::part(control) such as "max-width: 1300px", this is nearly an adequate workaround. However, this is not easy since the element you need to style contains the unique Id which is not known prior to rendering.

😯 Current Behavior

Currently, the dialog only supports setting a single Width property using the DialogParameters.Width property.

💁 Possible Solution

One possible solution would be to add a property to the DialogParameters object called MaxWidth and have the dialog handle outputting this directly to the correct location.

Another option would be to add an additional class to the fluent-dialog div element when output so that it would be possible to write a rule using the Id (that can currently be assigned in DialogParameters). The rule would look something like: #myFluentDialog > .dialog-wrapper { max-width: 1300px; }

vnbaaij commented 1 month ago

There are several possible ways this could be accomplished. Currently, if you set the width to 95% and then manually apply a style to the resulting div fluent-dialog[b-dsxskpj5rr]::part(control) such as "max-width: 1300px", this is nearly an adequate workaround. However, this is not easy since the element you need to style contains the unique Id which is not known prior to rendering.

You should be able to replace the [unique id] in CSS by using the standard Blazor ::deep selector and target the ::part(control) that way.

I'm pretty sure this can be solved with a CSS only solution and we don't need to add any specific parameters for this.

MarvinKlein1508 commented 1 month ago

@vnbaaij this is more likely refereing to bootstrap like modal size classes. https://getbootstrap.com/docs/5.3/components/modal/#optional-sizes

I have this one on my list of good to have as well. Right now I'm achieving this by creating a custom modal component from scratch like this:


<FluentDialog Class="@Class" @ref="_dialog" @bind-Hidden="@Hidden" aria-label="Simple dialog" Modal="true" TrapFocus="true" PreventScroll="true" @ondialogdismiss="OnDismiss">
    <FluentDialogHeader ShowDismiss="ShowDismiss" Visible="ShowHeader">
        <FluentStack VerticalAlignment="VerticalAlignment.Center">
            <FluentIcon Value="@Icon" />
            <FluentLabel Typo="Typography.PaneHeader">
                @Title
            </FluentLabel>
        </FluentStack>
    </FluentDialogHeader>

    <FluentDialogBody Style="overflow-y: auto;">
        @if (!Hidden)
        {
            @ChildContent
        }
    </FluentDialogBody>

    <FluentDialogFooter Visible="ShowFooter" Class="justify-content-end">

        <FluentButton Appearance="Appearance.Accent" Autofocus="true" @onclick="Hide">Schließen</FluentButton>

    </FluentDialogFooter>

</FluentDialog>

@code {
    private FluentDialog _dialog = default!;

    private bool Hidden { get; set; } = true;

    [Parameter]
    public bool ShowFooter { get; set; } = true;
    [Parameter]
    public bool ShowHeader { get; set; } = true;
    [Parameter]
    public bool ShowDismiss { get; set; } = true;

    [Parameter]
    public string Class { get; set; } = "modal-xl";

    [Parameter]
    public string Title { get; set; } = string.Empty;
    [Parameter]
    public Icon Icon { get; set; } = new Icons.Regular.Size24.WindowApps();
    [Parameter]
    public RenderFragment ChildContent { get; set; } = default!;

    public void Show()
    {
        _dialog.Show();
    }

    public void Hide()
    {
        _dialog.Hide();
    }

    private void OnDismiss(DialogEventArgs args)
    {
        if (args is not null && args.Reason is not null && args.Reason == "dismiss")
        {
            _dialog.Hide();
        }
    }
}

And in my CSS:

/* Modals */
@media (min-width: 576px) {
    .modal {
        --dialog-width: 500px !important;
    }

    .modal-sm {
        --dialog-width: 300px !important;
    }
}

@media (min-width: 992px) {
    .modal-lg,
    .modal-xl {
        --dialog-width: 800px !important;
    }
}

@media (min-width: 1200px) {
    .modal-xl {
        --dialog-width: 1140px !important;
    }
}

.modal-fullscreen {
    --dialog-width: 100% !important;
    --dialog-height: calc(100dvh - 2px) !important;
    --layer-corner-radius: 0 !important;
}
vnbaaij commented 1 month ago

Ok, I'll look at this after the vacation period

vnbaaij commented 2 weeks ago

I don't see why this cannot be solved with standard CSS rules. Closing this for now. @MarvinKlein1508 showed how to have a working approach for this,

MarvinKlein1508 commented 2 weeks ago

@vnbaaij I would suggest to re-open this. My solution requires the user to embed a new Modal instance everytime. It would be really great if this library could support this feature out of the box. With variables which can be overritten if neccessary.

vnbaaij commented 2 weeks ago

I don't understand why you would need a new instance. The Dialog allows for a class to be specified. You showed how to define some classes with specific sizes. What more is needed?

MarvinKlein1508 commented 2 weeks ago

@vnbaaij providing a class via the dialogService.