Rethink the main navigation: fluid, customisable, and made for a phone (part four of #282) #299

Open
opened 2026-09-24 23:13:00 +00:00 by tiagoagueda · 0 comments
Owner

#282 was split on the seam it proposed itself: the account button, the name inside the
account menu and the + menu have landed. What is left is the fourth part -- the only one
where "the right answer is not already visible from the code" -- and this issue is it.

What the main navigation is today

One row, written twice. core/navigation.py:ITEMS holds seven items, and
partials/nav_links.html renders them as a row at 768 pixels and up, and stacked inside
a <details> under Menu below it. Six links measure 635 pixels, so that disclosure
exists at all (#113). Below 768 the search box goes away with it (hidden md:block) --
there is no search on a phone at all -- and the header row's height is not a constant
(the row wraps), which is why app.js measures it into --header-height for the sticky
sidebars, the skip link, scroll-padding-top and the section observer.

The three questions #282 asked

Fluid / readable. Seven items at 635 pixels means the row is one label away from
wrapping in English and already wraps in German, Greek and Portuguese. Options worth
weighing: icons beside labels so the row survives translation; an overflow More menu
once the row runs out; grouping the seven into four (Search / Pipeline / Documents /
Records). Whatever is chosen, --header-height must keep working.

Customisable. This already half-exists and should be built on, not replaced:
hidden_nav_items on the profile, navigation.HIDEABLE, and the switches in
AppearanceForm. What is missing is order -- a person can hide Calendar but cannot
put Applications first. If reordering goes in, the stored shape changes from a list of
hidden keys to something that also carries position, and navigation.py's docstring
explains why hidden-not-shown was chosen (a new item in a later release must appear for
everybody); the same care applies to whatever replaces it. Note that #281 proposes an
Accessibility settings section, which may move where these switches live.

Mobile. Menu opening a panel of seven stacked links is functional and is not a
phone navigation. A bottom bar of four with the rest behind More is what a phone user
expects; a drawer is the other answer. This is the part to prototype rather than
specify.

What has to hold

  • tests/e2e/test_reflow.py::test_the_navigation_becomes_a_menu_and_still_works pins the
    current row + Menu disclosure at 320 pixels. A new shape rewrites that test with
    intent -- it is the fence for the old answer, not a bug -- and the replacement must keep
    the property it measures: nothing scrolls sideways at 320, in en, el and de.
  • test_target_size.py, test_sticky_header.py and test_keyboard_and_focus.py stay
    green, not edited into agreement.
  • No script dependence for what the platform already does: a menu somebody cannot open
    with scripts off is not one this project ships (cotton/dropdown_menu.html).
  • If a command palette (command.css) appears for "fluid", it appears on top of a
    search box that works without it, never instead of one -- which is also the answer to
    the missing phone search.

Where it meets #73

#73 (Readable and usable on a phone, 0.6.0) owns the page bodies: tables, the board,
touch targets, form inputmode, and adding a phone viewport to the browser suite. That
phone viewport is what holds the masthead's work in place afterwards. Neither blocks the
other; doing this one first means #73's phone pass is not fighting a header it also wants
to change.

Parked from #282: the standalone event

The + menu shipped Reminder, not Event: applications:event_create takes an
application's pk, an event belongs to an application, and there is no route that makes
one from nowhere. If an event gains a standalone create flow whose first field picks the
application, that is a feature with its own issue, not a menu entry (#238 is adjacent).

#282 was split on the seam it proposed itself: the account button, the name inside the account menu and the + menu have landed. What is left is the fourth part -- the only one where "the right answer is not already visible from the code" -- and this issue is it. ## What the main navigation is today One row, written twice. `core/navigation.py:ITEMS` holds seven items, and `partials/nav_links.html` renders them as a row at 768 pixels and up, and stacked inside a `<details>` under *Menu* below it. Six links measure 635 pixels, so that disclosure exists at all (#113). Below 768 the search box goes away with it (`hidden md:block`) -- **there is no search on a phone at all** -- and the header row's height is not a constant (the row wraps), which is why `app.js` measures it into `--header-height` for the sticky sidebars, the skip link, `scroll-padding-top` and the section observer. ## The three questions #282 asked **Fluid / readable.** Seven items at 635 pixels means the row is one label away from wrapping in English and already wraps in German, Greek and Portuguese. Options worth weighing: icons beside labels so the row survives translation; an overflow *More* menu once the row runs out; grouping the seven into four (Search / Pipeline / Documents / Records). Whatever is chosen, **`--header-height` must keep working**. **Customisable.** This already half-exists and should be built on, not replaced: `hidden_nav_items` on the profile, `navigation.HIDEABLE`, and the switches in `AppearanceForm`. What is missing is **order** -- a person can hide *Calendar* but cannot put *Applications* first. If reordering goes in, the stored shape changes from a list of hidden keys to something that also carries position, and `navigation.py`'s docstring explains why hidden-not-shown was chosen (a new item in a later release must appear for everybody); the same care applies to whatever replaces it. Note that #281 proposes an *Accessibility* settings section, which may move where these switches live. **Mobile.** *Menu* opening a panel of seven stacked links is functional and is not a phone navigation. A bottom bar of four with the rest behind *More* is what a phone user expects; a drawer is the other answer. **This is the part to prototype rather than specify.** ## What has to hold - `tests/e2e/test_reflow.py::test_the_navigation_becomes_a_menu_and_still_works` pins the current row + *Menu* disclosure at 320 pixels. A new shape rewrites that test with intent -- it is the fence for the old answer, not a bug -- and the replacement must keep the property it measures: nothing scrolls sideways at 320, in `en`, `el` and `de`. - `test_target_size.py`, `test_sticky_header.py` and `test_keyboard_and_focus.py` stay green, not edited into agreement. - No script dependence for what the platform already does: a menu somebody cannot open with scripts off is not one this project ships (`cotton/dropdown_menu.html`). - If a command palette (`command.css`) appears for "fluid", it appears *on top of* a search box that works without it, never instead of one -- which is also the answer to the missing phone search. ## Where it meets #73 #73 (*Readable and usable on a phone*, 0.6.0) owns the page bodies: tables, the board, touch targets, form `inputmode`, and adding a phone viewport to the browser suite. That phone viewport is what holds the masthead's work in place afterwards. Neither blocks the other; doing this one first means #73's phone pass is not fighting a header it also wants to change. ## Parked from #282: the standalone event The + menu shipped *Reminder*, not *Event*: `applications:event_create` takes an application's pk, an event belongs to an application, and there is no route that makes one from nowhere. If an event gains a standalone create flow whose first field picks the application, that is a feature with its own issue, not a menu entry (#238 is adjacent).
tiagoagueda added this to the 0.5.0 milestone 2026-09-24 23:13:00 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Postulo/postulo#299
No description provided.