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.3k stars 305 forks source link

fix: Setting panel size of FluentSplitter in code does not work after manually moving splitter bar #2029

Closed emetrix closed 3 weeks ago

emetrix commented 3 weeks ago

🐛 Bug Report

Setting a splitter panel size in code (e.g. mysplitter.Panel1Size = "250px";) works only as long as I do not move the splitter bar. Once I have resized the panels manually the code does not work any more. The call does not have any effect !

💻 Repro or Code Sample

n/a

🤔 Expected Behavior

Setting panel size in code should even work once the splitter bar has moved manually.

😯 Current Behavior

see bug report description.

💁 Possible Solution

🔦 Context

I'm trying to create a resizable FluentNavBar which should also be collapsible. For this I'm trying to adjust the first panel size in code if the NavBar should be collapsed or expanded.

🌍 Your Environment

dvoituron commented 3 weeks ago

Hi.

Did you tried the new MultiSplitter component?

https://www.fluentui-blazor.net/MultiSplitter

vnbaaij commented 3 weeks ago

This behavior is not really a bug but more a design choice we made when building the component. We use the PanelXSize parameters to set the initial width of the panels. Once you start moving the bar, you are manipulating those same values. The only way to go back to the original values is to reload the component (which is nor possible in Blazor) or reload the page (which is not what you want, I assume). As @dvoituron did, you may be able to achieve your desired behavior withe the MultiSplitter

emetrix commented 3 weeks ago

Thanks for the feedback. I've just tried to use FluentMultiSplitter. But setting Size property of a FluentMultiSplitterPane seem to have also no effect. The width of the pane does not change !? Should this be possible or am I missing something ?

dvoituron commented 3 weeks ago

Do you have an example of code ?

emetrix commented 3 weeks ago

Hi Denis,

please see the following quick and dirty snippet. If required I can also put together a full sample:

MainLayout.razor:

<FluentLayout>
    <FluentStack Class="main" Orientation="Microsoft.FluentUI.AspNetCore.Components.Orientation.Horizontal" Width="100%">
        <FluentMultiSplitter>

            <FluentMultiSplitterPane @ref="pane1" Size="@GetSideBarSize()" Min="100px" Max="500px">
                <SideBar @ref="sidebar" />
            </FluentMultiSplitterPane>

            <FluentMultiSplitterPane>
                <FluentBodyContent Class="body-content">
                    <div class="content">
                        @Body
                    </div>
                </FluentBodyContent>
            </FluentMultiSplitterPane>

        </FluentMultiSplitter>
    </FluentStack>
</FluentLayout>

@code {
  private FluentMultiSplitterPane pane1;
  private int temp = 250;

  private void MoveSplitterBar()
  {
      temp += 10;
      pane1.Size = temp.ToString() + "px";

      StateHasChanged();
  }

  private string GetSideBarSize()
  {
      return temp.ToString() + "px";
  }

}

Thank you.

dvoituron commented 3 weeks ago

@emetrix

  1. First of all, your example works until the user manually resizes the separator. From that moment on, the "internal" size replaces the defined value.

    Splitter-OK-Until

  2. To solve this problem, you need to "cancel" user resizing to continue using your Size value: using the following OnResize method. Another "detail" is that the OnResize event gives you the new size as a percentage (you can keep it or compute the equivalent pixel size).

    <FluentMultiSplitter OnResize="@OnResize" Height="100px">
        <FluentMultiSplitterPane Size="@(Size + "%")" Min="100px" Max="500px">
            Part1
        </FluentMultiSplitterPane>
        <FluentMultiSplitterPane>
            Part2
        </FluentMultiSplitterPane>
    </FluentMultiSplitter>
    <FluentButton OnClick="@(e => MoveSplitterBar())">Move</FluentButton>
    
    @code {
        double Size = 40; // Percentage
    
        void OnResize(FluentMultiSplitterResizeEventArgs e)
        {
            e.Cancel = true; // Cancel to use custom size
    
            if (e.PaneIndex == 0)
            {
                Size = e.NewSize;
            }
        }
    
        void MoveSplitterBar() => Size += 3;
    }

    Splitter-OK

emetrix commented 3 weeks ago

That sounds very promising. I'll try later today and send you my results. Just a quick thought: Do you think it makes sense to extend FluentMultiSplitterResizeEventArgs with the new sizes of the panes in pixels, too ? Or is that a very special case I have ? Because that would not need me to use JSInterop to get window dimension and recalculate percentage to pixels...

dvoituron commented 3 weeks ago

Just a quick thought: Do you think it makes sense to extend FluentMultiSplitterResizeEventArgs with the new sizes of the panes in pixels, too ?

It is not possible to manage these sizes using pixels, as the browser can be resized. When using percentages, these values remain unchanged, but when using pixels, these values change.

emetrix commented 3 weeks ago

That makes sense. I just thought at the time of the resize event the current sizes should be available in pixels. But I managed it to convert the percentage value in pixels.

emetrix commented 3 weeks ago

But I've noticed an issue: When using a collapsed FluentNavMenu in e.g. the left pane the fluent menu gets cut at the edge of panel1:

image

The tooltip is shown correctly:

image

vnbaaij commented 3 weeks ago

Try to do some experimentation with CSS styles content-visibility: visible; contain: style; That is what we use for the FluentCard content to break out of the card area.

emetrix commented 3 weeks ago

Hi Vincent, do you have a tip on which "element" the CSS styles you mentioned should be set ? Applying to fluent-menu and/or fluent-nav-menu had no effect.

vnbaaij commented 3 weeks ago

With the FluentCard we set it on the card element itself to have a select be able to 'escape' the card. Maybe you need to include the menu in a div with those styles set?

Not at a pc for a couple of days so can't look into it deeper.

Check https://www.fluentui-blazor.net/Card#arearestrictedexampl and the Card source for how it is done there

emetrix commented 3 weeks ago

I've tried several options using the mentioned classes - unfortunately without success. Maybe it's because of my very limited CSS skills... I would be thankful if you could have a look at it once you have some spare time. Thank you.

emetrix commented 1 week ago

Hi Vincent, do you think the mentioned issue in FluentUI webcomponents ( [Bug]: combobox dropdown not fully visible in datagrid row/cell #31359 ) does directly affect my issue ? Or do I need to raise some issue, too ?

vnbaaij commented 1 week ago

Not sure it is the same issue. Maybe better to raise an issue for this one as well.

emetrix commented 1 week ago

Thank you. I'm just confused how to do that at best because for me MultiSplitter seems to be a experimental component of your Blazor FluentUI library and not a official WebComponent control ?

vnbaaij commented 1 week ago

Yeah, that might complicate things a bit. Neither splitter not multi splitter are Fluent UI web components (but are web components).

I'm pretty it can be solved with CSS styling but not proficient enough to crack it.