App Layout Variants - #82
Draft
aaronsmulktis wants to merge 2 commits into
Draft
aaronsmulktis wants to merge 2 commits into
aaronsmulktis wants to merge 2 commits into
Conversation
…itor
The theme/layout split landed with the layout axis nearly empty: calendar,
messenger, maps and code_editor all declared `- layout: default` in their
defaults but nothing read `config.<app>.layout`, so their layout groups were
inert placeholders and structure was held almost constant across sweeps.
calendar agenda_first lands on the agenda, not the month grid
sidebar_nav month nav + view toggle become a left rail
messenger split_inbox chat list stays beside the open thread
compact_list dense avatar-less rows; flat messages
maps sidebar_left search + Saved Locations left of the map
bottom_sheet sidebar becomes a panel under the map
code_editor sidebar_right file tree right of the editor
top_tree file tree as a strip above the editor
Follows the `todo` convention: a `current_layout()` helper reads the config
and the page handlers branch on it. Three supporting refactors, each of which
removes a reason to duplicate:
- code_editor: the three page handlers all built the same
`Div(cls="flex space-x-2")(side_bar, main_screen)`; that is now a single
`editor_page()` so a new variant is added in one place instead of three.
- messenger: the chat list is extracted to `conversation_list(selected=)` so
`split_inbox` can render it beside a thread. The layout is applied as a
class on <body>, because the `max-w-lg` cap that makes this app
phone-shaped lives there and a descendant cannot widen its own ancestor.
- maps: the layout reaches templates/map.html as a <body> class; both
variants are CSS-only, so none of the template's JS knows about them.
Layouts change structure only. Routes, element ids and the `/<app>_all`
endpoints are identical across variants, so rewards -- which read state, not
the DOM -- are unaffected. Screenshot coverage adds the eight variations plus
a `messages_thread` route: both messenger layouts change the thread view,
which the existing list route never renders. Alice exists in every content
variation.
The file tree, the "No file selected" heading and the Language/Theme labels are all marked `text-white`, from when this app painted its panels a hard-coded blue. The theme migration repointed `.main-content` at `var(--color-bg)` -- white in the default theme -- so that chrome became invisible in every layout, including `default`. Point `.text-white` inside `.main-content` at `var(--color-fg)`, and restore white for the elements that carry their own dark fill: the mode/theme selects and tab strip (`bg-gray-*`) and the highlighted folder row (`bg-blue-*`). Found by reading the generated screenshots rather than the DOM -- the markup assertions passed throughout, since the text is present and merely the same color as what is behind it. Not covered by the Code Editor Tasks PR (aaronsmulktis/editor-tasks), whose code-editor changes are the save method and an `editor_binding()` refactor; it touches neither `text-white` nor `.main-content`.
aaronsmulktis
changed the base branch from
main
to
aaronsmulktis/themes-and-layouts
September 29, 2026 21:02
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
In an effort to introduce additional layouts for each app to increase variety in eval heuristics, this PR presents the following additional layouts:
calendaragenda_firstsidebar_navmessengersplit_inboxcompact_listmapssidebar_leftbottom_sheetcode_editorsidebar_righttop_treeThat closes the gap on every app except one:
tododefault,kanban_boardstart_pagedefault,broken_logos,clickable_logosonlineshopis excluded deliberately. It is off by default and gated on OpenJDK 21 plus adownloaded dataset, so its layouts cannot be screenshot-tested in the default CI path, and a
full Python rewrite is in flight on
aaronsmulktis/webshop-rewrite. Layouts written againstthe current implementation would be written against code on its way out.
How it works
Each app now follows the
todoconvention introduced in #72: declaring a- layout: defaultin their defaults and acurrent_layout()helper reads the config and the page handlers branch on it.Layout files use
defaults: - defaultso a variant states only what it changes.Introducing reusable markup functions:
Div(cls="flex space-x-2")(side_bar, main_screen). That is now oneeditor_page(), so anew variant is added in one place instead of three.
conversation_list(selected=)sosplit_inboxcan render it beside a thread. The layout is applied as a class on<body>,because the
max-w-lgcap that makes this app phone-shaped lives there and a descendantcannot widen its own ancestor.
templates/map.htmlas a<body>class. Both variants areCSS-only, so none of the template's JS needs to know which is active.
Reward safety
Layouts change structure only. Routes, element ids and the
/<app>_allendpoints areidentical across variants, and rewards are scored from state rather than the DOM, so no
existing task changes behaviour under any of these. The selectors tasks and screenshots key
off —
#todo-list,.calendar-table, .agenda-list,#map,#editor,#wrapper— arepreserved in every variant.
No MCP change was needed:
registry.pydiscovers variants by globbingconfig/apps/<app>/layout/*.yaml, so the new files surface inlist_variantsautomatically.Also included
A second commit fixes an unrelated, pre-existing bug the screenshots surfaced: the code
editor's file tree, "No file selected" heading and Language/Theme labels are all marked
text-white, left over from when the app painted its panels a hard-coded blue. The thememigration repointed
.main-contentatvar(--color-bg)— white in the default theme — sothat chrome was rendering white-on-white in every layout, including
default. It is notcovered by the Code Editor Tasks PR, whose code-editor changes are the save method and an
editor_binding()refactor.Worth noting how it was found: every markup assertion passed the whole time. The text was
present and merely the same colour as what was behind it. Only reading the generated images
caught it.
Test plan
uv run -m pytest tests/→ 768 passed, 7 skipped (the skips are the Java-21-gated shop)ruff→ no new findings; diffed against a stashed baseline, the pre-existing count isunchanged
TestClientand asserted on markup with<style>/<script>stripped — the inline stylesheets contain every variant's rules, so naive negative
assertions produce false passes
sidebar_rightperforms a real DOM reorder rather than a visualrow-reverse,so the accessibility tree matches what is rendered
Screenshot coverage adds the eight variations plus a new
messages_threadroute: bothmessenger layouts change the thread view, which the existing
/messageslist route neverrenders, so
split_inboxwould otherwise have been untestable. Alice is present in everycontent variation.