Skip to content

REDZ.UI 0.19.0

Choose a tag to compare

@github-actions github-actions released this 08 Nov 14:29
· 13 commits to main since this release
Immutable release. Only release title and notes can be modified.

Added

  • A banner for a state of the whole system, app-banner with the tones app-banner-info (the default),
    app-banner-success, app-banner-warning and app-banner-danger: the first row of app, above its header, across
    the window and sticky with the header under it; first in the body of a page without the shell; off paper.
    REDZ.ui.banner({tone, text}) shows the one banner or replaces it, and answers a function that removes it;
    REDZ.ui.banner(null) removes it. The same tone and words again change nothing and say nothing, so a page may call it
    on every answer of its server. The words are said once, politely, at once for danger. Its height goes to
    --redz-app-banner-height on the root, which the header, the side navigation, --redz-sticky-top and the scroll
    padding add.

  • redz-ui-tools-<version>.zip in every release: the tools a project runs on its own server and never serves, each
    the very file the release was built and checked with - floor.php, the browser floor checker, with its list
    floor.json, and min.php, the minifier -, PHP 8.4 or newer with no extension, no network, and their passport
    redz-ui-tools.json: the PHP they need, the file of each tool and the sha256 of every file. tools/dist/ of the tag,
    written by php tools/build.php; the Check workflow runs both on PHP 8.4 with no extension loaded.

  • The floor checker for a project: php floor.php check [--allow=FILE] [--json] FILE…, a finding a line on standard
    output and the summary on standard error, exit 0 clean, 1 findings, 2 for anything else; --json prints the findings
    as objects. An exception of a project's own carries its reason: /* floor-allow NAME[, NAME…] -- reason */ covers its
    lines and the next one, --allow=FILE a set of files; one that allows nothing is a finding. It applies the release's
    exceptions of scope any only.

  • The minifier for a project: MIN__JsBlocks([$label => $js, …]) joins classic scripts, each in a block of its own, for
    one ES module, and refuses what reads otherwise there - a static import or export, a var or a function declared
    outside any function, this outside any function but an arrow, with, an HTML-like comment, a legacy octal number or
    escape; MIN__SelfTest() gives the samples it proves itself on that misfire. A class's private names #name are read.

  • Outside judges of the minifier on every commit, php tools/judge.php: Lightning CSS reprints every stylesheet it
    squeezes, the library's and the css-tokenizer-tests corpus, as written and as squeezed, which must read the same;
    esbuild parses every script it writes for the browser floor; a watch on the size of the two main files against esbuild
    --minify. Both are native binaries from npm, pinned by version and sha512.

  • The passport names the arguments of every text: args beside texts and plurals, and editor.args beside
    editor.texts, give each key the {names} the library fills in it, [] for none, ["count"] for a count. They
    are read from the scripts' calls, and the build fails when two calls of one key pass different names or the
    library's own English text of a key uses other names than its calls pass.

  • A combination that a button's or a link's aria-keyshortcuts names is the page's even while none of them can be
    pressed: disabled, busy, hidden, inert or outside the open modal, it never reaches the browser, so a page's save keeps
    Ctrl S from the browser's own save while it saves or has nothing to save. The first that can be pressed is pressed.

  • A password field tells the page each time its text is shown or hidden, by the person or on its form's submit or the
    page's return from the history: redz:reveal bubbles from it, detail.revealed true or false.

  • data-ago="short" on a ticking time says how long ago it was in the short words of the page's language ("42 min.
    ago", "42 мин. назад") for a narrow place such as a stat tile; data-ago alone keeps the long words.

  • Filter buttons: a button with command="--filter" and aria-controls naming a region shows only the items whose
    data-NAME holds a word of its value - NAME is the button's name, state without one. The buttons of one name
    are one choice, value="" shows all, and pressing the pressed one again shows all; names narrow together and with the
    search field. data-filter-count counts: in a button its items, in a data-filter-group the group's, with a region's
    id the page's text filter.count. A data-filter-group hides while none of its items shows. A press says the count;
    the region fires redz:filter with {count, total}; items the page puts in or changes are filtered again.
    REDZ.ui.filter(region, {name: value}) chooses from code and answers the count, null clears. Any element with a
    data-search is an item, and a table row matches its band's label too.

  • A search on the server: a field with data-filter-server fires redz:search with {query, form, signal} on the
    field 600 ms after the typing pauses, at once on Enter and Escape and when another control of its <search> or form
    changes; answered with a promise, the region is aria-busy and a field in a form-adorn shows a ring, a newer
    question aborts the one before and a late answer is dropped, and the count is said - the answer's count, else the
    items there are.

  • Show more: a button with command="--more" and aria-controls naming a list fires redz:more with {shown, signal} on the list; answered with a promise, the button is busy, then the focus goes to the first new item and the
    page's text more.loaded says how many came. The answer may say {total} or {done: true}; data-more-total is a
    total known from the start, data-more-max a cap whose data-more-cap sentence takes the button's place, and a
    data-more-count reads more.count ("10 of 23") or more.some ("10+"). list-more is the row under a list that
    holds them. A server search over the list starts it again.

  • Selection: an element with data-select holds a selection; a check with data-select-all heads its checks (or those
    of the scopes its aria-controls names) - checked, mixed or clear, and pressed it checks or clears them all. Only
    enabled checks in items a filter shows count: a checked row a filter hides leaves the count while hidden and is
    checked again when shown. A selection-bar inside hides at zero, a data-select-count says the page's text
    selected, and the scope fires redz:selection with {count, total, values}. data-select="rows" checks a row
    clicked anywhere but on its controls; a data-select inside another is a group; command="--select-all" and
    "--select-none" buttons do what a head does.

  • Sorting in place: a table-sort button with a value sorts its table's rows by each row's data-sort-VALUE, else
    the cell's data-sort-value, else its text - numbers as numbers, words in the page's language, an empty value last
    both ways, ties in the drawn order, a band's rows under it with its subtotal last. data-sort-first="descending"
    starts the other way; data-sort-reset on the table makes a third press bring back the drawn order. The page's texts
    sort.ascending, sort.descending and sort.none say it. The table fires the cancelable redz:sort with {key, direction} first, for a page that sorts itself; rows the page puts in are sorted the same, and REDZ.ui.sort(table)
    sorts again.

  • A question that waits for the server: REDZ.ui.confirm({..., run}) carries the answer out before the dialog closes -
    run({choice, phrase, signal}) answers a promise; meanwhile OK is busy, the other buttons unavailable, the body inert,
    Escape and a click outside held. Refused with words, a danger alert with them stands right above the footer, said at
    once, the buttons wake and the focus stays on OK. A dialog closed by code meanwhile aborts the signal, and a later
    refusal is a danger toast. choice: {label, items: [{value, text, hint}], value} puts radios above the phrase, and
    the answer is then the chosen value. A dialog of the page's own waits the same way: a form[method="dialog"] fires
    the cancelable redz:save with {form, data, submitter, signal} on its submit.

  • A third answer: REDZ.ui.confirm({..., alt: {text, tone, value}}) puts a button at the footer's start - Discard
    beside Stay and Save - that answers its value; focus: 'ok' or 'alt' starts the focus there instead of on Cancel.
    dialog-footer-start is that place in any footer, and a footer of three buttons in a dialog narrower than 368 px
    stacks them full width, the confirming one on top.

  • REDZ.ui.alert(box, {tone, text}) fills a box with an alert of the tone, its icon and the words, and says them -
    politely, at once for danger, the same words again said again; null empties it; a promise shows the page's text
    busy past 400 ms, then what it answers or its rejection. No live role on the box.

  • REDZ.ui.status(line, {tone, text, keep: true}) keeps a success or an info in the line.

  • A text download: command="--download" naming a field, a textarea or any element downloads its value or its text,
    data-file, data-type; a text/csv file starts with a UTF-8 byte order mark unless data-bom="false".
    REDZ.ui.download({text, file, type, bom}) or ({blob, file}) does it from code. Each download is said, in the
    page's text downloaded.

  • busy() on an item of a menu holds the button that opened the menu busy too, the outermost one for a menu inside a
    menu. A region's data-busy shows its words under the spinner and says them instead of busy. Any other element - a
    cell that checks - shows a small ring after 400 ms and, for a screen reader, the words of its data-busy or busy,
    saying nothing aloud.

  • Contents loaded the first time they show: data-lazy on a details or its accordion-body, a region a --toggle
    button opens, a tab panel or a tree's group fires redz:load with {region} when it first shows - open at load, put
    in open later, or opened by a person, never for the paper. Answered with a promise, an empty region shows three
    placeholder lines; a refusal shows its words in the region, which stays open, and the next opening tries again.
    data-lazy written again on a region that shows loads it again.

  • Uploads: data-paste="page", or an element's id, takes files pasted anywhere on the page or in that element - a paste
    of words into a text field stays words, the one in the open modal or the one that shows takes them.
    REDZ.ui.upload.clear(upload), and the form's reset, takes away the files not yet stored, their sending aborted;
    REDZ.ui.upload.settled(upload) answers once nothing sends. redz:change adds pending and failed, and while a
    file sends the file field is invalid with the page's text file.pending.

  • data-follow on any element that scrolls keeps its end in view while its contents come in or grow, a ResizeObserver
    on it and its children; data-follow="current" keeps its child with aria-current in view at the nearest edge with a
    step's room beside it. A command="--follow" button naming it shows while the reader is away and something new came
    in, and brings the end back; follow-dock floats it at the middle of the box's bottom.

  • action-bar, a sticky bar at the bottom of the window on the page's tinted floor, with action-bar-text: across its
    region, clear of a phone's home bar, aside on a touch screen while a field has the focus, off paper.

  • A list group's item whose title is a stretched-link is a link as a whole by script, as a table's row: its words stay
    selectable, and Ctrl, Cmd or the middle button open a new tab. list-group-actions holds its buttons, dimmed until the
    item is pointed at or focused.

  • The package redz-ui-qr, js/redz-ui-qr.min.js in packages.qr: draws the QR code of a text into a qr tile as one
    SVG path that traces each dark region, so no seam shows on paper or at any zoom - data-qr, data-qr-level (L,
    M by default, Q, H) and data-qr-quiet (4) in the markup, or REDZ.ui.qr(tile, text, {level, quiet}) for a
    text such as a secret that should sit in no attribute, null to empty it. Byte mode UTF-8, versions 1 to 40, the
    level raised for free when the same version holds more; the tile is role="img", named by the page; a text too long
    empties the tile, marks it data-qr-error and hides it. Built without innerHTML or a style attribute, so a
    strict CSP with Trusted Types passes. A module never falls under 3 px (--redz-qr-module-min): the tile grows.

  • logo, a white mat for someone else's logo in both themes, with a border: 32 px high, logo-sm 28 and logo-lg 40,
    an h-* utility for a banner (h-88 added), and as wide as its logo asks - data-ratio, its width by its height,
    widens it by the ratio to the power 0.75, from square to four times as wide, and the picture fills 90 by 80 % of it.
    data-color grounds a logo drawn on a solid color, logo-fade softens its sides into it, and an img.logo-ground is
    a blurred copy behind a photo; choice-media takes the same, a logo there as high as the banner over the fourth root
    of its ratio, so a 4:1 wordmark gets 70 % of the height and stays readable.

  • Share links for X (share-x), Viber (share-viber, its letters drawn as VK's are) and WeChat (share-wechat, a plain
    button for the page's popover with a QR code); data-share-url and data-share-title on any element write the
    share links and copies inside it - a row of buttons without a menu.

  • A text token per tone, --redz-TONE-text: where a tone is text - a subtle badge, an outline or subtle button,
    text-TONE, an alert's icon, a form's and a log's tone - it reads it. It is the tone itself, and under data-brand
    the brand darkened in the light theme, its hue kept, to a luminance of 0.13 at most, so it reads at 4.5:1 on white
    and on its subtle fill. data-brand-secondary, -success, -info, -warning and -danger derive their tones the
    same way, each with its -subtle, -contrast and -text.

  • meter meter-stacked, a meter of several parts on a div role="meter": each child's data-v its share of the scale,
    data-tone its color, 2 px apart; a part with data-over is hatched red, readable without its color.

  • Charts: chart chart-line draws one series as an SVG line with its area under it, behind the rows that keep their
    tooltips and mark their point under the pointer; spark-line draws a sparkline as a line; spark-strip in a strip
    fills its box with a cell a day in its state's tone - 90 days, 60 below 560 px, 30 below 360 px, the oldest going
    first - and the strip-head caption with the data-days shown is the one that shows.

  • command-line, a command to copy in one frame: one line that scrolls under a fade at its cut edge, never under the
    copy button in its own column, left to right on any page, selected whole by a click; a var is an amber chip of a
    part the person puts in. command-steps numbers commands run one after another in circles; a --copy naming the
    list copies them all, a line each, and one inside a command-line without a target copies its command.

Changed

  • card-img-overlay lays its words in white on a shade that rises from the bottom of the picture, and its links turn
    white with them: the words kept the text's color, so on a phone dark words stood on dark water. A card-img under an
    overlay fills its card, so a card a grid stretches stays a picture instead of a picture over a white end.
  • A table row whose table-check box is checked is tinted, as a row with aria-selected="true" is.
  • A tree's group with data-lazy asks the page by redz:load, as every region that loads, instead of redz:expand
    (no page listened for it); a refusal now leaves the group open with the page's words instead of closing it.
  • A list group's item follows data-density: 12 px by default, 8 compact, 16 comfortable, 20 spacious.
  • data-follow is read by js/follow.js, which replaces js/log.js.
  • The link follows the primary tone's text token: under a light data-brand it stays readable.
  • A chart's first and last day labels are found by type, so a line drawn among the rows does not move them.
  • The budgets: the main stylesheet at most 38 KB and the main script 42 KB, gzipped.
  • floor.json carries, for each name that falls short at the floor, its BCD key, and for each vendor form the browsers
    that take it; its exceptions carry their scope and, for a key, the names under it. The verdict prefix -webkit- gives
    way to the browsers of "-webkit-".
  • Every exception of tools/floor/rules.json has a scope: any for an engine's own fact, library where the library's
    own code stands in - js/menu-place.js places only the library's menus and tooltips.
  • The library's floor gate, tools/floor.php, judges through the checker each release ships and by floor.json, and
    runs that checker on its command line on every commit.
  • A refusal of the minifier names the byte and the line of the text it was given, with the code around it, and has the
    byte as its code; a fault of its own proof is a LogicException.
  • The floor gate and the minifier read bytes without the ctype and mbstring extensions: on macOS ctype read bytes by the
    locale, so a byte such as 0xA0 counted as a space there and not on Linux.

Fixed

  • The minifier no longer hangs on a stylesheet that ends in a \; it refuses it (since 0.4.0).
  • The minifier refuses a script with a string, a pattern, a template or a comment that runs to its end, and a string or
    a pattern that runs past its line, instead of failing in its own proof.
  • A table's head sticks at the top of a page without the shell, or under a page's own bar by --redz-sticky-top. It held the shell header's
    height everywhere, so a table at the top of such a page had its head over its first row.
  • A menu, popover or dialog inside a th takes the size, weight and color of the page's text, not the head's.
  • A group's end slot table-group-end in a table wider than its table-scroll, as on a phone, stays at the scroller's
    visible end, over a label that runs under it. It stood at the far end of the band, out of sight until scrolled there.
  • A table-group band in a table-scroll-first or table-scroll-last keeps its own background and no line: it took
    the held column's background, line and stickiness.
  • A search field over a table with groups keeps a group's table-group band and table-subtotal while a row of the
    group matches, and hides them with the group's last row. It matched each band and subtotal against its own words, so
    a search hid the band of every row it found.
  • A search field's data-filter-empty note shows only while words are typed: in a region with no items, a search typed
    and cleared left the note that nothing matches.
  • A white label's --redz-primary-contrast is black or white by the luminance of --redz-brand, so its words read at
    4.5:1 or more on any colour. It went by the colour's lightness and turned white below 0.62, which gave 3.7 to 4.5:1 on
    many mid tones, such as #4f9453 and #7a7a7a.
  • A tablist with data-hash takes a new address as a person's choice, through redz:select: a page that refuses it,
    with unsaved edits, keeps its tab and gets the address back. A link to a panel or the back button selected the tab
    past the page's question. The panel the address names comes into view, as at load.
  • A stretched-link in a list-group-item makes that item its link, and the item's other links and buttons stay their
    own. The item was not the link's box, so the link covered the first screen of the page, wherever the list stood.
  • A button REDZ.ui.busy() marks keeps its own fill and edge while it waits, as the states table shows it. The
    aria-disabled it is given turned it to the disabled look, which on the page floor of a dialog's footer left only the
    spinner to see. A busy outline button without an icon keeps its edge too.
  • A logo in a choice-media without width and height fits the banner: its height went unbounded, so a wide logo
    drew at its own size, 236 by 68 where the banner holds 40.
  • On a phone, a shell without an app-sidebar lays its main region edge to edge, as one with a sidebar does; it kept
    an 8 px margin at the start. The same holds in print.
  • A shortcut leaves alone a button inside an inert region, which it pressed, and keeps a held combination's repeats
    from the browser: holding the keys of a page's save let the browser's own "Save page" through after the first press.
  • A list-group-flush right in a card, under its header, gives its rows the card's 16 px at the sides, as Bootstrap
    does: its rows' words stood against the card's edge (since 0.2.0). Inside a card-body, which has its own room, the
    rows stay flush.
  • An alert keeps its icon beside its words in a narrow box, such as a dialog on a phone: below about 320 px its words
    wrapped under the icon, which stood alone on a line above them.
  • A selection-bar in a narrow box with more than one action keeps its clear button on the line of its count, at the
    end, and its buttons wrap below them: the clear button, last, wrapped onto a line of its own at the start.
  • A busy region's words stand on a ground of the region's color, as wide as they are: they spanned the region over the
    dimmed words under them, which on a narrow region read through them.
  • A row header, th scope="row", in a table-scroll keeps its words on one line, as the scroller is there to give the
    table its width: on a phone "Boat A" broke onto two lines. text-wrap lets a long one wrap again.
  • A tooltip hides on a scroll only when the scroll moves its element: any box scrolling anywhere hid it, so a log with
    data-follow taking a line, or a page nudged by a pixel, closed the tooltip a reader was on.

Files. redz-ui-0.19.0.zip - the folder a project serves, as it is: css/, js/, LICENSE, LICENSE-editor, NOTICE and redz-ui.json, the passport (the version, the floor, the files to link, the vocabulary and the sha256 of every file). This release needs the icon pack redz-ui-icons 1.13.2, a release of its own. redz-ui-tools-0.19.0.zip - the tools a project runs on its own server, never serves: floor.php, the browser floor checker, with its list floor.json, and min.php, the minifier, each the file this release was built and checked with; PHP 8.4 or newer with no extension, no network; redz-ui-tools.json is their passport. checks.zip - the sheet of the probes this release passed in every engine, also at https://redz-tech.github.io/REDZ.UI/0.19.0/checks/.

Check the archives: gh release verify-asset v0.19.0 redz-ui-0.19.0.zip --repo redz-tech/REDZ.UI, and the same for redz-ui-tools-0.19.0.zip.