Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Direction and ABDD

snora’s first principle is ABDD — Accessible By Default and by Design. Layout is described in logical edges, not physical directions, so an app written for English readers also works for Arabic / Hebrew / Persian readers without a per-screen rewrite.

Two switches

#![allow(unused)]
fn main() {
use snora::{LayoutDirection, ToastPosition};

let layout = AppLayout::new(body)
    .direction(LayoutDirection::Rtl)            // body row mirrors
    .toast_position(ToastPosition::TopEnd);      // toast anchor mirrors
}

direction controls how snora composes the skeleton row (where the sidebar lands), and is also passed to the prefab widgets so they mirror their own internal start / end arrangements.

Logical vs physical

Edge is the central vocabulary type:

#![allow(unused)]
fn main() {
pub enum Edge { Start, End }
}
DirectionEdge::StartEdge::End
Ltrleftright
Rtlrightleft

Use Edge::is_left_under(direction) if you ever need to translate to a physical side.

Direction-aware rows

For your own widgets, snora::direction::row_dir (and row_dir_three) build a row! whose order is decided by direction:

#![allow(unused)]
fn main() {
use snora::direction::row_dir;

let bar = row_dir(
    state.direction,
    iced::widget::text("File: untitled"),       // start
    iced::widget::button("Save")                // end
        .on_press(Message::Save),
);
}

Under Ltr, “File:” is on the left and the Save button on the right; under Rtl, the order is mirrored. You write the row once.

Built-in widgets that take direction

WidgetWhat flips
app_headerTitle group on Start, end-controls on End
app_side_barTooltip side; the sidebar position is determined by AppLayout::direction
Toast layerAnchor side, when ToastPosition is *Start or *End
SheetAnchor side, when SheetEdge is Start or End. Inside-facing rounded corner also flips. Top / Bottom edges are unaffected.
DialogUnaffected — centered, not edge-anchored

Live flip

Live LTR ↔ RTL flipping is a one-line accessibility setting. Keep direction: LayoutDirection on your state, mutate it on a user action, and re-pass it on each view. Snora re-renders the whole skeleton mirrored — no per-widget reset needed.

The examples/rtl demo flips on a button press.

Intentionally non-mirroring elements

Some elements should not mirror:

  • Numbers, currency, ISO dates — readers of any direction parse these left-to-right within their text.
  • Code, logs, file paths — same.

Keep these in plain text; iced + snora will not mirror their internal contents, only the surrounding layout.

What snora does not do

  • Bidirectional text shaping. iced 0.14 handles BiDi at the text-layout layer; snora does not augment that.
  • Locale-driven number formatting. Use the icu or num-format crates.
  • Mirrored icons. Lucide ships icons that already include direction-aware variants where appropriate; pick the right name. snora does not flip raster or SVG content.

ABDD is a layout discipline, not a complete i18n stack. snora gets the skeleton right; you bring the rest of the i18n story.