Styling and theming

Styling with RxTheme is no more relevant in MauiReactor where the reccomended way is using standard .NET classes and XAML resources

You can style components or widgets directly in C#, for example creating a library of reusable custom widgets as classes or functions. The below code uses a static function to return a customized button:

public static RxButton PrimaryButton(string text)
    => new RxButton(text)
        .BackgroundColor(ThemeColor.CommunicationCommunicationPrimary)
        .TextColor(ThemeColor.NeutralWhite)
        .BorderWidth(0)
        .CornerRadius(2)
        .Padding(5, 0);

NOTE: Styling thru XAML (Resources) is not currently supported

Theming

Another powerful way to style an entire page is using an RxTheme object. A theme provides an efficient way to style every control present in a page. For example consider we want to style an application with a Dark and Light theme, we could create 2 RxTheme:

public static class Theme
{
    public static RxTheme Light()
        => new RxTheme()
            .StyleFor<RxLabel>(_ =>
            {
                _.TextColor(Color.Black);
                _.Margin(0, 10);
            })
            .StyleFor<RxEntry>(_ =>
            {
                _.TextColor(Color.Black);
                _.Margin(0, 10);
                _.BackgroundColor(Color.White);
            })
            .StyleFor<RxButton>(_ =>
            {
                _.TextColor(Color.Black);
                _.Margin(10);
                _.BackgroundColor(Color.DarkGray);
            })
            .StyleFor<RxNavigationPage>(_ =>
            {
                _.BarBackgroundColor((Color)NavigationPage.BarBackgroundColorProperty.DefaultValue);
                _.BarTextColor((Color)NavigationPage.BarTextColorProperty.DefaultValue);
            })
            .StyleFor<RxContentPage>(_ =>
            {
                _.BackgroundColor((Color)ContentPage.BackgroundColorProperty.DefaultValue);
                _.Padding(10);
            });

    public static RxTheme Dark()
        => new RxTheme()
            .StyleFor<RxLabel>(_ =>
            {
                _.TextColor(Color.White);
                _.Margin(0, 10);
            })
            .StyleFor<RxEntry>(_ =>
            {
                _.TextColor(Color.Black);
                _.Margin(0, 10);
                _.BackgroundColor(Color.LightGray);
            })
            .StyleFor<RxButton>(_ =>
            {
                _.TextColor(Color.Black);
                _.Margin(10);
                _.BackgroundColor(Color.LightGray);
            })
            .StyleFor<RxNavigationPage>(_ =>
            {
                _.BarBackgroundColor(Color.DarkGray);
                _.BarTextColor(Color.White);
            })
            .StyleFor<RxContentPage>(_ =>
            {
                _.BackgroundColor(Color.Black);
                _.Padding(10);
            });
}

Now we can wrap any component/visual with these themes to automatically change its style:

public enum ThemeColor
{ 
    Dark,

    Light
}

public class MainPageState : IState
{
    public ThemeColor ThemeColor { get; set; } = ThemeColor.Light;
}

public class MainPage : RxComponent<MainPageState>
{
    public override VisualNode Render()
    {
        return new RxNavigationPage()
        {
            new RxContentPage()
            { 
                new RxStackLayout()
                { 
                    new RxLabel("Label"),
                    new RxEntry(),
                    new RxButton("Toggle Theme")
                        .OnClick(()=> SetState(s => s.ThemeColor = (s.ThemeColor == ThemeColor.Dark ? ThemeColor.Light : ThemeColor.Dark)))
                }
            }
            .Title("Theming")
        }
        .UseTheme(State.ThemeColor == ThemeColor.Dark ? Theme.Dark() : Theme.Light());
    }
}

This should be the final effect:

Last updated