#[non_exhaustive]pub enum Affordance {
Hover,
Hint,
Ancillary,
Detail,
Anchored,
Overflow,
Gesture,
Haptic,
}Expand description
An affordance whose existence depends on the surface it is offered on.
Eight members, drawn from what the two measured apps already gate by hand
rather than from a taxonomy. makeover-layout’s warning applies and is the
reason each addition has to point at call sites rather than at a category:
guessing is how a description becomes a framework.
Each answers Self::available against the two axes and nothing else. An
affordance that is always available is not an affordance this crate has
anything to say about, and every_member_is_an_adaptation asserts none has
snuck in.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Hover
Anything a consumer reveals on hover: a row’s action cluster, a hover toolbar, a preview popover.
Both webview apps arrived at hover-revealed row actions independently
(goingson .task-row-action, Balanced Breakfast .row-actions), which
is why makeover-layout records the reveal as behaviour of
RowPart::Actions rather than as app policy. What neither app can say
is that a fingertip has no hover state at all, so the affordance is not
hidden on touch — it does not exist there, and something else has to
carry the same actions.
Hint
Chrome documenting a keyboard interaction: shortcut badges, key hints, a “press / to search” line.
goingson hides .kbd-hint on touch. Strictly this is a claim about
having a keyboard rather than about the contact patch, and Density
is the closest honest proxy the family carries. Stated rather than
hidden, because a detachable-keyboard tablet is where the proxy breaks
and a third axis is what fixing it would cost.
Ancillary
A secondary panel standing beside the primary content: a saved-views rail, a filter sidebar, an inspector.
goingson hides .saved-views-sidebar below its widest layout. Purely a
screen-budget claim — a touchscreen laptop should keep it — so this
reads SizeClass alone.
Detail
The detail half of a list-detail split, shown alongside the list rather than navigated to.
goingson’s .main-content and Balanced Breakfast’s .detail-panel.
Unavailable is not the same as absent: the detail still exists, it is
reached by navigation instead of by adjacency, and which of the two a
screen gets is what makeover-layout’s Arrangement is describing.
Anchored
Navigation or a primary action cluster pinned to a fixed screen edge instead of sitting in the flow of the page.
The reposition bucket, and the largest single one in goingson at 20%. It exists to compensate for what a compact window cannot hold in flow, so unlike the two above it is available at the narrow end and not the wide one. That inversion is the point: an adaptation that only ever removes things describes a degraded layout rather than a different one.
Overflow
An action cluster collapsed behind one control rather than laid out inline.
The other compensating member. makeover-layout’s Column::kept_at
already handles a table narrowing by dropping columns; this is the
same pressure on a cluster of controls, which cannot drop any of them
and folds instead.
Gesture
A direct-manipulation gesture on content: swipe-to-action, long-press to select, pull to refresh, swipe to navigate, drag to dismiss.
The density axis’s compensating member, and the answer to the question
Self::Hover asks and cannot answer. A fingertip has no hover state,
so the row actions a pointer reveals by hovering have to arrive some
other way; on both webview apps that way is a swipe.
One member for five gestures, on purpose. goingson and Balanced
Breakfast each gate all five behind a single boolean, so one member is
what is measured and five would be minted from one fact. If a surface
ever offers swipe without long-press, splitting this is additive and the
call sites that named Gesture keep meaning what they meant.
Haptic
Confirmation delivered through the contact patch rather than the eye: the tick as a drag crosses a threshold, the thump as a gesture fires.
A contact-patch claim, which is what makes it this crate’s business
despite being the one member nothing on screen shows. goingson
frontend/js/haptics.js.
The proxy breaks where the hardware has haptics and the user or the OS
has switched them off. That is neither Density nor SizeClass, and
it is stated here rather than fixed for the same reason Self::Hint
states the detachable-keyboard case: a third axis is what fixing it would
cost. This member says the surface can, never that the user wants.
Asking the platform whether haptics are enabled is the renderer’s job.
Implementations§
Source§impl Affordance
impl Affordance
Sourcepub const fn available(self, density: Density, size: SizeClass) -> bool
pub const fn available(self, density: Density, size: SizeClass) -> bool
Whether this affordance exists on a surface with the given input class and screen budget.
The whole crate in one call. A renderer asks per affordance and never branches on a width.
Sourcepub const fn gained_by(self) -> Option<Density>
pub const fn gained_by(self) -> Option<Density>
Which Density this affordance belongs to, or None when it reads the
screen budget instead.
The replacement for the withdrawn one-directional rule (see the crate
doc). Until 0.3.0 the direction was a property of the whole crate and a
test enforced it globally; now each member declares its own, and
a_density_member_is_available_on_exactly_the_density_it_declares holds
the declaration to the rule.
Exposed rather than kept private for the same reason Self::reads_density
is: it is the crate’s claim about itself, and a renderer that has one
density can read it directly instead of probing Self::available twice.
Sourcepub const fn reads_density(self) -> bool
pub const fn reads_density(self) -> bool
Whether this affordance’s availability reads Density at all.
Exposed rather than kept private because it is the crate’s own claim about itself: exactly the members gating a contact-patch interaction say yes. A renderer with one density can skip the rest entirely.
Sourcepub const fn reads_size(self) -> bool
pub const fn reads_size(self) -> bool
Whether this affordance’s availability reads SizeClass at all.
Sourcepub const fn token(self) -> &'static str
pub const fn token(self) -> &'static str
The CSS class name an app may hang off this, without the leading dot.
Present for the same reason SizeClass::token is: a webview renderer
needs a stable name, and minting it per app is how two apps end up with
has-hover and hover-capable.
Trait Implementations§
Source§impl Clone for Affordance
impl Clone for Affordance
Source§fn clone(&self) -> Affordance
fn clone(&self) -> Affordance
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more