@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 +9 -0
- package/dist/lib/popup-boundary.mjs +8 -6
- package/package.json +1 -1
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,
|