fluid

Fluid is a declarative library to build graphical user interfaces. Done the D way, the Fluid way.
These pages serve as the reference documentation for the library. For the time being, there are no recommended learning resources, but you can get a quickstart using the tour:
dub run fluid:tour
Import Fluid per module, or all at once:
import fluid;

General nodes

In Fluid, most things are accomplished with nodes. The most basic task a node can do is displaying text or providing interaction.
run(
    label("Hello, World!")
);

Layout nodes

A single node isn't very useful on its own — but nodes can be composed together. Using handy layout nodes like Frame or Space you can arrange other nodes on the screen. Use a NodeSlot to quickly switch between displayed nodes.
  • DragSlot can be dragged and rearranged by the user.
  • FieldSlot associates input with informative nodes, expanding hit regions.
  • Frame is a more general, styleable variant of space.
  • GridFrame creates a grid layout.
  • MapFrame places nodes in arbitrary positions.
  • NodeSlot wraps a node for quick replacement.
  • OnionFrame stacks nodes on top of each other (layers).
  • PopupButton is a handy shortcut for building dropdown menus.
  • PopupFrame displays outside of regular layout flow.
  • Space aligns nodes in a column or row.
  • ScrollFrame allows scrolling through a lot of content.
  • SwitchSlot (experimental) changes layouts for different screen sizes.
run(
    vspace(
        label("This text displays above"),
        label("This text displays below"),
    ),
);

Input nodes

Note: Documentation for this section is incomplete.
Get information from the user using input nodes.
  • Button is a clickable button.
  • Checkbox is a box that can be selected and deselected.
  • CodeInput is a code editor with syntax highlighting.
  • FieldSlot associates input with informative nodes, expanding hit regions.
  • NumberInput takes a number and does basic math.
  • PasswordInput takes a sensitive passphrase, without displaying it.
  • Radiobox allows selecting one out of multiple options.
  • ScrollInput is a bare scrollbar.
  • SizeLock restricts maximum size of a node for responsive layouts.
  • Slider selects one out of multiple values of a range.
  • TextInput takes text — a single line, or many.
TextInput name;
Checkbox agreement;
run(
    vframe(
        fieldSlot!vspace(
            label("Your name"),
            name = lineInput(),
        ),
        fieldSlot!hspace(
            agreement = checkbox(),
            label("I agree to the rules"),
        ),
        button("Continue", delegate { }),
    ),
);

Theming

Note: Documentation for this section is incomplete.
Fluid apps can be styled with a stylesheet.
import fluid.theme;

auto theme = Theme(
    rule!Frame(
        margin.sideY = 4,
        backgroundColor = color("#6abbe8"),
        gap = 4,
    ),
);

Tree actions

Note: Documentation for this section is incomplete.
Manipulate the node tree: search, modify, interact, automate, test, by hooking into tree events with Fluid's tree actions. Other tree actions are currently scattered across fluid.io.
auto ui = vspace(
    label("A tree action can click this button"),
    button("Click me!", delegate { }),
);
ui.focusChild()
    .then((Focusable child) => child
        .runInputAction!(FluidInputAction.press));

Your own nodes

Note: Documentation for this section is incomplete.
Extend a class from Node or any other Fluid node to extend Fluid's functionality. See fluid.node for a reference.
// Define your node's behavior with a Node class
class ColoredRectangle : Node {
    CanvasIO canvasIO;
    Vector2 size;

    override void resizeImpl(Vector2 space) {
        require(canvasIO);
        minSize = size;
    }

    override void drawImpl(Rectangle outer, Rectangle inner) {
        canvasIO.drawRectangle(inner,
            color("#600"));
    }
}

// Construct the node with a node builder
alias rectangle = nodeBuilder!ColoredRectangle;

Input and output

Note: Documentation for this section is incomplete.
Fluid does not communicate with the operating system on its own. To display content on the screen, and to take input from the keyboard and mouse, it uses a set of I/O nodes.

Transformation

Low-level

Nodes for unit testing and for specialized use-cases.
auto root = raylibStack(
    label("I'm displayed with Raylib!"),
);
while (!WindowShouldClose) {
    BeginDrawing();
    root.draw();
    EndDrawing();
}