@botiverse/raft-ui 0.96.0 → 0.96.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## [0.96.1](https://github.com/botiverse/raft-design/compare/v0.96.0...v0.96.1) (2026-11-13)
2
+
3
+ ### Fixed
4
+
5
+ - **A popup anchored in a sheet's body is always kept under the sheet's head, however little room its field has** ([Dialog › Popups in a sheet](https://raft-design.botiverse.build/components/dialog/#popups-in-a-sheet), [Drawer › Behavior](https://raft-design.botiverse.build/components/drawer/#behavior)). In `DialogSheetContent` below 768px, in a `Drawer` and under `SheetPopupBoundary`, the sheet no longer stops bounding a list whose field has little of the sheet's area on both sides: the list flips to the larger side, shrinks to it and scrolls. The `POPUP_ROOM_MIN_PX` constant in `lib/popup-boundary`, which no entry point exported, is removed.
6
+ - Why: the exception let the list open over the head in the commonest real case, a field in the middle of a sheet on a small phone with the keyboard up (about 130px on each side). There the list covered the head, or, when an app portaled it into the sheet's scrolling body, was drawn under the head, where its first rows could be neither seen nor pressed. A short list that scrolls can be used; one hidden under the head can't.
7
+ - Affects: a Select or Combobox list, a menu or a popover opened from a field with little room on both sides, which used to open over the head at its full height, now stays under the head at the height of the larger side less 12px: 128px with 140px of room, 88px with 100px, 48px with 60px. No popup sets a least height, so in a very short sheet a list can show one row or less. A popup anchored in the head, a sheet with no head, a centered dialog and a popup with its own `collisionBoundary` are unchanged (`"clipping-ancestors"` still opts one out).
8
+ - Docs: https://raft-design.botiverse.build/components/dialog/#popups-in-a-sheet
9
+
1
10
  ## [0.96.0](https://github.com/botiverse/raft-design/compare/v0.95.4...v0.96.0) (2026-11-13)
2
11
 
3
12
  ### Changed
@@ -123,10 +123,15 @@ function nextFrame(clear) {
123
123
  *
124
124
  * - the popup's anchor is inside the head (a tooltip or a menu on a head
125
125
  * button belongs above or over the head, not under it);
126
- * - neither side of the anchor has `POPUP_ROOM_MIN_PX` of the area: a list
127
- * held there would show a row or two, so it opens over the head instead;
128
126
  * - the sheet has no head, or nothing visible under it.
129
127
  *
128
+ * While the anchor is in the sheet's body the area always bounds the popup,
129
+ * however little of it either side of the anchor has: the list takes the
130
+ * larger side and scrolls. On a small phone with the keyboard up a field in
131
+ * the middle of a sheet has about 130px each side; a short list there can be
132
+ * used, and one let over the head covers it, or, portaled into the sheet's
133
+ * scrolling body, is drawn under it, where its first rows can't be pressed.
134
+ *
130
135
  * The anchor is the popup's own `anchor` prop when `anchor` returns one that
131
136
  * resolves to something (resolvePopupAnchor), and the trigger found in the
132
137
  * page otherwise (findPopupAnchor). A virtual anchor has no element, so it is
@@ -175,17 +180,14 @@ function sheetPopupBoundary(sheet, popup = () => null, anchor = () => void 0) {
175
180
  const positioner = popup();
176
181
  const target = resolvePopupAnchor(anchor()) ?? lookUp(positioner);
177
182
  if (target) {
178
- const anchorBox = target.getBoundingClientRect();
179
183
  if (isElement(target)) {
180
184
  if (head.contains(target)) return null;
181
185
  } else {
186
+ const anchorBox = target.getBoundingClientRect();
182
187
  const x = (anchorBox.left + anchorBox.right) / 2;
183
188
  const y = (anchorBox.top + anchorBox.bottom) / 2;
184
189
  if (x >= headBox.left && x <= headBox.right && y >= headBox.top && y <= headBox.bottom) return null;
185
190
  }
186
- const above = Math.min(anchorBox.top, bottom) - top;
187
- const below = bottom - Math.max(anchorBox.bottom, top);
188
- if (Math.max(above, below) < 150) return null;
189
191
  }
190
192
  return {
191
193
  top: top + visualViewportShift(positioner).y,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botiverse/raft-ui",
3
- "version": "0.96.0",
3
+ "version": "0.96.1",
4
4
  "description": "React components and CSS foundations for the Raft Design System.",
5
5
  "keywords": [
6
6
  "agent-skills",