0.9.1-alpha.40
Alpha@xaui/native@0.9.1-alpha.40
Patch Changes
-
78813c4:
Menu— Trigger · Overlay · Content · Label · Group · Item · ItemTitle · ItemDescription · ItemIndicatorA list of actions anchored to whatever opened it, and the third component to read the anchored positioning extracted for the
Popover—utils/placement.ts,hooks/use-anchor-ref.ts,hooks/use-anchored-position.ts,system/anchored/. Nothing about the measuring pass, the host origin or the collision flip is written again here, which is the whole return on that extraction.The intent belongs to the row, not to the menu. A menu is the theme's floating surface like a popover, with no emphasis of its own — but one row in it can be the destructive one, and a list where "Supprimer" reads like "Renommer" is the list that gets misread.
dangerpaints the title and any icon in it and nothing else: a red row would read as an alert. The description stays muted whatever the intent, because a danger row says what it does in red once and a red sentence under it says it twice.Both faces of a row are resolved once on the root, so a menu of forty actions costs what a menu of two costs and no slot ever touches the recipe (R5).
Choosing a row closes the menu after the caller's
onPresshas run, in that order: a handler that reads the menu's state has to run while there is still a menu.closesOnPress={false}is for the row that toggles something the reader will want to toggle again.offsetdefaults to 6 where thePopover's is 9 — a menu belongs to the control it drops out of, and a popover belongs to nothing.Menu.Separator, and you place it. A menu of four related actions wants none; a menu whose last row is "Supprimer" wants exactly one, above it. Drawing them between every pair and asking for the exceptions is the wrong way round — a menu is short enough that the one place a break belongs is obvious to whoever wrote it and invisible to the component.It runs the panel's full inner width rather than lining up with the rows' text, because a rule inset to the titles reads as belonging to the row under it and this one belongs to neither. Hidden from screen readers: announcing "separator" between every pair of actions is noise in the one place a menu has to be brisk. It is the menu's own trim rather than a
Divider, resolved on the root with everything else the panel reads.flex: 1cannot be written inside a panel that measures itselfMenu.ItemTitlehad it, and the whole menu rendered as a seventy-point capsule with no text in it.flex: 1isflexBasis: 0. The measuring pass asks the panel how wide it wants to be, so there is no definite width for a zero basis to grow into: the row's content size is nothing, the title collapses, and the panel holds that width. The reference implementation writesflex: 1on the same node and gets away with it because their measuring pass hands the panel a definite width — ours asks a question a zero basis cannot answer.flexGrow: 1, flexShrink: 1, flexBasis: 'auto'fills the row exactly the same once the width is known, and starts from the content rather than from zero.useAnchoredPositionnow says so where anyone writing the next anchored panel will read it.Menu.Contentalso takes a measure of its own, fifteen ems against thePopover's thirteen: a menu row is a title with an indicator beside it and sometimes a sentence under it, where a popover is prose alone.SubMenuis not here. The reference implementation ships it as its own component and it needs a second anchored panel whose trigger is a row of the first, which is worth its own change.