You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@fineract.apache.org by "Aman-Mittal (via GitHub)" <gi...@apache.org> on 2026/10/02 16:07:01 UTC

[I] ADR 0005: build the card and form primitives as one set — they only pay off together [fineract-backoffice-ui]

Aman-Mittal opened a new issue, #684:
URL: https://github.com/apache/fineract-backoffice-ui/issues/684

   `local/no-vendor-ui-import` has been stuck at **227 files** for a while, and measuring why turns up something worth acting on before anyone spends another PR on it.
   
   `src/app/ui/` currently holds six primitives: `button`, `icon`, `spinner`, `searchable-select`, `deferred-datetime-button`, `tabs`. Those cover the four most-imported Ionic components in the codebase — `IonButton` appears in 214 of the 227 files. And yet:
   
   | primitives available | files that fully clear |
   | --- | --- |
   | what exists today | **17** |
   | + a card set (`IonCard`/`CardHeader`/`CardTitle`/`CardContent`) | 28 |
   | + a form-field set (`IonItem`/`Label`/`Input`/`Textarea`/`Checkbox`) | 45 |
   | **+ both sets together** | **172** |
   | + a layout set (`IonGrid`/`Row`/`Col`/`List`) | 189 |
   
   ## Why the jump
   
   A file clears only when **every** Ionic import in it is covered — the rule reports the import statement, not the symbol. And these files are not small: of the 227, most import nine to fifteen distinct Ionic components.
   
   ```
    9 component(s): 25 files      12 component(s): 25 files
   10 component(s): 18 files      13 component(s): 11 files
   11 component(s): 23 files      14 component(s): 17 files
   ```
   
   A typical screen is a card wrapping a form. Shipping the card set alone leaves every one of those files importing `IonItem` and `IonInput`; shipping the form set alone leaves them importing `IonCard`. Either half on its own clears a handful. Together they clear 172 — **76% of the backlog**.
   
   This is also why a greedy "which primitive clears the most files" search is misleading here. It reports `+5, +2, +1…` and makes the work look like a long grind of unrewarding steps, when in fact almost all the value sits behind two clusters that have to land before anything moves.
   
   ## Suggested shape
   
   Build the primitives in one PR (or a short series that is merged together), then migrate screens in small batches afterwards. The migration batches are the easy, reviewable part; it is the primitive set that is the design work.
   
   Worth deciding deliberately rather than by accident:
   
   - **`IonItem` + `IonLabel` + `IonInput` is one primitive, not three.** Every form field in this codebase is that trio plus `fill="outline"` and `position="stacked"`. A field primitive that owns the trio is what removes the per-screen repetition; three thin wrappers would keep it.
   - **Accessible names are part of the contract.** `scripts/check-a11y-names.mjs` exists because these controls kept shipping without one. A primitive that takes a label and wires `[attr.aria-label]` itself makes that check redundant rather than adversarial.
   - **Keep the imperative boundary separate.** `ModalController` and friends are ADR 0003's surface, reached through `OVERLAY`, and `no-vendor-ui-import` deliberately exempts an import of nothing but controllers so that one import statement sits on one boundary. Eight files in this set still import `ModalController`; those go through `OVERLAY`, not through a new primitive.
   
   ## After both sets
   
   The long tail is genuinely small, and `IonSegment`/`IonSegmentButton` is most of it:
   
   ```
   15  IonSegment          9  IonPopover        5  IonChip
   15  IonSegmentButton    5  IonSearchbar      4  IonBadge
   ```
   
   Note `tabs` already exists as a primitive — the 15 `IonSegment` files are worth a look to see whether they want it rather than a new one.
   
   ## Acceptance
   
   - The card and form-field primitives live in `src/app/ui/`, with specs, and are added to the `VENDOR_UI_ALLOWED` list in `eslint.config.js`.
   - `npm run check:ui-primitives` passes.
   - Screen migrations land as separate small PRs, each dropping the files it touches from `eslint-suppressions.json` via `npm run lint:prune`.
   
   Background: `DOCS/adr/0005-ui-component-boundary.md`, `AGENTS.md`.
   


-- 
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: issues-unsubscribe@fineract.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [I] ADR 0005: build the card and form primitives as one set — they only pay off together [fineract-backoffice-ui]

Posted by "Aman-Mittal (via GitHub) via issues" <is...@fineract.apache.org>.
Aman-Mittal commented on issue #684:
URL: https://github.com/apache/fineract-backoffice-ui/issues/684#issuecomment-6722492855

   The set exists, so closing this against its Acceptance section.
   
   `src/app/ui/` now holds `card`, `form-field` and `date-field` alongside `button`, `icon`, `spinner`, `searchable-select`, `deferred-datetime-button` and `tabs`. `card.component.ts` wraps `IonCard`/`IonCardHeader`/`IonCardTitle`/`IonCardContent`; `eslint.config.js`'s `VENDOR_UI_ALLOWED` covers `src/app/ui/**/*.ts`, so the primitives may import Ionic while nothing else may; `npm run check:ui-primitives` passes.
   
   Commits `3f4a3267` "feat(ui): a form field whose label actually labels its control" (#848) and `0be98095` "feat(ui): a date field and a card, the primitives #684 pairs with the form field" (#849), plus #853.
   
   Building them together was the right call for the reason this issue gave. The form field had to render its label inside the control's own `label` slot rather than beside it, because Ionic's `getLabelledById()` reads only the control's own label — a sibling `ion-label` names nothing, which is the root of #287. The date field then needed the same treatment plus a `ControlValueAccessor` to own the `ion-datetime` / `ion-datetime-button` / `ion-modal` triad, and the card existed to stop every screen hand-rolling the header.
   
   Closing because the issue scopes the migrations as separate PRs. Two things that remain, both tracked elsewhere and neither a criterion here: `eslint-suppressions.json` still lists 227 files for `local/no-vendor-ui-import`, and the hand-copied label blocks are largely unmigrated — that is #287, which stays open. `app-select-field` was deliberately not built: `ion-select` takes the same label slot, so it needed no wrapper.
   


-- 
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: issues-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [I] ADR 0005: build the card and form primitives as one set — they only pay off together [fineract-backoffice-ui]

Posted by "Samearth17 (via GitHub)" <gi...@apache.org>.
Samearth17 commented on issue #684:
URL: https://github.com/apache/fineract-backoffice-ui/issues/684#issuecomment-5983858322

   Hi! I would like to work on this if this issue is free or unassigned
   
   
   


-- 
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: issues-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [I] ADR 0005: build the card and form primitives as one set — they only pay off together [fineract-backoffice-ui]

Posted by "Aman-Mittal (via GitHub) via issues" <is...@fineract.apache.org>.
Aman-Mittal closed issue #684: ADR 0005: build the card and form primitives as one set — they only pay off together
URL: https://github.com/apache/fineract-backoffice-ui/issues/684


-- 
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: issues-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org