Examples

Small documents, whole ideas.

Each example is a complete document. Run one in any host, change it, and save: the window follows.

Counter

Three buttons, three independent counters. State belongs to the call site, so each button keeps its own.

counter.masque
let button_colors = {
  content: { r: 33, g: 30, b: 25, a: 255 },
  border: { r: 134, g: 134, b: 145, a: 255 },
  background: { r: 255, g: 255, b: 255, a: 170 },
};

let button = fn (label: String) {
  state counter = 0;
  Flex {
    mouse_down: fn () {
      counter = counter + 1;
    },
    style: {
      width: 250,
      height: 44,
      direction: "row",
      main_alignment: "start",
      cross_alignment: "center",
      background_color: button_colors.background,
      border: {
        width: 2,
        color: button_colors.border,
        style: "solid",
      },
      padding: { top: 10, right: 12, bottom: 10, left: 12 },
      margin: { top: 6, right: 0, bottom: 6, left: 0 },
      corner_radius: 10,
    },
    children: [
      Text {
        text: label + " " + counter,
        style: {
          width: "grow",
          height: "shrink",
          align: "left",
          size: 18,
          color: button_colors.content,
        }
      },
    ],
  }
};

let main = fn () {
  Flex {
    style: {
      width: "grow",
      height: "grow",
      main_alignment: "center",
      cross_alignment: "center",
      direction: "column",
      padding: 24,
      gap: 12,
      background_color: {
        r: 30,
        g: 30,
        b: 30,
        a: 255,
      },
    },
    children: [
      button("Counter 1"),
      button("Counter 2"),
      button("Counter 3"),
    ],
  }
};

Conditional rendering

Widgets that come and go with state, using an if expression inside a children list.

conditional.masque
let button_colors = {
  content: { r: 33, g: 30, b: 25, a: 255 },
  border: { r: 134, g: 134, b: 145, a: 255 },
  background: { r: 255, g: 255, b: 255, a: 170 },
};

let counter_button = fn () {
  state counter = 0;
  Flex {
    mouse_down: fn () {
      counter = counter + 1;
    },
    style: {
      width: 250,
      height: 44,
      direction: "row",
      main_alignment: "start",
      cross_alignment: "center",
      background_color: button_colors.background,
      border: {
        width: 2,
        color: button_colors.border,
        style: "solid",
      },
      padding: { top: 10, right: 12, bottom: 10, left: 12 },
      margin: { top: 6, right: 0, bottom: 6, left: 0 },
      corner_radius: 10,
    },
    children: [
      Text {
        text: counter,
        style: {
          width: "grow",
          height: "shrink",
          align: "center",
          size: 18,
          color: button_colors.content,
        }
      },
    ],
  }
};

let button = fn (label: String, on_click: function) {
  Flex {
    mouse_down: on_click,
    style: {
      width: 250,
      height: 44,
      direction: "row",
      main_alignment: "start",
      cross_alignment: "center",
      background_color: button_colors.background,
      border: {
        width: 2,
        color: button_colors.border,
        style: "solid",
      },
      padding: { top: 10, right: 12, bottom: 10, left: 12 },
      margin: { top: 6, right: 0, bottom: 6, left: 0 },
      corner_radius: 10,
    },
    children: [
      Text {
        text: label,
        style: {
          width: "grow",
          height: "shrink",
          align: "left",
          size: 18,
          color: button_colors.content,
        }
      },
    ],
  }
};

let main = fn () {
  state counter_count = 0;
  Flex {
    style: {
      width: "grow",
      height: "grow",
      main_alignment: "center",
      cross_alignment: "center",
      direction: "row",
      padding: 24,
      gap: 16,
      background_color: {
        r: 30,
        g: 30,
        b: 30,
        a: 255,
      },
    },
    children: [
      Flex {
        style: {
          width: "grow",
          height: "shrink",
          direction: "column",
          main_alignment: "center",
          cross_alignment: "end",
          gap: 12,
        },
        children: [
          Text {
            text: "Showing " + counter_count + " counters.",
            style: {
              size: 18,
              color: { r: 255, g: 255, b: 255, a: 255 },
              width: "grow",
              align: "right",
            },
          },
          button("Add counter", fn () {
            counter_count = counter_count + 1;
          }),
          button("Remove counter", fn () {
            if counter_count > 0 {
              counter_count = counter_count - 1;
            }
          }),
        ],
      },
      Flex {
        style: {
          width: "grow",
          height: "shrink",
          direction: "column",
          main_alignment: "start",
          cross_alignment: "start",
          gap: 4,
        },
        children: for (i in 0..counter_count) {
          counter_button()
        },
      },
    ],
  }
};

Matching on state

The same idea with match. Passing callbacks as parameters keeps the button generic.

match.masque
let button_colors = {
  content: { r: 33, g: 30, b: 25, a: 255 },
  border: { r: 134, g: 134, b: 145, a: 255 },
  background: { r: 255, g: 255, b: 255, a: 170 },
};  

let button = fn (label: String, on_click: function) {
  Flex {
    mouse_down: on_click,
    style: {
      width: 250,
      height: 44,
      direction: "row",
      main_alignment: "start",
      cross_alignment: "center",
      background_color: button_colors.background,
      border: {
        width: 2,
        color: button_colors.border,
        style: "solid",
      },
      padding: { top: 10, right: 12, bottom: 10, left: 12 },
      margin: { top: 6, right: 0, bottom: 6, left: 0 },
      corner_radius: 10,
    },
    children: [
      Text {
        text: label,
        style: {
          width: "grow",
          height: "shrink",
          align: "left",
          size: 18,
          color: button_colors.content,
        }
      },
    ],
  }
};

let main = fn () {
  state view = "foo";
  Flex {
    style: {
      width: "grow",
      height: "grow",
      main_alignment: "center",
      cross_alignment: "center",
      direction: "column",
      padding: 24,
    },
    children: [
      match view {
        "foo" => {
          button("Foo", fn () {
            view = "bar";
          })  
        },
        "bar" => {
          button("Bar", fn () {
            view = "foo";
          })
        },
      },
    ],
  }
};

Anchored tooltip

A Portal seated at a point the host computes. The renderer keeps it on screen, with no edge arithmetic in the document.

anchored_tooltip.masque
// Anchored portals: chrome seated at a point the HOST computes.
//
// A Portal that names an `anchor:` takes its viewport origin from
// the host's anchor map instead of from the slot it was declared
// in. Paint, hit-testing, occlusion and nesting all follow, because
// the anchor resolves into the same viewport-absolute rect an
// unanchored portal computes.
//
// The host side of this file is one line per frame:
//
//     masque.set_anchor("cursor", Point::new(mouse_x, mouse_y));
//
// A previewer that does the same on every pointer move runs this
// file as-is: move the mouse and the card follows.
//
// Note what is NOT here: no edge arithmetic, no "am I near the
// bottom" branch, no measured card width. `anchor_policy` needs the
// subtree's laid-out size, which a document cannot see, so the renderer
// applies it after layout — that is the entire reason anchoring is
// a Portal property rather than a composition pattern.

let card = fn (title: String, body: String) {
  Flex {
    style: {
      direction: "column",
      width: 260,
      padding: 10,
      gap: 4,
      background_color: { r: 22, g: 22, b: 26, a: 242 },
      border: { width: 1, color: { r: 90, g: 90, b: 104, a: 255 } },
      corner_radius: 6,
    },
    children: [
      Text {
        text: title,
        style: { size: 15, color: { r: 236, g: 236, b: 242, a: 255 } },
      },
      Text {
        text: body,
        style: { size: 13, color: { r: 158, g: 158, b: 172, a: 255 } },
      },
    ],
  }
};

let main = fn () {
  Flex {
    style: {
      width: "grow",
      height: "grow",
      direction: "column",
      main_alignment: "center",
      cross_alignment: "center",
      gap: 8,
      background_color: { r: 14, g: 14, b: 17, a: 255 },
    },
    children: [
      Text {
        text: "Move the pointer — the card follows it.",
        style: { size: 16, color: { r: 222, g: 222, b: 230, a: 255 } },
      },
      Text {
        text: "Near the bottom edge it flips above the pointer; near the right edge it pulls back inside.",
        style: { size: 13, color: { r: 140, g: 140, b: 156, a: 255 } },
      },

      // The tooltip itself. `flip` reproduces the hand-rolled rule
      // every Skia tooltip in every host has re-implemented:
      // below-right of the pointer, above it when the card would
      // overrun the bottom of the window, always inside the sides.
      Portal {
        layer: "tooltip",
        open: true,
        anchor: "cursor",
        anchor_policy: "flip",
        anchor_offset: { x: 14, y: 22 },
        children: [
          card("Anchored", "layer: tooltip · policy: flip · offset: 14, 22"),
        ],
      },

      // The same anchor, a different policy. `clamp` never flips —
      // it only ever pulls the box back inside the 8 px inset — so
      // side by side the two make the flip rule visible.
      Portal {
        layer: "toast",
        open: true,
        anchor: "cursor",
        anchor_policy: "clamp",
        anchor_offset: { x: 14, y: -96 },
        children: [
          card("Clamped", "same anchor, policy: clamp"),
        ],
      },
    ],
  }
};