diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.razor b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.razor index 3e58665974..75dc2e7f8e 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.razor +++ b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.razor @@ -1,140 +1,143 @@ -@namespace Bit.BlazorUI -@inherits BitComponentBase -@typeparam TItem - - - - - -@{ - var _selectedItem = Sticky ? SelectedItem : null; -} -
- - - @if (Split) - { - - - - } +@namespace Bit.BlazorUI +@inherits BitComponentBase +@typeparam TItem + + + + + +@{ + var _selectedItem = Sticky ? SelectedItem : null; +} +
+ + + @if (Split) + { + + + + }
-
+ class="bit-mnb-ovl @Classes?.Overlay">
+ +
+ +
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.razor.cs index 603afd16ee..1f51715736 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.razor.cs @@ -37,6 +37,12 @@ public partial class BitMenuButton : BitComponentBase where TItem : class /// [Parameter] public bool AriaHidden { get; set; } + /// + /// The background color kind of the callout. + /// + [Parameter, ResetClassBuilder] + public BitColorKind? Background { get; set; } + /// /// The value of the type attribute of the menu button. /// @@ -68,6 +74,11 @@ public partial class BitMenuButton : BitComponentBase where TItem : class [Parameter, ResetClassBuilder] public BitColor? Color { get; set; } + /// + /// Default value of the IsToggled parameter in toggle mode. + /// + [Parameter] public bool? DefaultIsToggled { get; set; } + /// /// Default value of the SelectedItem. /// @@ -93,6 +104,11 @@ public partial class BitMenuButton : BitComponentBase where TItem : class /// [Parameter] public string? IconName { get; set; } + /// + /// If true, removes the icon from the header button. + /// + [Parameter] public bool NoIcon { get; set; } + /// /// Determines the opening state of the callout. /// @@ -101,6 +117,12 @@ public partial class BitMenuButton : BitComponentBase where TItem : class [ResetClassBuilder, ResetStyleBuilder, TwoWayBound] public bool IsOpen { get; set; } + /// + /// Determines whether the header button is in the checked/toggled state when Toggle is enabled. + /// + [Parameter, ResetClassBuilder, ResetStyleBuilder, TwoWayBound] + public bool IsToggled { get; set; } + /// /// List of items to show in the menu button. /// @@ -126,6 +148,11 @@ public partial class BitMenuButton : BitComponentBase where TItem : class /// [Parameter] public EventCallback OnChange { get; set; } + /// + /// The callback that is called when the IsToggled value changes in toggle mode. + /// + [Parameter] public EventCallback OnToggleChange { get; set; } + /// /// Alias of the ChildContent. /// @@ -152,7 +179,8 @@ public partial class BitMenuButton : BitComponentBase where TItem : class /// /// If true, the selected item is going to change the header item. /// - [Parameter] public bool Sticky { get; set; } + [Parameter, ResetClassBuilder, ResetStyleBuilder] + public bool Sticky { get; set; } /// /// Custom CSS styles for different parts of the menu button. @@ -164,6 +192,12 @@ public partial class BitMenuButton : BitComponentBase where TItem : class /// [Parameter] public string? Text { get; set; } + /// + /// If true, enables the toggling behavior on the header button in split mode. + /// + [Parameter, ResetClassBuilder, ResetStyleBuilder] + public bool Toggle { get; set; } + /// /// The visual variant of the menu button. /// @@ -253,6 +287,8 @@ protected override void RegisterCssClasses() ClassBuilder.Register(() => Split ? "bit-mnb-spl" : "bit-mnb-nsp"); + ClassBuilder.Register(() => Toggle && Split && IsToggled ? $"bit-mnb-tgl {Classes?.Toggled}" : string.Empty); + ClassBuilder.Register(() => Variant switch { BitVariant.Fill => "bit-mnb-fil", @@ -267,6 +303,8 @@ protected override void RegisterCssStyles() StyleBuilder.Register(() => Styles?.Root); StyleBuilder.Register(() => IsOpen ? Styles?.Opened : string.Empty); + + StyleBuilder.Register(() => Toggle && Split && IsToggled ? Styles?.Toggled : string.Empty); } protected override async Task OnInitializedAsync() @@ -274,6 +312,11 @@ protected override async Task OnInitializedAsync() _calloutId = $"BitMenuButton-{UniqueId}-callout"; _overlayId = $"BitMenuButton-{UniqueId}-overlay"; + if (Split && Toggle && IsToggledHasBeenSet is false && DefaultIsToggled.HasValue) + { + await AssignIsToggled(DefaultIsToggled.Value); + } + if (Sticky && SelectedItemHasBeenSet is false && DefaultSelectedItem is not null) { await AssignSelectedItem(DefaultSelectedItem); @@ -536,6 +579,13 @@ private async Task HandleOnHeaderClick(TItem? item) await OpenCallout(); } + if (Toggle && Split) + { + if (await AssignIsToggled(!IsToggled) is false) return; + + await OnToggleChange.InvokeAsync(IsToggled); + } + if (item is not null) { if (GetIsEnabled(item) is false) return; @@ -643,7 +693,20 @@ private string GetItemKey(TItem item, string defaultKey) return GetKey(item) ?? $"{UniqueId}-{defaultKey}"; } - + private string? GetCalloutCss() + { + var openClass = IsOpen ? "bit-mnb-ocl" : null; + var bgClass = Background switch + { + BitColorKind.Primary => "bit-mnb-bpg", + BitColorKind.Secondary => "bit-mnb-bsg", + BitColorKind.Tertiary => "bit-mnb-btg", + BitColorKind.Transparent => "bit-mnb-brg", + _ => null + }; + var result = $"{openClass} {bgClass}".Trim(); + return result.HasValue() ? result : null; + } protected override async ValueTask DisposeAsync(bool disposing) { diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss index ed6c18c215..70180bd280 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss +++ b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss @@ -1,4 +1,4 @@ -@import "../../../Styles/functions.scss"; +@import "../../../Styles/functions.scss"; .bit-mnb { display: flex; @@ -12,8 +12,6 @@ border-width: $shp-border-width; border-style: $shp-border-style; border-radius: $shp-border-radius; - --bit-mnb-cal-opa: 0; - --bit-mnb-cal-tra: translateY(#{spacing(-1.25)}); &.bit-dis { cursor: default; @@ -71,14 +69,19 @@ } .bit-mnb-omn { - --bit-mnb-cal-opa: 1; - --bit-mnb-cal-tra: translateY(0); --bit-mnb-clr-opb-txt: var(--bit-mnb-clr-opb-txt-nsp); --bit-mnb-clr-opb-bg: var(--bit-mnb-clr-opb-bg-nsp); --bit-mnb-clr-chb-txt: var(--bit-mnb-clr-txt); --bit-mnb-clr-chb-bg: var(--bit-mnb-clr-active); } +.bit-mnb-tgl { + .bit-mnb-opb { + color: var(--bit-mnb-clr-txt); + background-color: var(--bit-mnb-clr-active); + } +} + .bit-mnb-nsp { --bit-mnb-clr-opb-txt-nsp: var(--bit-mnb-clr-txt); --bit-mnb-clr-opb-bg-nsp: var(--bit-mnb-clr-active); @@ -104,18 +107,25 @@ } .bit-mnb-cal { + --bit-mnb-cal-opa: 0; + --bit-mnb-cal-tra: translateY(#{spacing(-1.25)}); display: none; position: fixed; overflow: hidden auto; min-width: max-content; box-sizing: border-box; z-index: $zindex-callout; - background-color: $clr-bg-pri; opacity: var(--bit-mnb-cal-opa); box-shadow: $box-shadow-callout; transform: var(--bit-mnb-cal-tra); transition: opacity 100ms, transform 300ms; border-radius: 0 0 spacing(0.25) spacing(0.25); + background-color: var(--bit-mnb-cal-bg, #{$clr-bg-pri}); + + &.bit-mnb-ocl { + --bit-mnb-cal-opa: 1; + --bit-mnb-cal-tra: translateY(0); + } } .bit-mnb-cul { @@ -346,3 +356,20 @@ font-size: spacing(2.0); --bit-mnb-padding: #{spacing(1.0)} #{spacing(2.0)}; } + + +.bit-mnb-bpg { + --bit-mnb-cal-bg: #{$clr-bg-pri}; +} + +.bit-mnb-bsg { + --bit-mnb-cal-bg: #{$clr-bg-sec}; +} + +.bit-mnb-btg { + --bit-mnb-cal-bg: #{$clr-bg-ter}; +} + +.bit-mnb-brg { + --bit-mnb-cal-bg: transparent; +} \ No newline at end of file diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButtonClassStyles.cs b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButtonClassStyles.cs index 800ae295e1..8aebd5c1a2 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButtonClassStyles.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButtonClassStyles.cs @@ -7,6 +7,11 @@ public class BitMenuButtonClassStyles /// public string? Root { get; set; } + /// + /// Custom CSS classes/styles for the checked/toggled state of the BitMenuButton. + /// + public string? Toggled { get; set; } + /// /// Custom CSS classes/styles for the opened callout state of the BitMenuButton. /// diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/BitMenuButtonDemo.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/BitMenuButtonDemo.razor.cs index 88b94826ff..c80406d946 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/BitMenuButtonDemo.razor.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/BitMenuButtonDemo.razor.cs @@ -19,6 +19,15 @@ public partial class BitMenuButtonDemo Description = "If true, add an aria-hidden attribute instructing screen readers to ignore the menu button." }, new() + { + Name = "Background", + Type = "BitColorKind?", + DefaultValue = "null", + Description = "The background color kind of the callout.", + LinkType = LinkType.Link, + Href = "#color-kind-enum", + }, + new() { Name = "ButtonType", Type = "BitButtonType?", @@ -76,6 +85,13 @@ public partial class BitMenuButtonDemo Description = "Default value of the SelectedItem." }, new() + { + Name = "DefaultIsToggled", + Type = "bool?", + DefaultValue = "null", + Description = "Default value of the IsToggled parameter in toggle mode.", + }, + new() { Name = "HeaderTemplate", Type = "RenderFragment?", @@ -106,6 +122,13 @@ public partial class BitMenuButtonDemo Description = "Determines the opening state of the callout.", }, new() + { + Name = "IsToggled", + Type = "bool", + DefaultValue = "false", + Description = "Determines whether the header button is in the toggled state when Toggle is enabled.", + }, + new() { Name = "Items", Type = "IEnumerable", @@ -131,6 +154,13 @@ public partial class BitMenuButtonDemo Href = "#name-selectors", }, new() + { + Name = "NoIcon", + Type = "bool", + DefaultValue = "false", + Description = "If true, the icon of the header button is hidden.", + }, + new() { Name = "OnClick", Type = "EventCallback", @@ -143,6 +173,12 @@ public partial class BitMenuButtonDemo Description = "The callback that is called when the selected item has changed." }, new() + { + Name = "OnToggleChange", + Type = "EventCallback", + Description = "The callback that is called when the IsToggled value changes in toggle mode.", + }, + new() { Name = "Options", Type = "RenderFragment?", @@ -196,6 +232,13 @@ public partial class BitMenuButtonDemo Description = "The text to show inside the header of menu button." }, new() + { + Name = "Toggle", + Type = "bool", + DefaultValue = "false", + Description = "If true, enables toggle behavior on the header button in Split mode.", + }, + new() { Name = "Variant", Type = "BitVariant?", @@ -493,6 +536,13 @@ public partial class BitMenuButtonDemo DefaultValue = "null", Description = "Custom CSS classes/styles for the text of the BitMenuButton." }, + new() + { + Name = "Toggled", + Type = "string?", + DefaultValue = "null", + Description = "Custom CSS classes/styles for the toggled state of the BitMenuButton." + }, ], }, new() @@ -637,6 +687,39 @@ public partial class BitMenuButtonDemo private readonly List componentSubEnums = [ + new() + { + Id = "color-kind-enum", + Name = "BitColorKind", + Description = "Defines the color kinds available in the bit BlazorUI.", + Items = + [ + new() + { + Name = "Primary", + Description = "The primary color kind.", + Value = "0", + }, + new() + { + Name = "Secondary", + Description = "The secondary color kind.", + Value = "1", + }, + new() + { + Name = "Tertiary", + Description = "The tertiary color kind.", + Value = "2", + }, + new() + { + Name = "Transparent", + Description = "The transparent color kind.", + Value = "3", + }, + ] + }, new() { Id = "button-type-enum", diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor index d6b843a0a2..357aae21ba 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor @@ -1,4 +1,4 @@ - +
@@ -40,7 +40,280 @@
- + + + +
Experience the Sticky functionality of BitMenuButton, showcasing a button that remains sticky after an item selection. The button displays the selected item and retains its state for continuous user interaction.
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+ + +
Present BitMenuButton instances with customized icons, enriching the visual options for representing menu buttons.
+
+
+ + +
+
+ + +
Empower customization by overriding default styles and classes, allowing tailored design modifications to suit specific UI requirements.
+
+
Component's Style & Class:
+
+
+ + +
+


+
Item's Style & Class:
+
+
Non-Sticky:
+ +
+
Sticky:
+ +


+
Styles & Classes:
+
+
+ +
+ +
+
+ + +
Use the Background parameter to control the background color of the callout using BitColorKind values.
+
+
+ + + + +
+
+ + +
+ Enable toggle behavior on the header button in Split mode. Clicking the operator button toggles the IsToggled state, while the chevron button still opens the callout. +
+
+
Toggle:
+
+
+ +
+

+
DefaultIsToggled:
+
+
+ +
+

+
Two-way binding:
+
+
+ + +
+

+
OnToggleChange: @customToggledValue
+
+ +
+ + +
Use the NoIcon parameter to hide the header icon of the menu button.
+
+
+ + +
+
+
+ + +
+
+ + +
Explore BitMenuButton's customization capabilities.
+
Note that if Sticky set to true, HeaderTemplate and Text will be ignored.
+
+
HeaderTemplate
+ + +
+ Custom Header! +
+
+
+

+
ItemTemplate
+ + +
+ @item.Name (@item.Id) +
+
+
+

+
Item's template
+ +
+ + +
Demonstrate BitMenuButton instances highlighting item click events, offering versatile interactions within the menu buttons.
+
+
+
Non-Sticky
+
+ + + +
+

+
Sticky
+
+ + + +
+
+

+
Changed custom item: @eventsChangedCustom
+
Clicked custom item: @eventsClickedCustom
+
+ + +
This example demonstrates different ways to handle item selection and changes within the component.
+



+
+
DefaultSelectedItem:
+
+ +
+



+
+
Two-way SelectedItem:
+
+ + +
+



+
+
Item's IsSelected:
+
+ +
+



+
One-way IsOpen (closes after 2 seconds):
+
+
+ + +
+



+
Two-way IsOpen:
+
+
+ + +
+
+ + +
External icon libraries like FontAwesome can be used with the Icon parameter.
+ +
+
+ + + +
+ + +
+ +
+
+ +
+ + +
+ +
+
+ +
+ + +
+
+ +
Offering a range of specialized color variants with Primary being the default, providing visual cues for specific actions or states within your application.


@@ -250,7 +523,7 @@
- +
Varying sizes for menu buttons tailored to meet diverse design needs, ensuring flexibility and visual hierarchy within your interface.

@@ -272,229 +545,12 @@
- -
Experience the Sticky functionality of BitMenuButton, showcasing a button that remains sticky after an item selection. The button displays the selected item and retains its state for continuous user interaction.
-
-
- - -
-
-
- - -
-
-
- - -
-
- - -
Present BitMenuButton instances with customized icons, enriching the visual options for representing menu buttons.
-
-
- - -
-
- - -
Empower customization by overriding default styles and classes, allowing tailored design modifications to suit specific UI requirements.
-
-
Component's Style & Class:
-
-
- - -
-


-
Item's Style & Class:
-
-
Non-Sticky:
- -
-
Sticky:
- -


-
Styles & Classes:
-
-
- -
- -
-
- - -
Explore BitMenuButton's customization capabilities.
-
Note that if Sticky set to true, HeaderTemplate and Text will be ignored.
-
-
HeaderTemplate
- - -
- Custom Header! -
-
-
-

-
ItemTemplate
- - -
- @item.Name (@item.Id) -
-
-
-

-
Item's template
- -
- - -
Demonstrate BitMenuButton instances highlighting item click events, offering versatile interactions within the menu buttons.
-
-
-
Non-Sticky
-
- - - -
-

-
Sticky
-
- - - -
-
-

-
Changed custom item: @eventsChangedCustom
-
Clicked custom item: @eventsClickedCustom
-
- - -
This example demonstrates different ways to handle item selection and changes within the component.
-



-
-
DefaultSelectedItem:
-
- -
-



-
-
Two-way SelectedItem:
-
- - -
-



-
-
Item's IsSelected:
-
- -
-



-
One-way IsOpen (closes after 2 seconds):
-
-
- - -
-



-
Two-way IsOpen:
-
-
- - -
-
- - -
External icon libraries like FontAwesome can be used with the Icon parameter.
- -
-
- - - -
- - -
- -
-
- -
- - -
- -
-
- -
- - -
-
- - +
Use BitMenuButton in right-to-left (RTL).

- +
diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.cs index ab0b805ed3..4335d7b18e 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.cs @@ -5,6 +5,9 @@ public partial class _BitMenuButtonCustomDemo private string? eventsChangedCustom; private string? eventsClickedCustom; + private bool customIsToggled; + private bool customToggledValue; + private Operation twoWaySelectedCustom = default!; private bool oneWayIsOpen; diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cs index 62f08f2ef3..76fe5c59dc 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cs @@ -94,7 +94,7 @@ public class Operation IsEnabled = { Selector = m => m.Disabled is false } };"; - private readonly string example4RazorCode = @" + private readonly string example15RazorCode = @" @@ -246,7 +246,7 @@ public class Operation "; - private readonly string example4CsharpCode = @" + private readonly string example15CsharpCode = @" public class Operation { public string? Id { get; set; } @@ -270,7 +270,7 @@ public class Operation IsEnabled = { Selector = m => m.Disabled is false } };"; - private readonly string example5RazorCode = @" + private readonly string example16RazorCode = @" @@ -282,7 +282,7 @@ public class Operation "; - private readonly string example5CsharpCode = @" + private readonly string example16CsharpCode = @" public class Operation { public string? Id { get; set; } @@ -306,7 +306,7 @@ public class Operation IsEnabled = { Selector = m => m.Disabled is false } };"; - private readonly string example6RazorCode = @" + private readonly string example4RazorCode = @" @@ -315,7 +315,7 @@ public class Operation "; - private readonly string example6CsharpCode = @" + private readonly string example4CsharpCode = @" public class Operation { public string? Id { get; set; } @@ -339,10 +339,10 @@ public class Operation IsEnabled = { Selector = m => m.Disabled is false } };"; - private readonly string example7RazorCode = @" - -"; - private readonly string example7CsharpCode = @" + private readonly string example5RazorCode = @" + +"; + private readonly string example5CsharpCode = @" public class Operation { public string? Id { get; set; } @@ -366,7 +366,7 @@ public class Operation IsEnabled = { Selector = m => m.Disabled is false } };"; - private readonly string example8RazorCode = @" + private readonly string example6RazorCode = @"