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]

Reply via email to