@oxyhq/bloom 0.72.2 → 0.73.0
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/lib/commonjs/avatar-group/AvatarGroup.web.js +22 -21
- package/lib/commonjs/avatar-group/AvatarGroup.web.js.map +1 -1
- package/lib/commonjs/bottom-sheet/index.web.js +11 -6
- package/lib/commonjs/bottom-sheet/index.web.js.map +1 -1
- package/lib/commonjs/context-menu/index.web.js +20 -22
- package/lib/commonjs/context-menu/index.web.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.js +66 -70
- package/lib/commonjs/dialog/Dialog.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.web.js +49 -51
- package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
- package/lib/commonjs/fonts/font-data.web.js +22 -0
- package/lib/commonjs/fonts/font-data.web.js.map +1 -0
- package/lib/commonjs/menu/index.web.js +15 -11
- package/lib/commonjs/menu/index.web.js.map +1 -1
- package/lib/commonjs/overlay/index.js +133 -7
- package/lib/commonjs/overlay/index.js.map +1 -1
- package/lib/commonjs/overlay/stack.js +170 -0
- package/lib/commonjs/overlay/stack.js.map +1 -0
- package/lib/commonjs/overlay/use-overlay-layer.js +37 -0
- package/lib/commonjs/overlay/use-overlay-layer.js.map +1 -0
- package/lib/commonjs/popover/index.web.js +31 -34
- package/lib/commonjs/popover/index.web.js.map +1 -1
- package/lib/commonjs/prompt-input/PromptInput.js +33 -29
- package/lib/commonjs/prompt-input/PromptInput.js.map +1 -1
- package/lib/commonjs/select/index.web.js +20 -22
- package/lib/commonjs/select/index.web.js.map +1 -1
- package/lib/commonjs/styles/z-index.js +33 -34
- package/lib/commonjs/styles/z-index.js.map +1 -1
- package/lib/commonjs/surfaces/SurfaceHost.js +3 -6
- package/lib/commonjs/surfaces/SurfaceHost.js.map +1 -1
- package/lib/commonjs/toast/ToastHost.js +9 -5
- package/lib/commonjs/toast/ToastHost.js.map +1 -1
- package/lib/commonjs/tooltip/index.js +9 -6
- package/lib/commonjs/tooltip/index.js.map +1 -1
- package/lib/commonjs/tooltip/index.web.js +8 -2
- package/lib/commonjs/tooltip/index.web.js.map +1 -1
- package/lib/commonjs/zoomable-image-gallery/ZoomableImageGallery.js +5 -5
- package/lib/commonjs/zoomable-image-gallery/ZoomableImageGallery.js.map +1 -1
- package/lib/module/avatar-group/AvatarGroup.web.js +21 -20
- package/lib/module/avatar-group/AvatarGroup.web.js.map +1 -1
- package/lib/module/bottom-sheet/index.web.js +11 -6
- package/lib/module/bottom-sheet/index.web.js.map +1 -1
- package/lib/module/context-menu/index.web.js +21 -23
- package/lib/module/context-menu/index.web.js.map +1 -1
- package/lib/module/dialog/Dialog.js +67 -71
- package/lib/module/dialog/Dialog.js.map +1 -1
- package/lib/module/dialog/Dialog.web.js +50 -52
- package/lib/module/dialog/Dialog.web.js.map +1 -1
- package/lib/module/fonts/font-data.web.js +18 -0
- package/lib/module/fonts/font-data.web.js.map +1 -0
- package/lib/module/menu/index.web.js +16 -12
- package/lib/module/menu/index.web.js.map +1 -1
- package/lib/module/overlay/index.js +99 -8
- package/lib/module/overlay/index.js.map +1 -1
- package/lib/module/overlay/stack.js +161 -0
- package/lib/module/overlay/stack.js.map +1 -0
- package/lib/module/overlay/use-overlay-layer.js +33 -0
- package/lib/module/overlay/use-overlay-layer.js.map +1 -0
- package/lib/module/popover/index.web.js +32 -34
- package/lib/module/popover/index.web.js.map +1 -1
- package/lib/module/prompt-input/PromptInput.js +33 -29
- package/lib/module/prompt-input/PromptInput.js.map +1 -1
- package/lib/module/select/index.web.js +21 -23
- package/lib/module/select/index.web.js.map +1 -1
- package/lib/module/styles/z-index.js +32 -30
- package/lib/module/styles/z-index.js.map +1 -1
- package/lib/module/surfaces/SurfaceHost.js +3 -6
- package/lib/module/surfaces/SurfaceHost.js.map +1 -1
- package/lib/module/toast/ToastHost.js +10 -6
- package/lib/module/toast/ToastHost.js.map +1 -1
- package/lib/module/tooltip/index.js +9 -6
- package/lib/module/tooltip/index.js.map +1 -1
- package/lib/module/tooltip/index.web.js +8 -2
- package/lib/module/tooltip/index.web.js.map +1 -1
- package/lib/module/zoomable-image-gallery/ZoomableImageGallery.js +5 -5
- package/lib/module/zoomable-image-gallery/ZoomableImageGallery.js.map +1 -1
- package/lib/typescript/commonjs/avatar-group/AvatarGroup.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/bottom-sheet/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/context-menu/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/Dialog.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/dialog/types.d.ts +0 -10
- package/lib/typescript/commonjs/dialog/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/fonts/font-data.web.d.ts +5 -0
- package/lib/typescript/commonjs/fonts/font-data.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/menu/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/overlay/index.d.ts +31 -6
- package/lib/typescript/commonjs/overlay/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/overlay/stack.d.ts +122 -0
- package/lib/typescript/commonjs/overlay/stack.d.ts.map +1 -0
- package/lib/typescript/commonjs/overlay/use-overlay-layer.d.ts +7 -0
- package/lib/typescript/commonjs/overlay/use-overlay-layer.d.ts.map +1 -0
- package/lib/typescript/commonjs/popover/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/prompt-input/PromptInput.d.ts.map +1 -1
- package/lib/typescript/commonjs/select/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/styles/z-index.d.ts +42 -29
- package/lib/typescript/commonjs/styles/z-index.d.ts.map +1 -1
- package/lib/typescript/commonjs/surfaces/SurfaceHost.d.ts.map +1 -1
- package/lib/typescript/commonjs/toast/ToastHost.d.ts.map +1 -1
- package/lib/typescript/commonjs/tooltip/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/zoomable-image-gallery/ZoomableImageGallery.d.ts.map +1 -1
- package/lib/typescript/module/avatar-group/AvatarGroup.web.d.ts.map +1 -1
- package/lib/typescript/module/bottom-sheet/index.web.d.ts.map +1 -1
- package/lib/typescript/module/context-menu/index.web.d.ts.map +1 -1
- package/lib/typescript/module/dialog/Dialog.d.ts.map +1 -1
- package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/module/dialog/types.d.ts +0 -10
- package/lib/typescript/module/dialog/types.d.ts.map +1 -1
- package/lib/typescript/module/fonts/font-data.web.d.ts +5 -0
- package/lib/typescript/module/fonts/font-data.web.d.ts.map +1 -0
- package/lib/typescript/module/menu/index.web.d.ts.map +1 -1
- package/lib/typescript/module/overlay/index.d.ts +31 -6
- package/lib/typescript/module/overlay/index.d.ts.map +1 -1
- package/lib/typescript/module/overlay/stack.d.ts +122 -0
- package/lib/typescript/module/overlay/stack.d.ts.map +1 -0
- package/lib/typescript/module/overlay/use-overlay-layer.d.ts +7 -0
- package/lib/typescript/module/overlay/use-overlay-layer.d.ts.map +1 -0
- package/lib/typescript/module/popover/index.web.d.ts.map +1 -1
- package/lib/typescript/module/prompt-input/PromptInput.d.ts.map +1 -1
- package/lib/typescript/module/select/index.web.d.ts.map +1 -1
- package/lib/typescript/module/styles/z-index.d.ts +42 -29
- package/lib/typescript/module/styles/z-index.d.ts.map +1 -1
- package/lib/typescript/module/surfaces/SurfaceHost.d.ts.map +1 -1
- package/lib/typescript/module/toast/ToastHost.d.ts.map +1 -1
- package/lib/typescript/module/tooltip/index.d.ts.map +1 -1
- package/lib/typescript/module/zoomable-image-gallery/ZoomableImageGallery.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/__tests__/ToastHostWebFork.test.ts +11 -3
- package/src/__tests__/overlay-stack-order.test.tsx +270 -0
- package/src/avatar-group/AvatarGroup.web.tsx +35 -31
- package/src/bottom-sheet/index.web.tsx +10 -5
- package/src/context-menu/index.web.tsx +33 -30
- package/src/dialog/Dialog.tsx +9 -18
- package/src/dialog/Dialog.web.tsx +62 -60
- package/src/dialog/types.ts +0 -10
- package/src/fonts/font-data.web.ts +15 -0
- package/src/menu/index.web.tsx +33 -22
- package/src/overlay/OverlayStacking.stories.tsx +207 -0
- package/src/overlay/index.tsx +114 -9
- package/src/overlay/stack.ts +166 -0
- package/src/overlay/use-overlay-layer.ts +39 -0
- package/src/popover/index.web.tsx +47 -44
- package/src/prompt-input/PromptInput.tsx +36 -29
- package/src/select/index.web.tsx +35 -32
- package/src/styles/z-index.ts +32 -34
- package/src/surfaces/SurfaceHost.tsx +3 -10
- package/src/toast/ToastHost.tsx +9 -6
- package/src/tooltip/index.tsx +14 -7
- package/src/tooltip/index.web.tsx +8 -2
- package/src/zoomable-image-gallery/ZoomableImageGallery.tsx +4 -4
|
@@ -10,9 +10,8 @@ import React, {
|
|
|
10
10
|
import { Pressable, StyleSheet, View } from 'react-native';
|
|
11
11
|
|
|
12
12
|
import { useTheme } from '../theme/use-theme';
|
|
13
|
-
import { Backdrop } from '../overlay';
|
|
13
|
+
import { Backdrop, OverlayRoot } from '../overlay';
|
|
14
14
|
import { Portal } from '../portal/index.web';
|
|
15
|
-
import { createOverlayZIndex } from '../styles/z-index';
|
|
16
15
|
import { WEB_POSITION_FIXED } from '../styles/web-view-style';
|
|
17
16
|
import { bloomShadowStyle } from '../design-tokens/shadows';
|
|
18
17
|
import { PopoverContext, usePopoverContext } from './context';
|
|
@@ -36,7 +35,6 @@ export type {
|
|
|
36
35
|
|
|
37
36
|
export { usePopoverContext };
|
|
38
37
|
|
|
39
|
-
const popoverZIndex = createOverlayZIndex();
|
|
40
38
|
|
|
41
39
|
/**
|
|
42
40
|
* Web self-contained control. Unlike native (which proxies a `BottomSheet`
|
|
@@ -262,45 +260,52 @@ export function PopoverContent({
|
|
|
262
260
|
|
|
263
261
|
return (
|
|
264
262
|
<Portal>
|
|
265
|
-
{
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
:
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
263
|
+
{/* `OverlayRoot` takes this surface's place in the open-order overlay
|
|
264
|
+
stack, so it paints above anything opened before it (see
|
|
265
|
+
`src/overlay/stack.ts`). It is `box-none`, so the area outside the
|
|
266
|
+
panel stays click-through and the backdrop below still takes its own
|
|
267
|
+
presses. */}
|
|
268
|
+
<OverlayRoot>
|
|
269
|
+
{dismissible ? (
|
|
270
|
+
<Backdrop
|
|
271
|
+
style={styles.backdrop}
|
|
272
|
+
onPress={() => control.close()}
|
|
273
|
+
accessibilityLabel="Dismiss popover"
|
|
274
|
+
/>
|
|
275
|
+
) : null}
|
|
276
|
+
<View
|
|
277
|
+
ref={panelRef}
|
|
278
|
+
accessibilityRole="none"
|
|
279
|
+
aria-label={label}
|
|
280
|
+
testID={testID}
|
|
281
|
+
onLayout={(e) =>
|
|
282
|
+
setPanelSize({
|
|
283
|
+
width: e.nativeEvent.layout.width,
|
|
284
|
+
height: e.nativeEvent.layout.height,
|
|
285
|
+
})
|
|
286
|
+
}
|
|
287
|
+
style={[
|
|
288
|
+
styles.panel,
|
|
289
|
+
{
|
|
290
|
+
left: position.left,
|
|
291
|
+
top: position.top,
|
|
292
|
+
minWidth: resolvedMinWidth,
|
|
293
|
+
maxWidth,
|
|
294
|
+
backgroundColor: theme.isDark
|
|
295
|
+
? theme.colors.backgroundSecondary
|
|
296
|
+
: theme.colors.background,
|
|
297
|
+
borderColor: theme.colors.borderLight,
|
|
298
|
+
// Design-system overlay elevation (`shadow-m`) as a `boxShadow` —
|
|
299
|
+
// RN-Web deprecated the `shadow*` style props.
|
|
300
|
+
...bloomShadowStyle('m'),
|
|
301
|
+
// Hide until measured to avoid a one-frame jump.
|
|
302
|
+
opacity: panelSize ? 1 : 0,
|
|
303
|
+
},
|
|
304
|
+
style,
|
|
305
|
+
]}>
|
|
306
|
+
{children}
|
|
307
|
+
</View>
|
|
308
|
+
</OverlayRoot>
|
|
304
309
|
</Portal>
|
|
305
310
|
);
|
|
306
311
|
}
|
|
@@ -315,12 +320,10 @@ const styles = StyleSheet.create({
|
|
|
315
320
|
left: 0,
|
|
316
321
|
right: 0,
|
|
317
322
|
bottom: 0,
|
|
318
|
-
zIndex: popoverZIndex.backdrop,
|
|
319
323
|
pointerEvents: 'auto',
|
|
320
324
|
},
|
|
321
325
|
panel: {
|
|
322
326
|
position: WEB_POSITION_FIXED,
|
|
323
|
-
zIndex: popoverZIndex.surface,
|
|
324
327
|
borderRadius: 12,
|
|
325
328
|
borderWidth: 1,
|
|
326
329
|
paddingVertical: 4,
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from 'react-native';
|
|
11
11
|
|
|
12
12
|
import { useTheme } from '../theme/use-theme';
|
|
13
|
+
import { OverlayRoot } from '../overlay';
|
|
13
14
|
import { Portal } from '../portal';
|
|
14
15
|
import { Z_INDEX } from '../styles/z-index';
|
|
15
16
|
import { PromptInputContext, type Attachment } from './context';
|
|
@@ -230,36 +231,42 @@ export function PromptInput({
|
|
|
230
231
|
|
|
231
232
|
{showFullscreen && (
|
|
232
233
|
<Portal>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
style={{
|
|
248
|
-
position: 'absolute',
|
|
249
|
-
top: 16,
|
|
250
|
-
right: 16,
|
|
251
|
-
zIndex: Z_INDEX.fullscreenControl,
|
|
252
|
-
padding: 8,
|
|
253
|
-
backgroundColor: theme.colors.background,
|
|
254
|
-
borderRadius: 9999,
|
|
255
|
-
}}
|
|
234
|
+
{/* `OverlayRoot` takes the fullscreen editor's place in the
|
|
235
|
+
open-order overlay stack (`src/overlay/stack.ts`). It mounts with
|
|
236
|
+
`showFullscreen`, so the rank tracks opening. */}
|
|
237
|
+
<OverlayRoot>
|
|
238
|
+
<View
|
|
239
|
+
style={[
|
|
240
|
+
StyleSheet.absoluteFill,
|
|
241
|
+
{
|
|
242
|
+
backgroundColor: theme.colors.background,
|
|
243
|
+
// Opt back in from the Portal root's `pointer-events: none`
|
|
244
|
+
// (web only — harmless on native).
|
|
245
|
+
pointerEvents: 'auto',
|
|
246
|
+
},
|
|
247
|
+
]}
|
|
256
248
|
>
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
249
|
+
<Pressable
|
|
250
|
+
onPress={() => setShowFullscreen(false)}
|
|
251
|
+
style={{
|
|
252
|
+
position: 'absolute',
|
|
253
|
+
top: 16,
|
|
254
|
+
right: 16,
|
|
255
|
+
// Above the editor's own body; where the editor sits relative
|
|
256
|
+
// to OTHER surfaces is the overlay stack's call.
|
|
257
|
+
zIndex: Z_INDEX.raised,
|
|
258
|
+
padding: 8,
|
|
259
|
+
backgroundColor: theme.colors.background,
|
|
260
|
+
borderRadius: 9999,
|
|
261
|
+
}}
|
|
262
|
+
>
|
|
263
|
+
{collapseIcon ?? (
|
|
264
|
+
<Text style={{ fontSize: 18, color: theme.colors.text }}>⤡</Text>
|
|
265
|
+
)}
|
|
266
|
+
</Pressable>
|
|
267
|
+
<View style={{ flex: 1 }}>{content}</View>
|
|
268
|
+
</View>
|
|
269
|
+
</OverlayRoot>
|
|
263
270
|
</Portal>
|
|
264
271
|
)}
|
|
265
272
|
</PromptInputContext.Provider>
|
package/src/select/index.web.tsx
CHANGED
|
@@ -12,9 +12,8 @@ import { Pressable, StyleSheet, View, type ViewStyle } from 'react-native';
|
|
|
12
12
|
|
|
13
13
|
import { useTheme } from '../theme/use-theme';
|
|
14
14
|
import { Text } from '../typography';
|
|
15
|
-
import { Backdrop } from '../overlay';
|
|
15
|
+
import { Backdrop, OverlayRoot } from '../overlay';
|
|
16
16
|
import { Portal } from '../portal/index.web';
|
|
17
|
-
import { createOverlayZIndex } from '../styles/z-index';
|
|
18
17
|
import { WEB_POSITION_FIXED } from '../styles/web-view-style';
|
|
19
18
|
import { resolveDropdownPlacement } from '../overlay/dropdown-placement';
|
|
20
19
|
import { bloomShadowStyle } from '../design-tokens/shadows';
|
|
@@ -39,7 +38,6 @@ import type {
|
|
|
39
38
|
|
|
40
39
|
export { useSelectItemContext };
|
|
41
40
|
|
|
42
|
-
const selectZIndex = createOverlayZIndex();
|
|
43
41
|
const VIEWPORT_GUTTER = 8;
|
|
44
42
|
const SELECT_OFFSET = 6;
|
|
45
43
|
|
|
@@ -259,33 +257,40 @@ export function SelectContent<T>({
|
|
|
259
257
|
|
|
260
258
|
return (
|
|
261
259
|
<Portal>
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
<
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
260
|
+
{/* `OverlayRoot` takes this surface's place in the open-order overlay
|
|
261
|
+
stack, so it paints above anything opened before it (see
|
|
262
|
+
`src/overlay/stack.ts`). It is `box-none`, so the area outside the
|
|
263
|
+
panel stays click-through and the backdrop below still takes its own
|
|
264
|
+
presses. */}
|
|
265
|
+
<OverlayRoot>
|
|
266
|
+
<Backdrop
|
|
267
|
+
style={styles.backdrop}
|
|
268
|
+
onPress={ctx.close}
|
|
269
|
+
accessibilityLabel="Close selection"
|
|
270
|
+
/>
|
|
271
|
+
<View
|
|
272
|
+
ref={attachDropdown}
|
|
273
|
+
accessibilityRole="list"
|
|
274
|
+
accessibilityLabel={label}
|
|
275
|
+
style={[
|
|
276
|
+
styles.dropdown,
|
|
277
|
+
{
|
|
278
|
+
backgroundColor: theme.isDark
|
|
279
|
+
? theme.colors.backgroundSecondary
|
|
280
|
+
: theme.colors.background,
|
|
281
|
+
borderColor: theme.colors.borderLight,
|
|
282
|
+
...bloomShadowStyle('m'),
|
|
283
|
+
},
|
|
284
|
+
position,
|
|
285
|
+
]}
|
|
286
|
+
>
|
|
287
|
+
{items.map((item, index) => (
|
|
288
|
+
<React.Fragment key={valueExtractor(item)}>
|
|
289
|
+
{renderItem(item, index, ctx.value)}
|
|
290
|
+
</React.Fragment>
|
|
291
|
+
))}
|
|
292
|
+
</View>
|
|
293
|
+
</OverlayRoot>
|
|
289
294
|
</Portal>
|
|
290
295
|
);
|
|
291
296
|
}
|
|
@@ -415,7 +420,6 @@ const styles = StyleSheet.create({
|
|
|
415
420
|
left: 0,
|
|
416
421
|
right: 0,
|
|
417
422
|
bottom: 0,
|
|
418
|
-
zIndex: selectZIndex.backdrop,
|
|
419
423
|
// Opt back in from the Portal root's `pointer-events: none`.
|
|
420
424
|
pointerEvents: 'auto',
|
|
421
425
|
},
|
|
@@ -428,7 +432,6 @@ const styles = StyleSheet.create({
|
|
|
428
432
|
position: WEB_POSITION_FIXED,
|
|
429
433
|
top: 0,
|
|
430
434
|
left: 0,
|
|
431
|
-
zIndex: selectZIndex.surface,
|
|
432
435
|
borderRadius: 8,
|
|
433
436
|
borderWidth: 1,
|
|
434
437
|
overflow: 'hidden',
|
package/src/styles/z-index.ts
CHANGED
|
@@ -1,47 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Stacking scale for stacking WITHIN a single context.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* ## What belongs here, and what does not
|
|
5
|
+
*
|
|
6
|
+
* These values order elements against their own siblings — a badge over its
|
|
7
|
+
* avatar, a floating control over the panel it sits on, a sheet's drag handle
|
|
8
|
+
* over the sheet body. That is a local decision with a local answer, so a
|
|
9
|
+
* constant is the right tool.
|
|
10
|
+
*
|
|
11
|
+
* **Which OVERLAY SURFACE is on top of which is NOT on this scale**, and must
|
|
12
|
+
* never be added back to it. That question is answered by open order — the
|
|
13
|
+
* surface the user opened last wins — and is owned by `src/overlay/stack.ts`.
|
|
14
|
+
*
|
|
15
|
+
* This file used to carry rungs for that too (`dropdown` 40/41, `overlay`
|
|
16
|
+
* 50/60, `tooltip` 70, `toast` 80, `fullscreen` 90/91), plus
|
|
17
|
+
* `createOverlayZIndex` / `createDropdownZIndex` / `Z_INDEX_LAYER_STEP` to
|
|
18
|
+
* offset them. Because a rung is fixed per COMPONENT KIND, it decided stacking
|
|
19
|
+
* by what a surface WAS rather than by when it opened, so some pairings were
|
|
20
|
+
* permanently inverted: a confirm dialog (50/60) opened from inside an open
|
|
21
|
+
* bottom sheet (999999) rendered underneath it and could not be pressed or
|
|
22
|
+
* dismissed, and a menu (40/41) opened from inside a dialog landed behind that
|
|
23
|
+
* dialog. Those rungs and helpers are gone; reintroducing one reintroduces the
|
|
24
|
+
* bug.
|
|
7
25
|
*/
|
|
8
26
|
export const Z_INDEX = {
|
|
27
|
+
/** Default resting level. */
|
|
9
28
|
base: 0,
|
|
29
|
+
/** One step above an immediate sibling — a badge over its avatar. */
|
|
10
30
|
raised: 1,
|
|
31
|
+
/** A control floating over the content it belongs to. */
|
|
11
32
|
floating: 10,
|
|
12
|
-
|
|
33
|
+
/** A dropdown's INLINE trigger wrapper, still in the app's document flow. */
|
|
13
34
|
dropdown: 40,
|
|
14
|
-
|
|
15
|
-
overlayBackdrop: 50,
|
|
16
|
-
overlaySurface: 60,
|
|
17
|
-
tooltip: 70,
|
|
18
|
-
toast: 80,
|
|
19
|
-
fullscreen: 90,
|
|
20
|
-
fullscreenControl: 91,
|
|
35
|
+
/** A bottom sheet's drag handle, over the sheet's own body. */
|
|
21
36
|
sheetHandle: 100,
|
|
37
|
+
/**
|
|
38
|
+
* The document-level portal container itself (`#bloom-portal-root`). Overlay
|
|
39
|
+
* surfaces render INSIDE it and order among themselves by open order — none
|
|
40
|
+
* of them may claim this value, which is what made the sheet unbeatable.
|
|
41
|
+
*/
|
|
22
42
|
portalRoot: 999999,
|
|
23
43
|
} as const;
|
|
24
44
|
|
|
25
|
-
export const Z_INDEX_LAYER_STEP = 10;
|
|
26
|
-
|
|
27
|
-
function layerOffset(layer = 0) {
|
|
28
|
-
return Math.max(0, Math.floor(layer)) * Z_INDEX_LAYER_STEP;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function createDropdownZIndex(layer = 0) {
|
|
32
|
-
const offset = layerOffset(layer);
|
|
33
|
-
return {
|
|
34
|
-
root: Z_INDEX.dropdown + offset,
|
|
35
|
-
surface: Z_INDEX.dropdownSurface + offset,
|
|
36
|
-
} as const;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function createOverlayZIndex(layer = 0) {
|
|
40
|
-
const offset = layerOffset(layer);
|
|
41
|
-
return {
|
|
42
|
-
backdrop: Z_INDEX.overlayBackdrop + offset,
|
|
43
|
-
surface: Z_INDEX.overlaySurface + offset,
|
|
44
|
-
} as const;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
45
|
export const zIndex = Z_INDEX;
|
|
@@ -67,13 +67,7 @@ export function createSurfaceHost(Dialog: DialogComponent) {
|
|
|
67
67
|
* dismiss REQUEST and has no post-exit callback, so it could never tell the
|
|
68
68
|
* store WHEN to splice the entry after the exit animation.
|
|
69
69
|
*/
|
|
70
|
-
function SurfaceLayer({
|
|
71
|
-
entry,
|
|
72
|
-
index,
|
|
73
|
-
}: {
|
|
74
|
-
entry: SurfaceEntry;
|
|
75
|
-
index: number;
|
|
76
|
-
}) {
|
|
70
|
+
function SurfaceLayer({ entry }: { entry: SurfaceEntry }) {
|
|
77
71
|
const control = useDialogControl();
|
|
78
72
|
const { id, status } = entry;
|
|
79
73
|
|
|
@@ -125,7 +119,6 @@ export function createSurfaceHost(Dialog: DialogComponent) {
|
|
|
125
119
|
<Dialog
|
|
126
120
|
control={control}
|
|
127
121
|
onClose={handleClose}
|
|
128
|
-
layer={index}
|
|
129
122
|
startOpen={status !== 'closing'}
|
|
130
123
|
{...placement}
|
|
131
124
|
>
|
|
@@ -144,8 +137,8 @@ export function createSurfaceHost(Dialog: DialogComponent) {
|
|
|
144
137
|
|
|
145
138
|
return (
|
|
146
139
|
<>
|
|
147
|
-
{stack.map((entry
|
|
148
|
-
<SurfaceLayer key={entry.id} entry={entry}
|
|
140
|
+
{stack.map((entry) => (
|
|
141
|
+
<SurfaceLayer key={entry.id} entry={entry} />
|
|
149
142
|
))}
|
|
150
143
|
</>
|
|
151
144
|
);
|
package/src/toast/ToastHost.tsx
CHANGED
|
@@ -26,10 +26,9 @@ import * as React from 'react';
|
|
|
26
26
|
import { StyleSheet } from 'react-native';
|
|
27
27
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
28
28
|
|
|
29
|
-
import { OverlayRoot } from '../overlay';
|
|
29
|
+
import { OverlayRoot, TOAST_LAYER_Z } from '../overlay';
|
|
30
30
|
import { Portal } from '../portal/index.web';
|
|
31
31
|
import { WEB_POSITION_FIXED } from '../styles/web-view-style';
|
|
32
|
-
import { Z_INDEX } from '../styles/z-index';
|
|
33
32
|
import type { ToastHostProps } from './types';
|
|
34
33
|
|
|
35
34
|
export function ToastHost({ children, ToasterOverlayWrapper }: ToastHostProps) {
|
|
@@ -37,7 +36,7 @@ export function ToastHost({ children, ToasterOverlayWrapper }: ToastHostProps) {
|
|
|
37
36
|
// `OverlayRoot` carries the pointer-events opt-in as a PROP; as a style
|
|
38
37
|
// entry it never reached the DOM, so the rows inherited the portal root's
|
|
39
38
|
// `pointer-events: none` and no toast could be pressed or swiped away.
|
|
40
|
-
<OverlayRoot style={styles.host}>
|
|
39
|
+
<OverlayRoot zIndex={TOAST_LAYER_Z} style={styles.host}>
|
|
41
40
|
{/* Also `box-none`: as the direct child of a box-none root it would
|
|
42
41
|
otherwise be handed `pointer-events: auto` and, spanning the whole
|
|
43
42
|
viewport, block the app underneath while a toast is up. */}
|
|
@@ -68,8 +67,12 @@ const styles = StyleSheet.create({
|
|
|
68
67
|
left: 0,
|
|
69
68
|
right: 0,
|
|
70
69
|
bottom: 0,
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
|
|
70
|
+
// The depth is `TOAST_LAYER_Z`, applied by `OverlayRoot` via its `zIndex`
|
|
71
|
+
// prop — a toast is a notification, not a modal surface, so it is pinned
|
|
72
|
+
// above the whole open-order overlay stack rather than taking a rank in it
|
|
73
|
+
// (see `src/overlay/stack.ts`). It must not be set here as well: a style
|
|
74
|
+
// z-index would fight the prop and, being a fixed number again, would land
|
|
75
|
+
// back under any surface that outranked it — which is how toasts were
|
|
76
|
+
// already being lost behind an open bottom sheet.
|
|
74
77
|
},
|
|
75
78
|
});
|
package/src/tooltip/index.tsx
CHANGED
|
@@ -18,6 +18,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
|
18
18
|
|
|
19
19
|
import { useTheme } from '../theme/use-theme';
|
|
20
20
|
import { atoms as a } from '../styles';
|
|
21
|
+
import { OverlayRoot } from '../overlay';
|
|
21
22
|
import { Portal } from '../portal';
|
|
22
23
|
import {
|
|
23
24
|
ARROW_HALF_SIZE,
|
|
@@ -173,13 +174,19 @@ export function TooltipContent({
|
|
|
173
174
|
|
|
174
175
|
return (
|
|
175
176
|
<Portal>
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
177
|
+
{/* `OverlayRoot` takes the tooltip's place in the open-order overlay
|
|
178
|
+
stack, so a tooltip opened over another surface paints above it (see
|
|
179
|
+
`src/overlay/stack.ts`). It mounts past the `visible` guard, so the
|
|
180
|
+
rank tracks opening. */}
|
|
181
|
+
<OverlayRoot>
|
|
182
|
+
<Bubble
|
|
183
|
+
label={label}
|
|
184
|
+
position={position}
|
|
185
|
+
targetMeasurements={targetMeasurements}
|
|
186
|
+
requestClose={requestClose}>
|
|
187
|
+
{children}
|
|
188
|
+
</Bubble>
|
|
189
|
+
</OverlayRoot>
|
|
183
190
|
</Portal>
|
|
184
191
|
);
|
|
185
192
|
}
|
|
@@ -3,8 +3,8 @@ import { Pressable, StyleSheet, View } from 'react-native';
|
|
|
3
3
|
|
|
4
4
|
import { useTheme } from '../theme/use-theme';
|
|
5
5
|
import { atoms as a, flatten } from '../styles';
|
|
6
|
-
import { Z_INDEX } from '../styles/z-index';
|
|
7
6
|
import { WEB_POSITION_FIXED } from '../styles/web-view-style';
|
|
7
|
+
import { Z_INDEX } from '../styles/z-index';
|
|
8
8
|
import {
|
|
9
9
|
ARROW_SIZE,
|
|
10
10
|
BUBBLE_MAX_WIDTH,
|
|
@@ -156,6 +156,12 @@ const webStyles = StyleSheet.create({
|
|
|
156
156
|
left: 0,
|
|
157
157
|
right: 0,
|
|
158
158
|
bottom: 0,
|
|
159
|
-
|
|
159
|
+
// In-flow depth, not an overlay-ordering one: the WEB tooltip is not
|
|
160
|
+
// portaled (unlike the native one) — the bubble is absolutely positioned
|
|
161
|
+
// against its trigger and renders inline. So this only lifts the
|
|
162
|
+
// outside-press catcher over adjacent content, and stays below the bubble's
|
|
163
|
+
// own `a.z_50`. Which SURFACE is on top is never decided here; see
|
|
164
|
+
// `src/overlay/stack.ts`.
|
|
165
|
+
zIndex: Z_INDEX.floating,
|
|
160
166
|
},
|
|
161
167
|
});
|
|
@@ -36,7 +36,6 @@ import {
|
|
|
36
36
|
ArrowRight_Stroke2_Corner0_Rounded,
|
|
37
37
|
ArrowOutOfBox_Stroke2_Corner0_Rounded,
|
|
38
38
|
} from '../icons';
|
|
39
|
-
import { Z_INDEX } from '../styles/z-index';
|
|
40
39
|
import { WEB_POSITION_FIXED, type WebCssStyle } from '../styles/web-view-style';
|
|
41
40
|
import {
|
|
42
41
|
getAspectRatio,
|
|
@@ -1039,14 +1038,15 @@ const styles = StyleSheet.create({
|
|
|
1039
1038
|
web: {
|
|
1040
1039
|
// Full-screen fixed overlay (web), like Bloom's Portal and Dialog.web.
|
|
1041
1040
|
// Only ever applied on web (this is the `web` arm of Platform.select),
|
|
1042
|
-
// so `WEB_POSITION_FIXED` is honest here
|
|
1043
|
-
//
|
|
1041
|
+
// so `WEB_POSITION_FIXED` is honest here. The depth is NOT set here:
|
|
1042
|
+
// `OverlayRoot` above assigns it from the open-order overlay stack, so
|
|
1043
|
+
// a viewer opened over another surface paints above it and one opened
|
|
1044
|
+
// under a later surface goes behind (see `src/overlay/stack.ts`).
|
|
1044
1045
|
position: WEB_POSITION_FIXED,
|
|
1045
1046
|
top: 0,
|
|
1046
1047
|
left: 0,
|
|
1047
1048
|
right: 0,
|
|
1048
1049
|
bottom: 0,
|
|
1049
|
-
zIndex: Z_INDEX.fullscreen,
|
|
1050
1050
|
},
|
|
1051
1051
|
default: {
|
|
1052
1052
|
// Mounted through the Bloom Portal `Outlet` (which renders its content
|