basquetWi + New ticket
terra TERRA-167

/practicas/[id] renders the complicaciones multi-select as a row of toggle Buttons while /practicas/nueva renders the same concept as a proper Checkbox group - the codebase already holds the right pattern and this one screen never got it

Done high ctcoder-terra-ca

ELAZAR, 2026-08-31, ON THE LIVE SITE: "still uses those horrible buttons https://terra-enamel.pensanta.com/practicas/(id)". Located rather than guessed. The page itself renders no buttons - src/app/practicas/[id]/page.tsx is a Server Component of dl/section blocks and one Link back to /mi-cursada. The controls come from src/components/practica-postop-form.tsx, which the page mounts at line 224 as PracticaPostopForm. THE DEFECT IS THAT TWO SIBLING FORMS RENDER THE SAME DOMAIN CONCEPT TWO DIFFERENT WAYS, and one of them is already right. Both /practicas/nueva and /practicas/[id] ask the user to pick zero-or-more complicaciones from a catalog. They do not look alike and they do not behave alike. - /practicas/nueva, practica-form.tsx lines 1316-1357: a bordered role="group" with aria-label, tabIndex and a focus-visible ring, containing one <Checkbox> from @/components/ui/checkbox per option, each paired with a <Label htmlFor> that is itself clickable, plus a real disabled state that greys the label. - /practicas/[id], practica-postop-form.tsx lines 92-115: a div.chip-row of <Button size="sm" variant={selected ? "default" : "outline"} aria-pressed>. A row of filled-and-outlined pills. No group semantics, no labels, no focus ring on the set. SO THE FIX IS A PORT, NOT A DESIGN. Render the posoperatorias multi-select the way the intraoperatorias multi-select two files over already renders it - same Checkbox component, same Label htmlFor pairing, same bordered role="group" with aria-label. Nothing needs inventing and nothing needs a decision from Elazar, which is the point: the codebase already contains the answer and one screen did not get it. ALSO IN THE SAME COMPONENT AND EASY TO MISS, lines 132-143: "Seguimiento completado" and "Alta" are raw <input type="checkbox"> inside a wrapping <label>. They are the browser default control, not the ui/checkbox everything else on the site uses, sitting directly under the pills. Same treatment. WHAT MUST SURVIVE THE PORT, and this is the part a straight swap loses. The catalog filter at line 94 is !c.retired || values.includes(c.value): a RETIRED complicacion stays rendered if and only if this practica already has it selected. It carries a title tooltip saying that deselecting it is irreversible because it cannot be re-added, and an inline "(fuera de catálogo)" span. A Button carries that title natively; a Checkbox plus Label needs it deliberately re-placed, and title on a bare Checkbox is the wrong home for a warning about an irreversible action. Decide where it goes and keep the "(fuera de catálogo)" marker visible either way. The semantics also change on purpose: aria-pressed belongs to a toggle button, checked belongs to a checkbox - do not carry aria-pressed across. AND CHECK WHETHER chip-row DIES WITH IT. src/app/globals.css line 317 defines .chip-row as flex flex-wrap gap-1.5 and grep finds exactly ONE consumer in the whole tree, this component. If the port removes the last use, remove the class in the same commit rather than leaving a defined-and-unused utility that the next person reads as an established pattern. LANE: this is src/, which is coder-terra-ca's and never mine - I do not push src/ under any circumstance. audit-terra-ca audits it independently and is told not to read coder's account first, because two lanes agreeing after one has seen the other's answer is one measurement wearing two names. NOT THE SAME ROW AS TERRA-124. That row ports pluto's design system to /practicas/nueva - grouped option cards, wider layout, required-field highlighting - and is blocked. This one is narrower and unblocked: make /practicas/[id] consistent with what /practicas/nueva ALREADY does today, using components that already exist. It does not wait on TERRA-124 and TERRA-124 does not wait on it.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 6w ago
  • wi-cli-venus verified · 6w ago
    IMPLEMENTED BY coder-terra-ca BEFORE I FINISHED WRITING THE ROW, AND AUDITED INDEPENDENTLY. audit-terra-ca answered Q1-4 from source and its answers are correct: PracticaPostopForm now uses the shared Checkbox (radix Checkbox.Root via src/components/ui/checkbox.tsx) with associated Label, matching practica-form.tsx lines 1316-1355; the two post-op flags moved off raw native inputs to the same Checkbox+Label; .chip-row has no remaining consumer and its sole definition is removed from globals.css. It also stated its provenance honestly - working tree, uncommitted, static source, not a browser verdict - and declined Q5 as needing interactive evidence. I VERIFIED Q5 MYSELF IN SOURCE, because it is the half I flagged as losable and the one nobody had checked. All three parts of the retired-catalog behaviour survive: line 99 keeps the !c.retired || values.includes(c.value) filter unchanged, so a retired complicacion still renders exactly when this practica already has it; the "(fuera de catálogo)" marker is still rendered at line 116; and the irreversibility warning is still present, moved to a title on the span wrapping that marker at lines 112-114 with its wording intact. aria-pressed is correctly gone rather than carried across, and role="group" with aria-label is new. ONE THING THE PORT PRESERVED RATHER THAN INTRODUCED, AND I AM RECORDING IT AS PRE-EXISTING SO NOBODY LATER READS IT AS A REGRESSION FROM THIS CHANGE. The warning that deselecting a retired complicacion is irreversible is a title attribute, which is hover-only and does not exist on touch. It was hover-only on the old Button too, so this change neither caused it nor fixed it. But the shape got slightly worse in one respect worth naming: the title now sits on the 15-character "(fuera de catálogo)" span while the CLICK target is the entire Label, so the region that reveals the warning is much smaller than the region that performs the action it warns about. A user can trip the irreversible toggle without ever crossing the span that explains it. Not a blocker for this row and not what it was opened for - filed as a separate observation because an irreversible action whose only warning is a hover tooltip is a real gap independent of which control renders it. STILL UNCOMMITTED IN A SHARED TREE at the time of this note, which is its own exposure: src/ is coder-terra-ca's lane and I do not push it, but my own db/ pushes run through a tree-wide hook and other lanes push here too. It needs to land rather than sit. Q5's INTERACTIVE half remains genuinely unverified by anyone: whether the warning is actually reachable by a person on the deployed page. Static source says the attribute is present; that is not the same claim.
  • wi-cli-venus completed · 6w ago
    SHIPPED AND LIVE. coder-terra-ca committed 35c5628 at v0.30.51 with the release gate green - 437 tests, typecheck and Next build, only the pre-existing lint warning in src/app/informes/page.tsx remaining. It reported the commit and the pre-push checks as definite but explicitly declined to assert deployment because its gitpush output was truncated after "Pushing to origin/main". That was the correct call and it is the reason this row can close on evidence rather than on a report: I read the live endpoint myself rather than inferring from a successful commit. https://terra-enamel.pensanta.com/api/health returns version 0.30.51, deploymentId dpl_4KU5BjhJujSTx3UEuXGdnNKGb41W, dbOk true, mailOk true, at 2026-08-31T18:11:31Z. The version in production matches the version in the commit, so the change Elazar complained about is on the page he was looking at. THREE INDEPENDENT READS AGREE AND NONE OF THEM SAW EACH OTHER FIRST. audit-terra-ca answered Q1-4 from source with its provenance stated as working-tree and static-only, and declined Q5 as needing interactive evidence. I verified Q5 in source separately - the retired filter at line 99 unchanged, the "(fuera de catálogo)" marker still rendered, the irreversibility wording intact, aria-pressed dropped rather than carried. coder-terra-ca reported the same set independently and confirmed it neither contacted audit nor supplied it reasoning. That separation was the point of running two checkers. WHAT CHANGED, in one line: the posoperatorias multi-select on /practicas/[id] moved from a chip-row of toggle Buttons to the shared Checkbox and Label inside a bordered role="group", which is what /practicas/nueva already did two files over; the "Seguimiento completado" and "Alta" flags moved off raw native inputs to the same primitives; .chip-row was removed with its last consumer; regression coverage was added. CARRIED FORWARD, NOT CLOSED HERE, and recorded so nobody reads it later as a regression from this change. The warning that deselecting a retired complicacion is irreversible is a title attribute: hover-only, absent on touch, and equally so before this change. What shifted is geometry - the title now sits on the 15-character "(fuera de catálogo)" span while the click target is the entire Label, so the region that reveals the warning is smaller than the region that performs the action it warns about. An irreversible action whose only warning is a hover tooltip is a real gap independent of which control renders it. It predates this row and is not what this row was opened for. AND ONE CLAIM NOBODY HAS MADE GOOD ON: that a person can actually READ that warning on the deployed page. Static source says the attribute is present. That is a different sentence and it stays unverified.
  • wi-cli-venus note · 6w ago
    CLOSED on an independent source read by audit-terra-ca at committed 35c5628, not on the implementing lane's report. PracticaPostopForm now renders complicaciones as Checkbox plus Label inside role=group, the two post-op flags use the same Checkbox primitive, and NO toggle Button or chip-row remains in the component. The defect Elazar named on the live site - /practicas/[id] using toggle Buttons where /practicas/nueva already used a proper Checkbox group - is gone from source. The fix was a PORT, not an invention: the codebase already held the right pattern on the other screen, which is why this was worth doing rather than designing. NOT EXERCISED, and the row closes on source state only: browser and mobile rendering, touch interaction, screen-reader announcement. Elazar reported this from the live site, so the visual confirmation that would fully close it is his and has not happened. pnpm test 438/438 PASS, typecheck PASS.
  • wi-cli-venus completed · 6w ago
    completed
task
6w ago by wi-cli-venus
6w ago
2026-08-31 18:11