Aman-Mittal opened a new issue, #233:
URL: https://github.com/apache/fineract-backoffice-ui/issues/233
## What is wrong
Most icon-only buttons in the app carry a tooltip, which also gives them
their accessible name — there are **246** uses of `appTooltip` doing exactly
that. **38** buttons were missed, in 19 files:
- **28 have no accessible name at all.** A screen reader announces "button",
with nothing to distinguish delete from edit.
```html
<ion-button fill="clear" color="danger" (click)="onDelete(row)">
<ion-icon name="trash-outline"></ion-icon>
</ion-button>
```
- **10 use a hardcoded English `title`**, so they are readable but never
translated, unlike the rest of the interface.
```html
<ion-button fill="clear" color="danger" title="Re-open Period"
(click)="onDeleteClosure(closure)">
```
## Business value
On a row of icon buttons, the icon is the only thing distinguishing "edit"
from "delete". A screen-reader user gets "button, button, button" and has to
guess which is which — on rows where one of those buttons deletes an accounting
rule or re-opens a closed accounting period. Guessing wrong is destructive and
there is nothing to guess from.
Sighted users lose out too: the missing tooltip is the only place the app
explains what an unlabelled icon does, so anyone new to the screen has to click
one to find out. And a trash icon meaning "re-open period" is not something
anyone should have to discover by trying it.
The pattern is already established and used 246 times. These 38 are
stragglers, so this is consistency work as much as accessibility work.
## Finding them
```bash
python3 - <<'PY'
import pathlib, re
for p in pathlib.Path('src/app/features').rglob('*.ts'):
if p.name.endswith('.spec.ts'): continue
s = p.read_text(errors='ignore')
for m in re.finditer(r'<ion-button\b[^>]*>(.*?)</ion-button>', s, re.S):
body, tag = m.group(1), m.group(0)
if '<ion-icon' in body and not
re.search(r'\{\{|appTranslate|translate', body):
if 'appTooltip' not in tag and 'aria-label' not in tag:
print(f"{p}:{s[:m.start()].count(chr(10))+1}")
PY
```
Known files include `accounting/accounting-closures-list`,
`accounting/accounting-rules-list`, `accounting/chart-of-accounts` and
`accounting/financial-activity-mappings-list`; the script prints the full set.
## How to fix
Apply the pattern already used across the app:
```html
<ion-button
fill="clear"
color="danger"
[appTooltip]="'COMMON.DELETE' | appTranslate"
(click)="onDelete(row)"
>
<ion-icon name="trash-outline"></ion-icon>
</ion-button>
```
- `appTooltip` gives both the hover tooltip and the accessible name. Where a
tooltip is not wanted, `[attr.aria-label]="'COMMON.DELETE' | appTranslate"` is
enough.
- Replace hardcoded `title="..."` with the translated tooltip rather than
leaving both.
- Reuse existing `COMMON.*` keys where one fits; add new keys to
`src/assets/i18n/en.json` otherwise (`npm run i18n:check` only requires
`en.json`).
- Name the **action**, not the icon: "Re-open period", not "Unlock".
## Note on why lint does not catch this
The `@angular-eslint` accessibility rules are already enabled and pass
cleanly — they are not disabled or suppressed. They cannot see this: the rules
reason about native elements, and `<ion-button>` is a custom element whose
accessible name is computed inside Ionic's shadow DOM at runtime. See the
companion issue on adding a runtime accessibility check, which is what would
catch these automatically.
## Verifying
```
npm run lint
npm run i18n:check
npm run build
```
Then check one converted screen by keyboard: tab to the button and confirm a
screen reader (or the accessibility inspector in browser devtools) reads the
action name.
## Picking this up
No need to be assigned — assignment here is limited to committers. Comment
that you are starting, then open a PR.
This can also be split by feature directory if you would rather send a
smaller PR — say which directory you are taking in your comment, and someone
else can take another. The files are independent.
--
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]