Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A note about the DSL #1096

Open
MangelMaxime opened this issue Jan 11, 2025 · 2 comments
Open

A note about the DSL #1096

MangelMaxime opened this issue Jan 11, 2025 · 2 comments

Comments

@MangelMaxime
Copy link

Hello,

While looking online about Fabulous I stumbled on this fslang-suggestions - Allow dot notation after body of computation expression without need for parenthesis.

While reading the issue discussion it made me think about how Oxpecker solve a similar problem. Instead of using members after the CE, it use properties to set information inside of the "CE constructor".

This code

ContentPage(
    "Dashboard",
    ScrollView(
        (VStack() {
            Label("Hello, World!")
                .textColor(Color.Red.ToFabColor())

            Button("Click me!")
                .backgroundColor(Color.Blue.ToFabColor())
        })
            .margin(Thickness(10., 0.))
    )
        .verticalScrollBarVisibility(ScrollBarVisibility.Never)
)
    .hasNavigationBar(false)

could be something like

ContentPage(
    "Dashboard",
    ScrollView(
        VStack(margin = Thickness(10., 0.)) {
            Label("Hello, World!", textColor = Color.Red.ToFabColor())
            Button("Click me!", backgroundColor = Color.Blue.ToFabColor())
        },
        verticalScrollBarVisibility = ScrollBarVisibility.Never
    )
    navigationBar = false
)

I didn't test my code out as I just wanted to mention the idea

You can see some example of working code in Oxpecker repository:

@TimLariviere
Copy link
Member

Hey,

Thanks for the suggestion!

This is a really interesting approach - I hadn’t realized you could extend a type with properties and still use the object initialization syntax. That would indeed eliminate the issue with the extra parentheses.

That said, our current approach has a few advantages that I don’t think the properties approach can replicate.

One major benefit is that each extension member returns a new copy of the widget with the added modification. This makes it possible to have shared widgets that can be customized differently in various contexts. It’s particularly useful for "attached properties" (which affect parent layout), such as the grid example below.

type View with
    static member PrimaryButton(text: string, onClicked: 'msg) =
        Button(text, onClicked)
            .font(...)
            .textColor(...)
            .backgroundColor(...)
            .border(...)

Grid(...) {
    PrimaryButton(...)
        .height(42)
        .margin(0., 0, 24, 0)
        .gridRow(1)

    PrimaryButton(...)
        .gridRow(2)
        .gridColumn(1)
}

@MangelMaxime
Copy link
Author

One major benefit is that each extension member returns a new copy of the widget with the added modification.

Indeed, another advantage that I though about when writing this issue is that you can also support method overload when properties don't allow that. Could be emulated using constructor overload but the code would not be as ergonomic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants