Osy#betaRun it on Osyrin: osyrin.com

Reference / UI

WidgetGrid

WidgetGrid { Widget("Revenue", span: WidgetSpan.Two, editing: customising, onRemove: () => Hide("revenue")) { … } }

A workspace of cards — figures, charts and lists side by side on a four-column grid (two on a tablet, one on a phone), each a Widget with a title and a span. With editing on, each widget shows its tools (move it earlier or later, remove it), so a person arranges their own workspace; the order and the set are the page's to keep.

stable1 example compiled by CIuikitlayoutdashboard

Summary#

A dashboard is a set of answers a person checks at a glance, and the person checking them is the best judge of which they need. WidgetGrid lays Widgets on a four-column grid (two columns on a tablet, one on a phone); a widget takes one column, or WidgetSpan.Two, Three or Full. Turn editing on — Switch("Customise", value: editing) is the control for it — and every widget shows its tools (earlier, later, remove); the page keeps what the person chose.

[Route("/")] [Render(CSR)] [AllowAnonymous]
component Overview() {
  bool editing = false;
  List<string> hidden = [];
  action Hide(string key) {
    var next = new List<string>();
    foreach (var h in hidden) { next.Add(h); }
    next.Add(key);
    hidden = next;
  }

  render {
    Stack(gap: 4, p: 6) {
      PageHead("Overview") { Switch("Customise", value: editing); }
      WidgetGrid {
        if (!hidden.Contains("visits")) {
          Widget("Visits", subtitle: "today", editing: editing, onRemove: () => Hide("visits")) { Metric("visits", "1,208"); }
        }
        if (!hidden.Contains("orders")) {
          Widget("Orders", subtitle: "today", span: WidgetSpan.Two, editing: editing, onRemove: () => Hide("orders")) { Metric("orders", "64"); }
        }
      }
    }
  }
}

Signature#

WidgetGrid { Widget(…); … }
Widget(string title, string subtitle = "", WidgetSpan span = WidgetSpan.One, bool editing = false,
       Action onRemove = null, Action onEarlier = null, Action onLater = null) { <content> }
enum WidgetSpan { One, Two, Three, Full }

Description#

Where is the arrangement kept?#

Wherever the page keeps it — a field for a session, a stored row for good. Store it on a row and the customising is a real edit of the page's unit of work, so SaveActions beside the Customise button keeps or drops it like any other change (the command centre archetype does exactly that).

How wide is a span on a phone?#

Every span is one column below Tablet, two at most on a tablet, and as asked from Laptop up — a span never asks for more columns than there are.

How do I drive it in a test?#

Each widget is a region named by its title: Assert.Visible("1,208", within: "Visits"). While editing, its tools are Ui.Click("Remove Visits"), Ui.Click("Move Visits earlier") and Ui.Click("Move Visits later").

See also#

Related

Arrangements — five ways to build a whole app, and which look wears each

A look decides how an app's pixels read; an ARRANGEMENT decides how the app is built — where navigation lives, how a…

Save, discard, undo — three ways to show a page's unit of work

Every edit on a page joins the route's unit of work; how the page OFFERS to keep it is a choice of presentation…

The chart kit — line, column, bar, scatter and candle, with no JavaScript

Line, area, column, bar, scatter and OHLC candle marks over one shared value scale, plus a Pie — an optional KIT you…

Looks for business apps — start from a finished design and make it yours

Osysharp.Ui.Looks ships seven finished looks for any app built on the UI kit — Ledger, Relay, Civic, Studio, Signal…