Widgets

All Available widgets

WidgetsBase.ButtonType
Button(name; style=Styles(), dom_attributes...)

A simple button, which can be styled a style::Styles.

Example

App() do
    style = Styles(
        CSS("font-weight" => "500"),
        CSS(":hover", "background-color" => "silver"),
        CSS(":focus", "box-shadow" => "rgba(0, 0, 0, 0.5) 0px 0px 5px"),
    )
    button = Button("Click me"; style=style)
    on(button.value) do click::Bool
        @info "Button clicked!"
    end
    return button
end
source
WidgetsBase.TextFieldType
TextField(default_text; style=Styles(), dom_attributes...)

A simple TextField, which can be styled via the style::Styles attribute.

Example

App() do
    style = Styles(
        CSS("font-weight" => "500"),
        CSS(":hover", "background-color" => "silver"),
        CSS(":focus", "box-shadow" => "rgba(0, 0, 0, 0.5) 0px 0px 5px"),
    )
    textfield = TextField("write something"; style=style)
    on(textfield.value) do text::String
        @info text
    end
    return textfield
end
source
WidgetsBase.NumberInputType
NumberInput(default_value; style=Styles(), dom_attributes...)

A simple NumberInput, which can be styled via the style::Styles attribute.

Example

App() do
    style = Styles(
        CSS("font-weight" => "500"),
        CSS(":hover", "background-color" => "silver"),
        CSS(":focus", "box-shadow" => "rgba(0, 0, 0, 0.5) 0px 0px 5px"),
    )
    numberinput = NumberInput(0.0; style=style)
    on(numberinput.value) do value::Float64
        @info value
    end
    return numberinput
end
source
Bonito.DropdownType
Dropdown(options; index=1, option_to_string=string, style=Styles(), dom_attributes...)

A simple Dropdown, which can be styled via the style::Styles attribute.

Example

App() do
    style = Styles(
        CSS("font-weight" => "500"),
        CSS(":hover", "background-color" => "silver"),
        CSS(":focus", "box-shadow" => "rgba(0, 0, 0, 0.5) 0px 0px 5px"),
    )
    dropdown = Dropdown(["a", "b", "c"]; index=2, style=style)
    on(dropdown.value) do value
        @info value
    end
    return dropdown
end
source
Bonito.CardFunction
Card(
    content;
    style::Styles=Styles(),
    backgroundcolor=RGBA(1, 1, 1, 0.2),
    shadow_size="0 4px 8px",
    padding="12px",
    margin="2px",
    shadow_color=RGBA(0, 0, 0.2, 0.2),
    width="auto",
    height="auto",
    border_radius="10px",
    div_attributes...,
)

A Card is a container with a shadow and rounded corners. It is a good way to group elements together and make them stand out from the background. One can easily style them via the above keyword arguments or via the style argument with any CSS attribute.

Example

    App() do
        Card(
            DOM.h1("This is a card");
            width="200px",
            height="200px",
            backgroundcolor="white",
            shadow_size="0 0 10px",
            shadow_color="blue",
            padding="20px",
            margin="20px",
            border_radius="20px",
            style = Styles(
                CSS("hover", "background-color" => "lightgray")
            )
        )
    end
source

This is a card

Bonito.StylableSliderType
StylableSlider(
    range::AbstractVector;
    value=first(range),
    slider_height=15,
    thumb_width=slider_height,
    thumb_height=slider_height,
    track_height=slider_height / 2,
    track_active_height=track_height + 2,
    backgroundcolor="transparent",
    track_color="#eee",
    track_active_color="#ddd",
    thumb_color="#fff",
    style::Styles=Styles(),
    track_style::Styles=Styles(),
    thumb_style::Styles=Styles(),
    track_active_style::Styles=Styles(),
)

Creates a Stylable Slider, where the basic attributes are easily custimizable via keyword arguments, while the more advanced details can be styled via the style, track_style, thumb_style and track_active_style arguments with the whole might of CSS. This does not use <input type="range"> but is a custom implementation using <div>s javascript, since it is not easily possible to style the native slider in a cross-browser way. For using pure HTML sliders, use Bonito.Slider.

Example

App() do
    Bonito.StylableSlider(
        1:10;
        value=5,
        slider_height=20,
        track_color="lightblue",
        track_active_color="#F0F8FF",
        thumb_color="#fff",
        style=Styles(
            CSS("hover", "background-color" => "lightgray"),
            CSS("border-radius" => "0px"),
        ),
        track_style=Styles(
            "border-radius" => "3px",
            "border" => "1px solid black",
        ),
        thumb_style=Styles(
            "border-radius" => "3px",
            "border" => "1px solid black",
        ),
    )
end
source

Widgets in Layouts

There are a few helpers to e.g. put a label next to a widget:

Bonito.LabeledFunction
Labeled(object, label; label_style=Styles(), attributes...)

A Labeled container with a simople layout to put a label next to an object.

App() do
    label_style = Styles(
        "color" => "white",
        "padding" => "3px",
        "font-size" => "1.5rem",
        "text-shadow" => "0px 0px 10px black, 1px 1px 3px black")
    slider = StylableSlider(1:10)
    Card(Labeled(slider, slider.value; label_style=label_style, width="auto"); backgroundcolor="gray")
end
source
1

To create more complex layouts, one should use e.g. Grid, and visit the Layouting tutorial.

App() do session
    s = Bonito.StylableSlider(0:10;)
    d = Dropdown(["a", "b", "c"])
    ni = NumberInput(10.0)
    ti = Bonito.TextField("helo")
    button = Button("click")
    clicks = Observable(0)
    on(session, button.value) do bool
        clicks[] = clicks[] + 1
    end
    return Card(Grid(
            button, Bonito.Label(clicks),
            s, Bonito.Label(s.value),
            d, Bonito.Label(d.value),
            ni, Bonito.Label(ni.value),
            ti, Bonito.Label(ti.value);
            columns="1fr min-content",
            justify_content="begin",
            align_items="center",
        ); width="300px",)
end
0
0
a
10.0 helo

Editor

This editor works in pure Javascript, so feel free to try out editing the Javascript and clicking eval to see how the output changes. In Bonito/examples/editor.jl, you will find a version that works with Julia code, but that requires a running Julia server of course.

using Bonito, Observables
src = """
(() => {
    const canvas = document.createElement("canvas");
    const context = canvas.getContext('2d');
    const width = 500
    const height = 400
    canvas.width = width;
    canvas.height = height;
    const gradient = context.createRadialGradient(200, 200, 0, 200, 200, 200);
    gradient.addColorStop("0", "magenta");
    gradient.addColorStop(".25", "blue");
    gradient.addColorStop(".50", "green");
    gradient.addColorStop(".75", "yellow");
    gradient.addColorStop("1.0", "red");
    context.fillStyle = gradient;
    context.fillRect(0, 0, width, height);
    return canvas;
})();
"""
App() do session::Session
    editor = CodeEditor("javascript"; initial_source=src, width=800, height=300)
    eval_button = Button("eval")
    output = DOM.div(DOM.span())
    Bonito.onjs(session, eval_button.value, js"""function (click){
        const js_src = $(editor.onchange).value;
        const result = new Function("return " + (js_src))()
        let dom;
        if (typeof result === 'object' && result.nodeName) {
            dom = result
        } else {
            const span = document.createElement("span")
            span.innerText = result;
            dom = span
        }
        Bonito.update_or_replace($(output), dom, false);
        return
    }
    """)
    notify(eval_button.value)
    return DOM.div(editor, eval_button, output)
end

Tailwinddashboard

Styles is preferred to style components, but Bonito also includes some Tailwind based components. They're from before Styles and will likely get removed in the future.

using Bonito
import Bonito.TailwindDashboard as D

function range_slider(orientation)
    range_slider = RangeSlider(1:100; value=[10, 80])
    range_slider.tooltips[] = true
    range_slider.ticks[] = Dict(
        "mode" => "range",
        "density" => 3
    )
    range_slider.orientation[] = orientation
    return range_slider
end

App() do

    button = D.Button("click")
    textfield = D.TextField("type in your text")
    numberinput = D.NumberInput(0.0)
    file_input = D.FileInput()
    on(file_input.value) do file
        @show file
    end
    slider = D.Slider("Test", 1:5)

    checkbox = D.Checkbox("check this", true)
    table = Bonito.Table([(a=22, b=33, c=44), (a=22, b=33, c=44)])

    source = """
    function test(a, b)
        return a + b
    end
    """
    editor = CodeEditor("julia"; initial_source=source, width=250, height=200, scrollPastEnd=false)
    dropdown = D.Dropdown("chose", ["option 1", "option 2", "option 3"])

    vrange_slider = range_slider(Bonito.WidgetsBase.vertical)

    hrange_slider = range_slider(Bonito.WidgetsBase.horizontal)


    return DOM.div(
        D.Card.([
            D.FlexRow(
                D.Card(D.FlexCol(
                    button,
                    textfield,
                    numberinput,
                    dropdown,
                    file_input,
                    slider,
                    checkbox,
                    class="items-start"
                )),
                D.Card(D.FlexCol(
                    D.Card(DOM.div(vrange_slider; style="height: 200px; padding: 1px 50px")),
                    D.Card(DOM.div(hrange_slider; style="width: 200px; padding: 50px 1px"),
                    )),
                )),
            D.FlexRow(
                D.Card.([

                    D.Card(table; class="w-64")
                    editor
                ])
            ),
        ])...
    )
end

chose

Test
1

check this

a b c
22 33 44
22 33 44