@ngrok/mantle's Dialog.Footer no longer reverses its children. Previously it
applied flex-row-reverse, which laid its children out right-to-left — so
the DOM order was the visual mirror of what you wrote. It now uses normal
flex with justify-end, so children render left-to-right in DOM order,
matching Sheet.Footer and AlertDialog.Footer.
TL;DR: For every Dialog.Footer with two or more children, reverse the
order of its direct children. The conventional layout is the secondary/cancel
action first and the primary action last (so the primary action stays on the
right). Footers with a single child need no change.
Dialog.Footer (the footer of @ngrok/mantle's Dialog
compound component). Search for Dialog.Footer, and for any destructured or
renamed imports of the same component (e.g. const { Footer } = Dialog; or
import { Footer } from "@ngrok/mantle/dialog").Dialog.Footer with two or more direct children, reverse the
order of those direct children. Do not touch the children's internals — only
their order.Dialog.Footer instances with zero or one direct child unchanged.Sheet.Footer or AlertDialog.Footer. They already render
in DOM order and are not affected by this change.Why reverse? The visual result must stay the same. Under the old
flex-row-reverse, the first DOM child rendered on the right. Code was therefore written primary-action-first to put the primary action on the right. Now that children render in DOM order, primary-action-first would put the primary action on the left. Reversing restores the intended left-to-right appearance (secondary/cancel on the left, primary on the right).
1// BEFORE — primary action written first to land on the right under flex-row-reverse2<Dialog.Footer>3 <Button type="button" appearance="filled">4 Save5 </Button>6 <Dialog.Close asChild>7 <Button type="button" appearance="outlined">8 Cancel9 </Button>10 </Dialog.Close>11</Dialog.Footer>1// AFTER — DOM order matches visual order: cancel on the left, primary on the right2<Dialog.Footer>3 <Dialog.Close asChild>4 <Button type="button" appearance="outlined">5 Cancel6 </Button>7 </Dialog.Close>8 <Button type="button" appearance="filled">9 Save10 </Button>11</Dialog.Footer>1// BEFORE2<Dialog.Footer>3 <Dialog.Close asChild>4 <Button type="button" priority="danger" appearance="filled">5 Delete6 </Button>7 </Dialog.Close>8 <Dialog.Close asChild>9 <Button type="button" priority="neutral" appearance="outlined">10 Cancel11 </Button>12 </Dialog.Close>13</Dialog.Footer>1// AFTER2<Dialog.Footer>3 <Dialog.Close asChild>4 <Button type="button" priority="neutral" appearance="outlined">5 Cancel6 </Button>7 </Dialog.Close>8 <Dialog.Close asChild>9 <Button type="button" priority="danger" appearance="filled">10 Delete11 </Button>12 </Dialog.Close>13</Dialog.Footer>1// A footer with one child renders identically before and after. Leave it alone.2<Dialog.Footer>3 <Dialog.Close asChild>4 <Button type="button" appearance="outlined">5 Close6 </Button>7 </Dialog.Close>8</Dialog.Footer>[A, B, C] under the old reversal appeared as
[C, B, A]; to preserve that appearance, write [C, B, A] now.&&, ternaries, or
.map, reverse the order in which they appear, not just the static JSX. For
mapped lists, reverse the array (or render order) so the visual sequence is
unchanged.className on Dialog.Footer. If a footer overrode the layout
(e.g. added its own flex-row-reverse, flex-row, or justify-*), review it
by hand — the base class change may interact with the override. The base now
contributes flex justify-end.Dialog.Footer with non-action content (text, links, a left-aligned
hint alongside buttons): verify the layout visually. If it relied on the
reversal for positioning, adjust with explicit classes rather than DOM order.