//! A figure with a caption, and a strip of them. //! //! The fourth phase-B emitter. `makeover_layout::Figure` arrived at 0.11.0 after //! goingson turned out to have five of these across five screens, each with its //! own class names for the one shape: `task-overview-stat`, `stat-box`, //! `month-stat-item`, `contact-summary-stat`, `sync-stat`. //! //! # Why the strip has its own function //! //! Four tiles in a row and four tiles down a column are different things, and a //! renderer handed one figure at a time cannot tell it is looking at a set. So //! the set is what gets emitted, and a lone figure is a set of one. //! //! # The reading order is markup, not CSS //! //! Visually the value is set large over a small caption, which is what four of //! the five sites drew. A screen reader meeting "17" before it knows what was //! counted has to hold the number until the noun arrives, so the figure carries //! its own accessible name — "Current Streak: 17" — and the two spans are hidden //! from the reader that has already been told. //! //! Solving it that way rather than by inverting the markup and turning it back //! with `column-reverse` is deliberate: the arrangement and the type scale are //! the app's, and a renderer that emitted them would be naming sizes. Same line //! `meter_html` holds when it emits the tones and never the width. use crate::form::escape; use crate::{Emit, class}; use makeover_layout::{Figure, Intent, Tone}; use std::fmt::Write as _; /// The accessible name for a figure: the noun, then the number. /// /// Built here rather than carried, for the reason [`meter_text`] is: a strip /// wants "Current Streak: 17" and a terminal at one line wants something else, /// and a description that shipped either would have chosen for both. /// /// [`meter_text`]: crate::meter::meter_text #[must_use] pub fn figure_text(figure: &Figure<'_>) -> String { format!("{}: {}", figure.caption, figure.value) } /// One figure, as its own element. /// /// ``` /// use makeover_layout::{Figure, Tone}; /// use makeover_webview::{Emit, figure::figure_html}; /// /// let figure = Figure::new("17", "Current Streak").tone(Tone::Success); /// let html = figure_html(&figure, &Emit::default()); /// /// assert!(html.contains(r#"data-tone="success""#)); /// assert!(html.contains(r#"aria-label="Current Streak: 17""#)); /// ``` #[must_use] pub fn figure_html(figure: &Figure<'_>, opts: &Emit) -> String { let mut html = format!( "