From 3324b4eb701e34f64e859dd90937793ccf7f75c5 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Mon, 12 Oct 2026 01:27:00 +0200 Subject: feat: keep the sidebar for groups; search in the nav, the rest in the user menu Search is an icon in the nav, left of the tray button and the bell, and marks itself current on its page. Administration, Node, Create group and Android Sync moved to the user menu, between Settings and the theme, each under the condition it had in the sidebar. The sidebar keeps Public groups and the groups. On a phone, a tablet or the Android application the menu trigger is the avatar alone (max-width 768px or a coarse pointer); the name is the dropdown's first line, one line with an ellipsis. Measured: a 20-character handle put the trigger 159 px off a 320 px screen with search and transfers in the nav, and a 64-character one pushed the dropdown 122 px off the left. Creating a group is a desktop-application feature by design: a hand-typed #/create-group no longer opens the form in a browser, and QUICKSTART step 6 now says to use the desktop application instead of the browser. test_layout_responsive read only the first 768px media block; it reads them all now. Co-Authored-By: Claude Opus 5.5 --- packages/meshbay-hub/tests/test_layout_measured.py | 83 +++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) (limited to 'packages/meshbay-hub/tests/test_layout_measured.py') diff --git a/packages/meshbay-hub/tests/test_layout_measured.py b/packages/meshbay-hub/tests/test_layout_measured.py index 57d325a..298a754 100644 --- a/packages/meshbay-hub/tests/test_layout_measured.py +++ b/packages/meshbay-hub/tests/test_layout_measured.py @@ -62,8 +62,12 @@ NAV = textwrap.dedent(""" + + 🔔 -
+
""") @@ -206,8 +210,12 @@ GROUPED = textwrap.dedent(""" + + 🔔 -
+
""") @@ -283,3 +291,74 @@ def test_the_waiting_bar_is_as_wide_as_a_progress_bar(grouped): assert bar["width"] > 100, ( f"at {width} px the waiting bar is {bar['width']} px wide") assert bar["height"] >= 3, "the waiting bar has no height" + + +# ── The whole nav on a phone ──────────────────────────────────────────────── +# +# Search moved from the sidebar to the nav, beside the bell. With the user's +# name in the menu trigger, a 20-character handle already put the trigger 79 px +# off a 320 px screen, and 159 px once search and a transfer were there too. +# The fixture is the real markup of `Nav()` and `UserMenu()`, with the icons as +# the 1em boxes `Icon()` draws. + +_ICON = '' +FULL_NAV = textwrap.dedent(f""" + +""") +FULL_NAV_WIDTHS = [320, 360, 412, 521, 768, 1024] + + +@pytest.fixture(scope="module") +def full_nav(tmp_path_factory): + fragment = tmp_path_factory.mktemp("fullnav") / "fragment.html" + fragment.write_text(FULL_NAV, encoding="utf-8") + proc = subprocess.run( + ["python3", str(HARNESS), ",".join(str(w) for w in FULL_NAV_WIDTHS), + str(fragment), ".nav-brand", ".nav-right", ".user-menu-trigger", + ".user-menu-name"], + capture_output=True, text=True, timeout=180) + assert proc.returncode == 0, f"probe failed: {proc.stdout}{proc.stderr}" + out = json.loads(proc.stdout) + assert "error" not in out, f"no measurement: {out}" + return out + + +@pytest.mark.parametrize("width", FULL_NAV_WIDTHS) +def test_the_user_menu_stays_inside_the_nav(full_nav, width): + """Off the right edge is where nobody can open it — and it holds sign-out.""" + boxes = full_nav[str(width)]["boxes"] + trigger = boxes[".user-menu-trigger"] + assert trigger["right"] <= width - 16, ( + f"at {width} px the user menu ends at {trigger['right']} px, past the " + "nav's own padding") + assert boxes[".nav-right"]["left"] >= boxes[".nav-brand"]["right"], ( + f"at {width} px the nav's icons slide under the wordmark") + + +@pytest.mark.parametrize("width", FULL_NAV_WIDTHS) +def test_the_name_leaves_the_trigger_on_mobile_only(full_nav, width): + """Avatar alone up to the mobile breakpoint; the name beside it on a desktop.""" + name = full_nav[str(width)]["boxes"][".user-menu-name"] + shown = bool(name and name["width"] > 0) + assert shown == (width > 768), ( + f"at {width} px the name in the user menu is " + f"{'shown' if shown else 'hidden'}") -- cgit v1.2.3