| name | feedback-reuse-first-extract-gate | ||
|---|---|---|---|
| description | Before hand-rolling ANY UI/util in mtp-web, run the reuse-first gate (does it exist in @mtp/ui, @mtp/hooks, lib/*, or Radix?); when hand-rolling something structural, decide up-front whether to extract a primitive that OWNS the invariant. Stops per-screen bugs recurring. | ||
| metadata |
|
The recurring class of bug this session (data-grid clip, action-bar overlap, sticky panels) all came from the same cause: structural UI was hand-rolled per screen, so an invariant got re-implemented — and re-broken — each time. This gate prevents it. Apply it before writing any component or utility.
Search first; do not write until you've checked:
- Radix — for any interactive control / behaviour (modal, popover, tabs, select, scroll-area, tooltip…). [[feedback-check-radix-first]].
@mtp/ui— layout primitives (Sidebar,ThreePane,SplitPane,Grid,Stack,Cluster,DataGridScroll), wrappers (Tabs,Toast,Tooltip,Button,EmptyState),AppShell.@mtp/icons,lib/api(apiGet/apiSearch/apiUpload),lib/forms(handleServerErrors,typedWatch),lib/validation(schemaTools),lib/utils(typeGuards, flattenObjectKeys),stores/appStore.
If something fits, use it. Never re-implement a scroll container, sticky panel, focus trap, column split, etc. by hand.
If nothing fits and you must hand-roll, decide BEFORE finishing: one-off or pattern? Extract a primitive on first use (not "rule of three") when ANY of these is true:
- It encodes a structural invariant that breaks silently if forgotten (overflow + min-width,
min-width:0, sticky offsets, focus trap, equal-height) — the primitive must OWN the invariant so no screen can re-break it. (DataGridScrollowns overflow+min-width;Sidebarowns sticky+min-width:0;ThreePaneowns the 3-col.) - 2+ screens plausibly need it, or a bug here would recur across screens.
- It's chrome/layout, not screen-specific content.
Keep it local (don't extract) only when it's genuinely screen-specific content with no shared invariant.
The test: "If I get this subtly wrong, does it break on one screen or many?" Many → primitive now.
When you extract: export from the package barrel (@mtp/ui index etc.), add a one-line entry to [[project-mtp-component-authoring]], and (if it's an architecture-level primitive) an ADR. So the next person finds it in Gate 1.
Why: confirmed 2026-05-23 — the data-grid clip recurred on Approvals/Ledger/Coa because the "overflow-x:auto + min-width" rule was tribal, not a component. The fix was <DataGridScroll> owning the invariant. Had this gate been applied at the first grid, the primitive would have existed and the bug never spread.
Related: [[feedback-check-radix-first]], [[project-mtp-component-authoring]], [[feedback-verify-data-grids]].