Aman-Mittal opened a new pull request, #526:
URL: https://github.com/apache/fineract-backoffice-ui/pull/526
## The headline defect
The Guide button opened the **dashboard** tour on every route it did not
recognise. Route matching was `url.includes('/loans')`, which also claimed any
path with those characters anywhere in it.
`/accounting` on `main` — the copy reads "the key areas of the dashboard"
over a screen that is not one:

The same screen on this branch:

```
before /accounting → {"title":"Welcome to Fineract
Backoffice","counter":"Step 1 of 2"}
after /accounting → {"title":"Accounting","counter":"Step 1 of 5"}
```
Both frames are the same screen at the same moment — `main` at `55abe539`
was served alongside the branch.
## Every screen gets its own tour
URLs resolve through anchored patterns, most specific first. A screen with
no hand-written copy gets a tour **composed** from its own route `title` plus
one step per control that is actually on it, detected at open time. A
hand-written tour that points at nothing gains those steps too, which took the
section pages from one card to four.
A step appears only because the control is there, so nothing is filler and
nothing can go stale when a screen changes.
## Four selectors pointed at elements that cannot exist
Each rendered its copy and highlighted nothing, which is invisible from the
outside:
| Selector | Why it never matched | Tours |
|---|---|---|
| `button[headerActions]` | the attribute sits on an `ion-button`, whose
native button is in a shadow root that never carries it | 4 |
| `mat-select[name="productId"]`, `[name="savingsAccountId"]` | Material
leftovers; this application has no Angular Material | shares-create |
| `.tab-group` | applied by **no template anywhere** — a dead style rule in
five record views, from the Material port. All sixteen screens with tabs render
an `ion-segment` | 4 |
| `[headerActions]` alone | groups, centres and share accounts ask
`app-data-table` for a create button instead of projecting one | 3 |
Steps are also scoped now: a content step is searched inside `main`, so a
loose selector can no longer reach the shell the way a bare `ul` once resolved
to the sidebar's nav list. Resolution retries while the view settles rather
than silently finding nothing on a screen that is still fetching.
## Walking all twenty guided views found three more
At **412×839** and **1440×900**, stepping every step and checking whether
the declared target actually took the highlight:
- the business-date and Guide steps pointed at controls that move into the
header's overflow menu on a narrow viewport, so both highlighted nothing;
- the share-account form's last select sat 30px **under** the mobile sheet;
- on the dashboard at 1440×900 the card painted over **77.6%** of the System
Status card — that step's entire subject, with 48px showing.

Both widths now get room to scroll a target clear of the card. Re-measured:
**0% covered**, and no step at either width fails to find its target.

The narrow layout is a full-width bottom sheet at the shared 768px shell
breakpoint:

## Two defects found in review, in code added by this PR
Worth calling out rather than burying, since both were mine and both were
caught by checking rather than by reading:
- **Escape only worked while focus was inside the card.** It was a host
binding, and the tour is non-modal by design, so a user who clicked the thing a
step describes had no keyboard way out. It listens on `document` now, guarded
so it does not answer an Escape meant for something else.
- **A tour survived navigation.** Opening it on the dashboard and clicking
Clients left the dashboard card over the client list, with Next explaining
Fineract environment health and nothing highlighted — the same wrongness as the
old fallback, reached by navigating instead of by pressing the button. It ends
on `NavigationEnd`.
Both have a regression test that fails without the fix.
## Accessibility, i18n and theming
The card is a `dialog` named and described by its own copy, the step counter
is a polite live region because Next replaces the text in place, Escape closes,
and focus returns to the opener.
"Step X of Y" and the button's own label were hardcoded English and are now
translated.
The highlight colour is a themed token instead of a hex in a component. One
value cannot serve both themes — measured against the surfaces a highlight
lands on:
| | light | dark |
|---|---|---|
| `#b45309` | 4.23 – 5.02:1 | 3.32 – 3.87:1 |
| `#f59e0b` | 1.81 – 2.15:1 | 7.76 – 9.05:1 |
So each theme takes the value that clears WCAG 1.4.11's 3:1 comfortably.
Measured live in dark mode afterwards: **8.72:1** for the outline against the
surface behind it, **7.69:1** for the card text.

The highlight also no longer sets `position` or `z-index`, which was enough
to move a grid child while the tour was open.
## Verification
| | |
|---|---|
| `npm run test:unit` | 237 files / **1454 tests**, exit 0 |
| `npm run build` | clean |
| e2e `mocked` / `mobile` | 5 passed 1 skipped / 1 passed 5 skipped — the
skips are the viewport guards |
| Mobile walkthrough, 20 views | no dead targets, nothing hidden by the
card, no overflow |
| Desktop walkthrough, 20 views | same |
| lint, `check:translations`, `check:responsive`, `check:a11y-names`,
`check:icons`, `check-license.sh`, `check:branding-path`, `typecheck:e2e` |
clean |
`playwright.config.ts` gains a `DUAL_VIEWPORT_SPECS` list rather than adding
the spec to `MOBILE_SPECS`: that array doubles as the `mocked` project's
`testIgnore`, so joining it would have removed the desktop half of the spec
from the run entirely.
`DOCS/GUIDED_TOUR.md` documents how a tour is chosen, how one is composed,
and the selector traps above. `DOCS/MOBILE.md` said the narrow header *hides*
the business date and guide — it moves them into a popover, which is what the
new grouped selectors depend on, so that paragraph is corrected.
## Known and not addressed here
- `/tellers` shows "This screen" rather than "Tellers": its `path: ''` child
declares no `title`. 197 of 305 route entries have one; #355 covers that.
- `role="dialog"` without a focus trap. Correct for a non-modal coach mark,
but Tab still walks behind the card.
- The blank `/accounting`, `/organization`, `/system` visible in the first
screenshot, and `/security/audit-trails` silently redirecting to `/dashboard`.
Both predate this branch and are filed separately.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]