Skip to main content

Region

Enum Region 

Source
#[non_exhaustive]
pub enum Region<'a> { Band, Sidebar, Pane, Split, TabGroup, Modal, Bespoke { name: &'a str, }, Widget { name: &'a str, }, }
Expand description

A named part of a screen.

The thing makeover-geometry deliberately does not name: it names the space between things by relationship, and nothing named the things. Six named members, taken from what the two webview apps actually use, plus Region::Bespoke for the parts no description should reach. Both apps’ layout.css currently names exactly two things, .raised and .well, so this layer is absent rather than divergent, which makes it the cheapest of the schemas to add and the easiest to over-build.

#[non_exhaustive] arrives with Region::Widget, the pairing RowPart made at 0.9.0 and Readiness at 0.12.0, and for the same reason: the member after this one should not be a lockstep event across three renderers.

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

Band

A full-width strip with a title slot and an actions cluster, either of which may be empty. goingson’s .page-header, Balanced Breakfast’s .header and .detail-header are all this, differing only in which slots they fill.

§

Sidebar

A persistent column beside the content, holding navigation.

§

Pane

A region of content with its own scroll.

§

Split

Two panes side by side, where the left chooses what the right shows.

§

TabGroup

A set of panes, one visible at a time, with a Selector::Tabs above.

§

Modal

Content over a scrim, taking input until dismissed.

§

Bespoke

A region this crate names the place of and nothing else. The app owns what goes in it.

The escape hatch, and the thing that keeps the description honest about its own limits. A day-plan timeline, a kanban board, a calendar and the paint interaction over the timeline are not describable here and are not going to become describable: a description expressive enough to produce a timeline is a widget library wearing a description’s name.

But a screen containing one still has to be a screen. Without this member the description covers only the boring screens, and the four that make goingson worth using would need a second, undescribed path beside the router. Two paths is how the vocabulary starts drifting from the app again, which is the exact failure this crate exists to end.

So the description says “a thing called day-plan goes here” and stops. The name is opaque: this crate never interprets it, and no renderer is expected to know what it means beyond handing the space over.

Fields

§name: &'a str

What the app calls it. Never interpreted here.

§

Widget

A named assembly of things the vocabulary already says.

The third tier, between a primitive and Bespoke. Stated by Max 2026-08-12 answering the carousel: “something in between a primitive and a bespoke interface, like a widget, which is just an assembly of primitives.” Full note: wiki widget-tier.

§What separates it from the two members either side

A primitive is a thing every renderer draws from scratch, and the test it has to pass is that every host has an honest answer. A carousel fails that test — a terminal has no carousel — which is the same refusal Node::Html got and is why the carousel sat unsayable for months.

Bespoke fails it from the other side. Bespoke is for what one app owns and nobody will build twice, and it carries no contents: the description names the place and stops. A carousel is furniture any app would have, and every part of it — an ordered set of frames, a position, prev and next, a strip of position indicators — is already sayable. Only the assembly had no name.

So this member is the pair the other two are not: a name and contents. The contents are the assembly, in the region’s own body, said in members that already exist.

§Why the name does not have to be understood

A renderer that recognises the name draws it the way its host does it: a carousel in a webview, a pager with a count in a terminal, a selector in egui. A renderer that does not recognise it walks the body, which is primitives all the way down and which it can already draw.

That is what lets the widget set be open without every renderer knowing every widget. An unrecognised widget degrades to its assembly instead of failing, so a second or third party can name one without three renderers releasing in lockstep to accept it. Contrast Bespoke, which no renderer can degrade: there is nothing under it to fall back to.

§What it does not do

It does not make a timeline describable, and the refusal in the crate header stands unchanged. A widget is an assembly of things the vocabulary already says; anything that needs a member the vocabulary does not have is a finding about the vocabulary or it is Bespoke. A widget is never the way a primitive gets added by the back door.

Fields

§name: &'a str

What the assembly is called. This crate never interprets it, and a renderer is free not to know it.

Implementations§

Source§

impl<'a> Region<'a>

Source

pub const fn depth(self) -> Depth

How the region sits on what is behind it.

Source

pub const fn described(self) -> bool

Whether this crate can say anything about the region’s contents.

A renderer walks the description and hands every region it understands to the right drawing code. This is how it tells the two apart, and the reason it is a method rather than a matches! at each renderer: there is exactly one opaque member and there should stay exactly one.

Widget is described, and that is the whole of what separates it from Bespoke here. Both carry a name this crate never interprets; only one of them carries contents under it. A renderer that does not recognise a widget’s name still walks its body, so there is nothing for it to hand over and nothing it cannot draw.

Source

pub const fn name(self) -> Option<&'a str>

The name an app gave this region, if it gave one.

Bespoke and Widget are the two members that carry a name, for two different purposes: one says what the app will fill the space with, the other says what the assembly under it is called. A renderer dispatching on either wants the string without caring which member it came from, and writing that matches! at each renderer is how the two drift apart.

Trait Implementations§

Source§

impl<'a> Clone for Region<'a>

Source§

fn clone(&self) -> Region<'a>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a> Copy for Region<'a>

Source§

impl<'a> Debug for Region<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a> Eq for Region<'a>

Source§

impl<'a> Hash for Region<'a>

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<'a> PartialEq for Region<'a>

Source§

fn eq(&self, other: &Region<'a>) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl<'a> StructuralPartialEq for Region<'a>

Auto Trait Implementations§

§

impl<'a> Freeze for Region<'a>

§

impl<'a> RefUnwindSafe for Region<'a>

§

impl<'a> Send for Region<'a>

§

impl<'a> Sync for Region<'a>

§

impl<'a> Unpin for Region<'a>

§

impl<'a> UnsafeUnpin for Region<'a>

§

impl<'a> UnwindSafe for Region<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.