Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ All notable changes to this project are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/), and the project adheres to
[Semantic Versioning](https://semver.org/).

## [0.1.13] - 2026-07-29

### Changed
- Viewer: the app frame is now viewport-bounded (`body` uses a fixed
`100vh`/`100dvh` height instead of `min-height`), so a long tree-mode node
list scrolls inside its own map pane instead of growing the whole page —
previously a 100+-node artifact in tree mode stretched the page to several
thousand pixels and scrolled the header away.
- Viewer: the default layout is now `split` (map left, detail right) and the
default display is now `tree`, so the exploration trajectory reads
top-to-bottom in a fixed, independently scrollable left pane on first load.
`stack` and `graph` remain available from the toolbar; unknown mode tokens
now fall back to the new defaults.

## [0.1.12] - 2026-07-25

### Added
Expand Down
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ resolver = "3"
members = ["crates/*"]

[workspace.package]
version = "0.1.12"
version = "0.1.13"
edition = "2024"
license = "MPL-2.0"
repository = "https://github.com/ARA-Labs/ara-cli"
Expand Down
2 changes: 1 addition & 1 deletion crates/ara-cli/assets/viewer.source-hash
Original file line number Diff line number Diff line change
@@ -1 +1 @@
154193f53a25f8cabb0fe326e0c14e578be5d3f7190bbd724c8399c6819224f5
c8b4f3e3c84dbfd1b9f99cdc45dd3a24841d2e703a44d627c1ada9f8f42f9355
Binary file not shown.
Binary file not shown.
8 changes: 4 additions & 4 deletions crates/ara-cli/assets/viewer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ARA Viewer</title>
<link rel="stylesheet" href="/styles-8e96cbefbbb65688.css" integrity="sha384-PLvTi5Lx4ul+vvTOCXuUffVA68PMjVWQHC89Ejz6JUiQI0SyTnywcoGAjEMPamoM"/>
<link rel="stylesheet" href="/styles-155177c35e1c149.css" integrity="sha384-MFt4Wb3NnUdo5vU4rUTkm7y8+QODGkKxoiJhAWrCfR5CkrUJGgpb9ROOTW5d0ndF"/>
<!-- Copy manifest.json to dist/ so the runtime fetch URL "manifest.json" resolves. -->
<!-- Trunk does not auto-copy public/ contents; this directive is required. -->


<script type="module">
import init, * as bindings from '/ara-viewer-1213ab1da86ce3ef.js';
const wasm = await init({ module_or_path: '/ara-viewer-1213ab1da86ce3ef_bg.wasm' });
import init, * as bindings from '/ara-viewer-ac78a8d0c42a85a9.js';
const wasm = await init({ module_or_path: '/ara-viewer-ac78a8d0c42a85a9_bg.wasm' });


window.wasmBindings = bindings;
Expand All @@ -20,6 +20,6 @@
dispatchEvent(new CustomEvent("TrunkApplicationStarted", {detail: {wasm}}));

</script>
<link rel="modulepreload" href="/ara-viewer-1213ab1da86ce3ef.js" crossorigin="anonymous" integrity="sha384-2WuofkhQAQ8NmTYBxWI406jmQ5VZKPYELR8SvJlfo2Ptncsj5RG5nzBa+lh7WKH9"><link rel="preload" href="/ara-viewer-1213ab1da86ce3ef_bg.wasm" crossorigin="anonymous" integrity="sha384-sner112zdRC9zqV6mq5+O1snCQUUKTaeqfLhIdZu9QOliF9mu42Nf4oKR8p/jIoK" as="fetch" type="application/wasm"></head>
<link rel="modulepreload" href="/ara-viewer-ac78a8d0c42a85a9.js" crossorigin="anonymous" integrity="sha384-2WuofkhQAQ8NmTYBxWI406jmQ5VZKPYELR8SvJlfo2Ptncsj5RG5nzBa+lh7WKH9"><link rel="preload" href="/ara-viewer-ac78a8d0c42a85a9_bg.wasm" crossorigin="anonymous" integrity="sha384-RfICuw4NNpPUoM3D27h9cOBnEsJ0AJ8rUM+EV9v4j6SgUmcc88JwHuqQfSlHpO/N" as="fetch" type="application/wasm"></head>
<body></body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ body {
font-family: var(--font-body);
font-size: 15px;
line-height: 1.5;
min-height: 100vh;
/* Fixed app frame: the viewport bounds the page so each .panel scrolls
internally. With only a min-height, a tall tree-mode node list gives the
grid its content height and the whole page grows instead (dvh keeps the
frame correct under mobile browser toolbars; vh is the fallback). */
height: 100vh;
height: 100dvh;
display: flex;
flex-direction: column;
}
Expand Down
7 changes: 6 additions & 1 deletion crates/ara-viewer/public/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ body {
font-family: var(--font-body);
font-size: 15px;
line-height: 1.5;
min-height: 100vh;
/* Fixed app frame: the viewport bounds the page so each .panel scrolls
internally. With only a min-height, a tall tree-mode node list gives the
grid its content height and the whole page grows instead (dvh keeps the
frame correct under mobile browser toolbars; vh is the fallback). */
height: 100vh;
height: 100dvh;
display: flex;
flex-direction: column;
}
Expand Down
6 changes: 3 additions & 3 deletions crates/ara-viewer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ pub fn App() -> impl IntoView {
let filter: RwSignal<FilterState> = RwSignal::new(FilterState::default());

// ── Layout mode (stack vs. split; survives manifest swaps) ────────────────
// Stack (map on top, detail below) is the default — it matches the wide DAG
// shape and uses the full viewport width. Split is the opt-in side-by-side.
// Split (map left, detail right) is the default — the trajectory reads
// top-to-bottom beside the step detail. Stack is the opt-in full-width mode.
let layout: RwSignal<LayoutMode> = RwSignal::new(LayoutMode::default());

// Per-mode split fractions (map fraction of the main axis). In-memory only;
Expand All @@ -95,7 +95,7 @@ pub fn App() -> impl IntoView {
};

// ── Display mode (graph vs. tree; survives manifest swaps) ────────────────
// Graph (SVG DAG) is the default; Tree is the published DOM tree-list.
// Tree (the published DOM tree-list) is the default; Graph is the SVG DAG.
let display: RwSignal<DisplayMode> = RwSignal::new(DisplayMode::default());

// ── Shared derived state (lifted into App — the single owner) ─────────────
Expand Down
48 changes: 25 additions & 23 deletions crates/ara-viewer/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,12 @@ pub fn safe_viewbox(bounds: Option<&Rect>) -> (f64, f64, f64, f64) {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum LayoutMode {
/// Map on top (full viewport width), detail below — `grid-template-rows`.
/// The default: matches the naturally wide-and-short exploration DAG shape.
#[default]
/// Opt-in: suits a naturally wide-and-short exploration DAG.
Stack,
/// Map left, detail right — `grid-template-columns`. The pre-issue-#9
/// behaviour, kept as an opt-in mode.
/// Map left, detail right — `grid-template-columns`. The default: the
/// trajectory reads top-to-bottom on the left while the selected step's
/// detail stays beside it.
#[default]
Split,
}

Expand All @@ -119,11 +120,11 @@ impl LayoutMode {
}

/// Parse a token back to a mode. Unknown input falls back to the default
/// (`Stack`) so a stale/garbage value can never wedge the layout.
/// (`Split`) so a stale/garbage value can never wedge the layout.
pub fn from_token(s: &str) -> Self {
match s {
"split" => LayoutMode::Split,
_ => LayoutMode::Stack,
"stack" => LayoutMode::Stack,
_ => LayoutMode::Split,
}
}
}
Expand All @@ -136,10 +137,11 @@ impl LayoutMode {
/// `Copy` enum so it can live in a Leptos signal and be unit-tested on native.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum DisplayMode {
/// Today's interactive SVG DAG (pan/zoom). The default.
#[default]
/// The interactive SVG DAG (pan/zoom). Opt-in via the toolbar.
Graph,
/// The published DOM indented tree-list.
/// The published DOM indented tree-list. The default: the full trajectory
/// scrolls vertically inside the map pane's own scroll range.
#[default]
Tree,
}

Expand All @@ -162,11 +164,11 @@ impl DisplayMode {
}

/// Parse a token back to a mode. Unknown input falls back to the default
/// (`Graph`) so a stale/garbage value can never wedge the display.
/// (`Tree`) so a stale/garbage value can never wedge the display.
pub fn from_token(s: &str) -> Self {
match s {
"tree" => DisplayMode::Tree,
_ => DisplayMode::Graph,
"graph" => DisplayMode::Graph,
_ => DisplayMode::Tree,
}
}
}
Expand Down Expand Up @@ -345,8 +347,8 @@ mod tests {
// ── LayoutMode ────────────────────────────────────────────────────────────

#[test]
fn layout_mode_default_is_stack() {
assert_eq!(LayoutMode::default(), LayoutMode::Stack);
fn layout_mode_default_is_split() {
assert_eq!(LayoutMode::default(), LayoutMode::Split);
}

#[test]
Expand All @@ -363,16 +365,16 @@ mod tests {
}

#[test]
fn layout_mode_from_unknown_token_falls_back_to_stack() {
assert_eq!(LayoutMode::from_token(""), LayoutMode::Stack);
assert_eq!(LayoutMode::from_token("garbage"), LayoutMode::Stack);
fn layout_mode_from_unknown_token_falls_back_to_split() {
assert_eq!(LayoutMode::from_token(""), LayoutMode::Split);
assert_eq!(LayoutMode::from_token("garbage"), LayoutMode::Split);
}

// ── DisplayMode ───────────────────────────────────────────────────────────

#[test]
fn display_mode_default_is_graph() {
assert_eq!(DisplayMode::default(), DisplayMode::Graph);
fn display_mode_default_is_tree() {
assert_eq!(DisplayMode::default(), DisplayMode::Tree);
}

#[test]
Expand All @@ -389,9 +391,9 @@ mod tests {
}

#[test]
fn display_mode_from_unknown_token_falls_back_to_graph() {
assert_eq!(DisplayMode::from_token(""), DisplayMode::Graph);
assert_eq!(DisplayMode::from_token("garbage"), DisplayMode::Graph);
fn display_mode_from_unknown_token_falls_back_to_tree() {
assert_eq!(DisplayMode::from_token(""), DisplayMode::Tree);
assert_eq!(DisplayMode::from_token("garbage"), DisplayMode::Tree);
}

// ── apply_manifest ────────────────────────────────────────────────────────
Expand Down
Loading