makeover-webview 0.98.4

The webview renderer for makeover-layout. Emits CSS, and is the one renderer that needs no palette: var() is the late binding, so resolution stays with the browser. With the build feature, writes a consumer's generated frontend files and checks the hand-written ones against them.
Documentation

makeover-webview

The webview renderer for makeover-layout. Emits CSS.

The renderer that needs no palette

makeover-immediate and makeover-tui both take a Palette, because egui and a terminal need an actual colour before they can put anything on screen. A webview does not. var(--surface-raised) is the late binding, and the browser resolves it against whatever the theme layer last wrote onto :root.

So this crate emits text naming intents and never learns a colour. It is also why the webview is the wrong renderer to derive a vocabulary from: it can express anything, so it never pushes back.

The stylesheet

stylesheet(&Emit) writes the component CSS: depths, controls, tokens, selectors, rows, tables, facets, meters, charts, figures and placeholders. An app that builds its own markup keeps every line of it and gains the classes.

:root {
    --bevel-raised: inset 1px 1px 0 var(--bevel-light), inset -1px -1px 0 var(--bevel-dark);
    --bevel-inset: inset 1px 1px 0 var(--bevel-dark), inset -1px -1px 0 var(--bevel-light);
}

.raised { background: var(--surface-raised); box-shadow: var(--bevel-raised); }
.well { background: var(--surface-well, var(--surface-page)); box-shadow: var(--bevel-inset); }
.button:active { background: var(--surface-well, var(--surface-page)); box-shadow: var(--bevel-inset); }

The depth classes are surfaces and nothing more, and the states belong to the named surfaces. .button is that same depth and a control, so it carries hover, press, focus and disabled. .card is a raised object, and carries those states only when it is written on a control: a.card, button.card, label.card, or a card with data-act. A card that is only read has no hover to cancel.

Hover rules are gated on the pointer density makeover-layout's Affordance and makeover-geometry answer for, never decided here, and every focus ring is the one focus_rule writes.

The markup

Each module renders one description member to markup, and each has a _into form that writes into a buffer the caller already has:

  • form::field_html renders a makeover_layout::Field: label, control, hint, error and note, marked aria-invalid and aria-describedby from the description itself.
  • list::cells_html renders a row's cells against its columns, and table holds the rules that narrow a table by column priority.
  • facet, meter, chart, figure and placeholder render the members of the same names.
use makeover_layout::{Field, FieldKind, Value};
use makeover_webview::{Emit, form::{Filling, field_html}};

let field = Field::new(FieldKind::Text, "title", "Title");
let html = field_html(&field, &Filling::of(Value::Text("Ship it")), &Emit::default());

Everything is escaped here. One escaper covers both text and attribute sinks, and the single hole is form::Markup, which a caller has to name. The copy the markup carries (the required marker, the exclude button's name, the markdown editor's modes) comes from Emit, English by default.

Numbers the rules read, such as a bar's value, ride in data-vars rather than style, so a page under a style-src without 'unsafe-inline' still draws them. Serve VARS_JS beside the stylesheet to apply them.

The _placed forms write the same bytes and also report where each part landed, for a caller compiling this markup into a template.

Substitution, three ways

A theme with no surface-well is answered differently by each of the three renderers, which is why substitution belongs to a renderer and not to the description:

  • makeover-immediate substitutes the page in Rust.
  • makeover-tui refuses to substitute and draws an edge, because a terminal quantises the two together.
  • here, CSS already has the mechanism. var(--surface-well, var(--surface-page)) falls back in the browser and nothing in Rust decides anything.

Status

On crates.io. A consumer takes it twice: as a dependency for the markup, and as a build-dependency with features = ["build"], whose build module writes the themes, the generated stylesheets and the font faces into an app's frontend and checks the hand-written CSS and JS against them. links keeps the two at one version. The build module was the makeover-build crate, which is retired.

Licence

MIT.