Rendering pages
A page is built with the Ui library, not written as HTML. You compose static methods, each taking a closure for its content, and the library emits the markup, escapes your text, and gives every module the same look without a line of per-module CSS.
A page is a tree of calls
You describe a page as nested method calls rather than opening and closing tags by
hand. UiContent::Area opens a region; UiContent::Title and
UiContent::Text place a heading and copy; UiContent::Panel
groups related content; UiContent::Link and UiContent::Button
add navigation. Each call that has content takes a closure, and the calls inside that
closure become the content nested within it, so the shape of the code matches the shape
of the page:
UiContent::Area(function() {
UiContent::Title('Products');
UiContent::Text('Everything currently for sale.');
UiContent::Link('Add a product', '/shop/add');
});
There are no tags to close and no class names to remember. Because the text you pass is escaped for you, you never hand-escape a value or risk forgetting to.
Why declare instead of write markup
Building a page through the library rather than echoing HTML is one instance of the framework's wider declarative style: you state what the page should contain and let the library work out how to render it. That is the same principle behind routing and the other interfaces, and it is what lets the framework treat a page as data it can gather and, in future, emit for the front end from the same PHP. The full reasoning lives on its own page; see Declarative code.
The library groups, by what they build
The Ui library is organised into classes of static methods, each named for the kind of thing it produces:
UiContent: areas, panels, sections, titles, text, links, buttons, menus and images, the everyday page body.UiForm: text inputs, text areas, dropdowns, checkboxes, hidden and file inputs, and submit buttons.UiTable: headers, rows and typed cells for text, numbers, booleans, code and buttons.UiLayout: rows, columns, grids, stacks and sizing wrappers.UiCard,UiNavigationandUiTabs: cards and card lists, menus with navigation items, and horizontal or vertical tabs.UiHtmlandUiPage: the outer page, its title, description, styles and scripts.
The ready-made building blocks are covered next, in Components and widgets.
Styling comes from the library
UiThemeService generates the presentation from the library's own semantic
tags. You write the structure and the theme decides how it looks, so every module
renders with the same style and the pages of a whole site stay consistent. This is why
hand-written markup and invented class names do nothing here: the theme only knows the
library's tags, so any HTML you write by hand is unstyled and unmaintainable. When the
library cannot express something, the answer is to add a method to the Ui module, never
to drop down to raw HTML.
A page area with a form
A typical page section opens an area, adds a title and some text, then renders a form
with a few fields and a submit button. This mirrors the admin pages that ship with the
framework, where UiForm::ActionForm takes one closure for the fields and a
second closure that runs when the form is submitted:
UiContent::Area(function() {
UiContent::Title('Add product');
UiContent::Text('Enter a name and price to add a product.');
UiForm::ActionForm('shop_product_add', function() {
UiForm::Text('name', 'Name');
UiForm::Text('price', 'Price (pence)');
UiForm::Submit('Add');
}, function() {
Shop::AddProduct();
});
});
Handling that submission, validating the fields, and redirecting is the subject of Forms and input.
Next: Components and widgets.