Skip to content

Page anatomy, index pages, and show and edit pages - #386

Merged
eirvandelden merged 34 commits into
mainfrom
page-anatomy-and-action-row
Oct 22, 2026
Merged

eirvandelden merged 34 commits into
mainfrom
page-anatomy-and-action-row

Conversation

@eirvandelden

@eirvandelden eirvandelden commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner

Summary

Every button in the app looks like the main action, so a page cannot show which action is the default. Each template decides where its actions go: the title bar, a paragraph above the content, a card, a footer or a div.actions. Delete sits on show pages, in index table rows, and in footers outside the form on edit pages. Deleting a person or a group asks for no confirmation at all. Several pages (accounts, categories, chattels, transactions, transaction links, todos, the dashboard) have no h1. Index rows carry action columns and database IDs instead of opening the record. Wide tables push the page sideways, beside the sidebar and on a phone.

UI-review slices 3 (page anatomy), 4 (index pages) and 5 (show and edit pages) ship together. The review is the artifact https://claude.ai/artifact/Btg62aW6itkPG4pZJiKFe6. The app runs on mvpa.css with PR #41 and follows the rails-ui reference interaction-design.md on dotfiles main (agents/.agents/skills/rails-ui/references/interaction-design.md). That reference is the specification; this intent does not repeat it.

  • Page anatomy: every page has an h1 in a shared title bar. Every form ends in a shared action row. An "Acties ▾" pull-down menu holds a show page's secondary commands. Form errors render as <aside role="alert">.
  • Index pages: a row opens its record. No per-row action columns. "+ Nieuw" sits in the title bar. No database IDs. Every cell has a data-label, and a table that does not fit stacks into labelled rows.
  • Show and edit pages: a show page lists its fields as a <dl>. Delete lives only on the edit page: a red Verwijderen… apart on the far left of the action row, confirmed by the browser's native confirm.

Proof

  • On an account's edit page the bottom row shows a red Verwijderen… far left, then Annuleren and a filled Opslaan, Opslaan rightmost → test/integration/accounts_edit_test.rb edit form ends in an action row of Verwijderen…, Annuleren and Opslaan and test/system/action_row_test.rb Verwijderen… stands apart on the left and Opslaan is rightmost
  • On the new-account page the bottom row shows only Annuleren and a filled Opslaan, on the right → test/integration/accounts_edit_test.rb new form ends in an action row of Annuleren and Opslaan and test/system/action_row_test.rb new page action row sits on the right without Verwijderen…
  • Pressing Return in a field on an edit page saves the record and never asks to delete → test/system/action_row_test.rb pressing Return in the account name saves the account
  • Annuleren on an edit page returns to the show page; on a new page to the index → test/integration/accounts_edit_test.rb Annuleren on the edit page links to the account and Annuleren on the new page links to the accounts index
  • Verwijderen… on a person's edit page shows the browser's confirm naming the person and that it cannot be undone; cancelling keeps, confirming deletes → test/system/people_test.rb dismissing the delete confirm keeps the person and accepting the delete confirm deletes the person
  • The show pages of an account, category, chattel, person and group show no Delete → test/integration/accounts_show_test.rb show page has no delete button, test/integration/categories_show_test.rb show page has no delete button, test/integration/chattels_show_test.rb show page has no delete button, test/integration/people_test.rb show page has no delete button, test/integration/groups_test.rb show page has no delete button
  • The accounts, admin users, appropriations and budgets indexes show no per-row action buttons; a row's name opens the record → test/integration/accounts_index_test.rb rows carry no buttons and the name links to the account, test/integration/admin/users_test.rb index rows carry no buttons and the name links to the user, test/integration/appropriations_test.rb index rows carry no buttons and the purpose links to the appropriation, test/integration/budgets_test.rb index rows carry no buttons and the date range links to the budget
  • Each index page has + Nieuw in its title bar and shows no database IDs → test/integration/index_pages_test.rb every index with a new route has + Nieuw in its title bar and no index shows a database ID column
  • Every page has exactly one h1 → test/integration/page_headings_test.rb every page has exactly one h1 in its title bar
  • On a transaction's show page Nieuw bezit sits in the "Acties" menu next to Bewerken → test/integration/transactions_show_test.rb Nieuw bezit sits in the Acties menu beside Bewerken
  • Saving an account with a number another account already has shows the error in an alert above the form, announced by a screen reader → test/integration/accounts_edit_test.rb a rejected save shows the errors in an alert above the fields, test/integration/people_test.rb saving a person without a name shows the error in an alert, plus one manual VoiceOver or accessibility-tree check after a rejected save, recorded in the pull request
  • A chattel's show page lists its fields as a description list → test/integration/chattels_show_test.rb show page lists the fields as a description list
  • A refused delete returns to the edit page → test/integration/people_test.rb a refused delete returns to the edit page with the reason, and the same test in accounts_edit_test.rb, groups_test.rb, appropriations_test.rb
  • On the Gebruikers list no row has a remove button; an administrator removes a user from the admin edit page after the native confirm → test/integration/users_index_test.rb rows carry no remove button and test/system/admin_users_test.rb an administrator deletes a user from the edit page after the confirm
  • With the sidebar open on a laptop the transactions table never scrolls the page sideways; a long description wraps; amounts and dates stay on one line → test/system/responsive_tables_test.rb transactions table fits beside the sidebar at laptop width
  • On a phone each transaction stacks, each value labelled with its translated column name, still a table with column headers to a screen reader → test/system/responsive_tables_test.rb transactions table stacks into labelled rows at phone width (computed display, ::before content, header clipped not display: none, roles), plus one manual VoiceOver or accessibility-tree check recorded in the pull request
  • The same width and stacking hold for every index table → test/integration/index_pages_test.rb every index table stacks with a data-label on every cell and test/system/responsive_tables_test.rb no index page, show page or the dashboard scrolls sideways at phone width
  • A plain Annuleren looks like a bordered button beside a filled Opslaan → test/system/action_row_test.rb Annuleren has a border and a different background from Opslaan. The test asserts <a role="button" class="button-secondary"> with the plain-button look of a type="button"

Manual checks

Headless Edge on a copy of the development data, at 1280×900 and at 390×844 (phone width, through device emulation). The accessibility tree (CDP Accessibility.getFullAXTree) stands in for VoiceOver.

  • Account edit page: Verwijderen… (red) far left, Annuleren (an <a role="button">, light) and a filled Opslaan on the right, Opslaan rightmost. On a phone the row stacks with Opslaan on top. The number fieldset sits inside the form, above the action row.
  • Return in the account name field saves and opens the show page; no dialog.
  • Person edit page, Verwijderen…: the native confirm reads "<name>" verwijderen? Dit kan niet ongedaan worden gemaakt. Dismissing it keeps the person.
  • Refused save (an account number another account already has): <aside role="alert"> is the first visible child of the form. Its accessibility role is alert with live=assertive, and it is in the DOM at turbo:render, so a screen reader announces it. The delete confirm on that refused page names the stored name, not the unsaved one.
  • Transactions at phone width: rows stack with a translated label before each value. The accessibility tree still shows a table named "Transacties" with 8 columnheaders and cells; the ::before labels do not leak into the cell names.
  • All 15 index pages and the dashboard have exactly one h1 and no sideways scroll at 1280 and at 390. The account merge page from One external account can hold several account numbers #385 uses the shared title bar.

Notes

  • Upstream: the pull-down menu, responsive table CSS and title-bar row layout landed in Page anatomy, index pages, and show and edit pages MVPA.css#44; the lock already points at its merge commit.
  • Out of scope, proposed separately: <html> has no lang attribute; the title-bar heading wrap rule (local/layout/title_bar.css) could move into mvpa.css.

🤖 Generated with Claude Code

eirvandelden and others added 30 commits October 22, 2026 13:48
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ion-row

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er-account

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s menu partials

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…king tables

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… and stacking tables

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ts and stacking tables

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…tables

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ables

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… stacking tables

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…d stacking tables

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… decisions

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n account_numbers

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@eirvandelden
eirvandelden marked this pull request as ready for review October 22, 2026 12:07
@eirvandelden
eirvandelden merged commit 8bd01d1 into main Oct 22, 2026
13 of 14 checks passed
@eirvandelden
eirvandelden deleted the page-anatomy-and-action-row branch October 22, 2026 19:03
@eirvandelden eirvandelden mentioned this pull request Oct 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant