@floegence/floe-webapp-core 0.77.3 → 0.78.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/dist/components/layout/MobileNavigationPanel.d.ts +20 -0
- package/dist/components/layout/MobileNavigationPanel.js +95 -0
- package/dist/components/layout/MobileTabBar.d.ts +2 -0
- package/dist/components/layout/MobileTabBar.js +95 -71
- package/dist/components/layout/Shell.d.ts +8 -0
- package/dist/components/layout/Shell.js +248 -213
- package/dist/components/layout/index.d.ts +1 -0
- package/dist/components/ui/Button.js +3 -3
- package/dist/components/ui/Dropdown.js +5 -5
- package/dist/components/ui/Input.js +36 -36
- package/dist/hooks/useOverlayMask.d.ts +2 -0
- package/dist/hooks/useOverlayMask.js +75 -70
- package/dist/primitives.css +22 -0
- package/dist/styles/tokens.d.ts +12 -0
- package/dist/styles/tokens.js +6 -0
- package/dist/styles.css +1 -1
- package/dist/ui.css +27 -25
- package/package.json +1 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type JSX } from 'solid-js';
|
|
2
|
+
export interface MobileNavigationPanelProps {
|
|
3
|
+
id: string;
|
|
4
|
+
open: boolean;
|
|
5
|
+
title: string;
|
|
6
|
+
children: JSX.Element;
|
|
7
|
+
onOpenChange: (open: boolean) => void;
|
|
8
|
+
trigger?: HTMLElement | null;
|
|
9
|
+
/** Null allows content with its own identity and close controls. */
|
|
10
|
+
header?: JSX.Element;
|
|
11
|
+
closeLabel?: string;
|
|
12
|
+
class?: string;
|
|
13
|
+
contentClass?: string;
|
|
14
|
+
onKeyDown?: JSX.EventHandler<HTMLDivElement, KeyboardEvent>;
|
|
15
|
+
onPresenceChange?: (present: boolean) => void;
|
|
16
|
+
}
|
|
17
|
+
/** Shell-owned navigation surface; its backdrop never covers the bottom navigation. */
|
|
18
|
+
export declare function MobileNavigationPanel(props: MobileNavigationPanelProps & {
|
|
19
|
+
navigation: () => HTMLElement | undefined;
|
|
20
|
+
}): JSX.Element;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { createComponent as b, use as E, setAttribute as a, insert as f, effect as S, memo as N, className as P, template as g, delegateEvents as T } from "solid-js/web";
|
|
2
|
+
import { createUniqueId as j, createEffect as M, onCleanup as q, createMemo as A, Show as _, untrack as I } from "solid-js";
|
|
3
|
+
import { useOverlayMask as K } from "../../hooks/useOverlayMask.js";
|
|
4
|
+
import { createFloatingPresence as O } from "../ui/floatingPresence.js";
|
|
5
|
+
import { cn as F } from "../../utils/cn.js";
|
|
6
|
+
import { deferAfterPaint as z } from "../../utils/defer.js";
|
|
7
|
+
import { X as L } from "../icons/index.js";
|
|
8
|
+
var R = /* @__PURE__ */ g('<header class="flex shrink-0 items-center gap-2 border-b px-4 py-2"><h2 class="min-w-0 flex-1 text-base font-semibold"></h2><button type=button data-floe-autofocus class="flex h-11 w-11 shrink-0 items-center justify-center rounded-md hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">'), U = /* @__PURE__ */ g('<div data-floe-mobile-navigation-overlay class="absolute inset-0 z-50 overflow-hidden p-2"><div class="absolute inset-0 floe-floating-presence floe-floating-backdrop floe-bottom-drawer-backdrop"data-floe-mobile-navigation-backdrop></div><div class="relative pointer-events-none flex h-full min-h-0 items-end justify-center"><div role=dialog tabindex=-1 data-floe-mobile-navigation-panel data-floe-surface=floating data-floe-surface-portal-layer=true style="max-height:min(680px, 86%);border-radius:24px"><div>'), W = /* @__PURE__ */ g("<h2 class=sr-only>");
|
|
9
|
+
function Z(t) {
|
|
10
|
+
const u = `mobile-navigation-${j()}`, r = O({
|
|
11
|
+
open: () => t.open,
|
|
12
|
+
exitDurationMs: 180
|
|
13
|
+
});
|
|
14
|
+
let i, d = null;
|
|
15
|
+
const v = () => {
|
|
16
|
+
d = t.trigger ?? null, t.onOpenChange(!1);
|
|
17
|
+
};
|
|
18
|
+
M(() => {
|
|
19
|
+
const n = r.mounted();
|
|
20
|
+
if (t.onPresenceChange?.(n), !n && d) {
|
|
21
|
+
const l = d;
|
|
22
|
+
d = null, l.isConnected && !l.closest("[hidden], [inert]") && l.focus({
|
|
23
|
+
preventScroll: !0
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}), q(() => t.onPresenceChange?.(!1)), M(() => {
|
|
27
|
+
const n = t.id;
|
|
28
|
+
t.open && (d = null, z(() => I(() => {
|
|
29
|
+
if (!t.open || t.id !== n || !i?.isConnected) return;
|
|
30
|
+
const l = i.ownerDocument.activeElement;
|
|
31
|
+
l && i.contains(l) || (i.querySelector("[data-floe-autofocus]") ?? i).focus({
|
|
32
|
+
preventScroll: !0
|
|
33
|
+
});
|
|
34
|
+
})));
|
|
35
|
+
}), K({
|
|
36
|
+
open: r.mounted,
|
|
37
|
+
root: () => i,
|
|
38
|
+
focusRoots: () => [i, t.navigation()].filter((n) => !!n),
|
|
39
|
+
containsTarget: (n) => n instanceof Node && !!(i?.contains(n) || t.navigation()?.contains(n)),
|
|
40
|
+
onClose: v,
|
|
41
|
+
lockBodyScroll: !1,
|
|
42
|
+
trapFocus: !0,
|
|
43
|
+
blockWheel: "outside",
|
|
44
|
+
blockTouchMove: "outside",
|
|
45
|
+
escapeKeyPhase: "bubble",
|
|
46
|
+
autoFocus: !1,
|
|
47
|
+
restoreFocus: !1
|
|
48
|
+
});
|
|
49
|
+
const B = A(() => t.children);
|
|
50
|
+
return b(_, {
|
|
51
|
+
get when() {
|
|
52
|
+
return r.mounted();
|
|
53
|
+
},
|
|
54
|
+
get children() {
|
|
55
|
+
var n = U(), l = n.firstChild, D = l.nextSibling, o = D.firstChild, m = o.firstChild;
|
|
56
|
+
l.$$click = () => {
|
|
57
|
+
t.open && v();
|
|
58
|
+
}, o.$$keydown = (e) => t.onKeyDown?.(e);
|
|
59
|
+
var h = i;
|
|
60
|
+
return typeof h == "function" ? E(h, o) : i = o, a(o, "aria-labelledby", u), f(o, b(_, {
|
|
61
|
+
get when() {
|
|
62
|
+
return t.header === void 0;
|
|
63
|
+
},
|
|
64
|
+
get fallback() {
|
|
65
|
+
return [(() => {
|
|
66
|
+
var e = W();
|
|
67
|
+
return a(e, "id", u), f(e, () => t.title), e;
|
|
68
|
+
})(), N(() => t.header)];
|
|
69
|
+
},
|
|
70
|
+
get children() {
|
|
71
|
+
var e = R(), s = e.firstChild, c = s.nextSibling;
|
|
72
|
+
return a(s, "id", u), f(s, () => t.title), c.$$click = v, f(c, b(L, {
|
|
73
|
+
class: "h-5 w-5"
|
|
74
|
+
})), S(() => a(c, "aria-label", t.closeLabel ?? "Close")), e;
|
|
75
|
+
}
|
|
76
|
+
}), m), f(m, B), S((e) => {
|
|
77
|
+
var s = r.state(), c = r.state(), x = t.id, w = r.state(), y = r.exiting(), k = r.exiting() ? "true" : void 0, C = F("pointer-events-auto relative flex min-h-0 w-full max-w-[640px] flex-col border border-border bg-card text-card-foreground shadow-xl floe-floating-presence floe-bottom-drawer-panel", t.class), $ = F("flex min-h-0 flex-col overflow-auto overscroll-contain", t.contentClass);
|
|
78
|
+
return s !== e.e && a(n, "data-floating-presence", e.e = s), c !== e.t && a(l, "data-floating-presence", e.t = c), x !== e.a && a(o, "id", e.a = x), w !== e.o && a(o, "data-floating-presence", e.o = w), y !== e.i && (o.inert = e.i = y), k !== e.n && a(o, "aria-hidden", e.n = k), C !== e.s && P(o, e.s = C), $ !== e.h && P(m, e.h = $), e;
|
|
79
|
+
}, {
|
|
80
|
+
e: void 0,
|
|
81
|
+
t: void 0,
|
|
82
|
+
a: void 0,
|
|
83
|
+
o: void 0,
|
|
84
|
+
i: void 0,
|
|
85
|
+
n: void 0,
|
|
86
|
+
s: void 0,
|
|
87
|
+
h: void 0
|
|
88
|
+
}), n;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
T(["click", "keydown"]);
|
|
93
|
+
export {
|
|
94
|
+
Z as MobileNavigationPanel
|
|
95
|
+
};
|
|
@@ -11,6 +11,8 @@ export interface MobileTabBarItem extends Pick<ActivityBarItem, 'buttonRef' | 'a
|
|
|
11
11
|
onClick?: () => void;
|
|
12
12
|
}
|
|
13
13
|
export interface MobileTabBarProps {
|
|
14
|
+
ref?: (element: HTMLElement) => void;
|
|
15
|
+
actions?: MobileTabBarItem[];
|
|
14
16
|
hidden?: boolean;
|
|
15
17
|
items: MobileTabBarItem[];
|
|
16
18
|
activeId: string;
|
|
@@ -1,106 +1,129 @@
|
|
|
1
|
-
import { insert as
|
|
2
|
-
import { createSignal as
|
|
3
|
-
import { cn as
|
|
4
|
-
import { deferNonBlocking as
|
|
5
|
-
var
|
|
6
|
-
function
|
|
7
|
-
let
|
|
8
|
-
const [
|
|
9
|
-
let
|
|
1
|
+
import { use as R, insert as u, createComponent as d, effect as _, className as C, setAttribute as s, template as v, Dynamic as j, memo as q, delegateEvents as B } from "solid-js/web";
|
|
2
|
+
import { createSignal as E, onMount as z, onCleanup as D, Show as S, For as F } from "solid-js";
|
|
3
|
+
import { cn as A } from "../../utils/cn.js";
|
|
4
|
+
import { deferNonBlocking as W } from "../../utils/defer.js";
|
|
5
|
+
var H = /* @__PURE__ */ v('<div class="absolute left-0 top-0 bottom-0 w-8 bg-gradient-to-r from-background to-transparent z-10 pointer-events-none">'), N = /* @__PURE__ */ v('<div class="absolute right-0 top-0 bottom-0 w-8 bg-gradient-to-l from-background to-transparent z-10 pointer-events-none">'), T = /* @__PURE__ */ v('<div data-floe-mobile-navigation-actions class="flex shrink-0 border-l border-border">'), P = /* @__PURE__ */ v('<nav data-floe-shell-slot=mobile-tab-bar style=border-top-color:var(--bottom-bar-border)><div class="relative flex h-14"><div class="relative min-w-0 flex-1"><div class="h-full flex items-center overflow-x-auto scrollbar-hide snap-x snap-mandatory"role=tablist aria-orientation=horizontal style=-webkit-overflow-scrolling:touch>'), U = /* @__PURE__ */ v("<span>"), V = /* @__PURE__ */ v('<div class="absolute bottom-0 left-1/2 -translate-x-1/2 w-8 h-0.5 bg-primary rounded-t">'), G = /* @__PURE__ */ v("<button type=button><div></div><span>");
|
|
6
|
+
function Y(e) {
|
|
7
|
+
let r;
|
|
8
|
+
const [$, b] = E(!1), [i, h] = E(!1);
|
|
9
|
+
let f = null;
|
|
10
10
|
const g = () => {
|
|
11
|
-
|
|
11
|
+
r && (b(r.scrollLeft > 0), h(r.scrollLeft < r.scrollWidth - r.clientWidth - 1));
|
|
12
12
|
}, t = () => {
|
|
13
|
-
if (
|
|
13
|
+
if (f === null) {
|
|
14
14
|
if (typeof requestAnimationFrame > "u") {
|
|
15
15
|
g();
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
f = requestAnimationFrame(() => {
|
|
19
|
+
f = null, g();
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
|
-
}, o = () => e.items,
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
25
|
-
if (
|
|
26
|
-
|
|
22
|
+
}, o = () => e.items, I = (l) => {
|
|
23
|
+
const a = o()[l];
|
|
24
|
+
if (a) {
|
|
25
|
+
if (a.onClick) {
|
|
26
|
+
W(() => a.onClick());
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
|
-
e.onSelect(
|
|
29
|
+
e.onSelect(a.id);
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
|
-
return
|
|
32
|
+
return z(() => {
|
|
33
33
|
g();
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
36
|
-
const
|
|
37
|
-
|
|
34
|
+
const l = e.items.findIndex((a) => a.id === e.activeId);
|
|
35
|
+
if (l > 0 && r) {
|
|
36
|
+
const a = r.scrollWidth / e.items.length;
|
|
37
|
+
r.scrollLeft = Math.max(0, a * l - r.clientWidth / 2 + a / 2);
|
|
38
38
|
}
|
|
39
|
-
}),
|
|
40
|
-
|
|
39
|
+
}), D(() => {
|
|
40
|
+
f !== null && typeof cancelAnimationFrame < "u" && (cancelAnimationFrame(f), f = null);
|
|
41
41
|
}), (() => {
|
|
42
|
-
var
|
|
43
|
-
|
|
42
|
+
var l = P(), a = l.firstChild, x = a.firstChild, m = x.firstChild, w = e.ref;
|
|
43
|
+
typeof w == "function" ? R(w, l) : e.ref = l, u(x, d(S, {
|
|
44
44
|
get when() {
|
|
45
|
-
return
|
|
45
|
+
return $();
|
|
46
46
|
},
|
|
47
47
|
get children() {
|
|
48
|
-
return
|
|
48
|
+
return H();
|
|
49
49
|
}
|
|
50
|
-
}),
|
|
50
|
+
}), m), u(x, d(S, {
|
|
51
51
|
get when() {
|
|
52
|
-
return
|
|
52
|
+
return i();
|
|
53
53
|
},
|
|
54
54
|
get children() {
|
|
55
|
-
return
|
|
55
|
+
return N();
|
|
56
56
|
}
|
|
57
|
-
}),
|
|
58
|
-
var
|
|
59
|
-
return typeof
|
|
57
|
+
}), m), m.addEventListener("scroll", t);
|
|
58
|
+
var y = r;
|
|
59
|
+
return typeof y == "function" ? R(y, m) : r = m, u(m, d(F, {
|
|
60
60
|
get each() {
|
|
61
61
|
return e.items;
|
|
62
62
|
},
|
|
63
|
-
children: (
|
|
64
|
-
item:
|
|
63
|
+
children: (n, c) => d(M, {
|
|
64
|
+
item: n,
|
|
65
65
|
get isActive() {
|
|
66
|
-
return e.activeId ===
|
|
66
|
+
return e.activeId === n.id;
|
|
67
67
|
},
|
|
68
68
|
get index() {
|
|
69
|
-
return
|
|
69
|
+
return c();
|
|
70
70
|
},
|
|
71
71
|
get itemCount() {
|
|
72
72
|
return e.items.length;
|
|
73
73
|
},
|
|
74
74
|
onClick: () => {
|
|
75
75
|
"vibrate" in navigator && navigator.vibrate(10);
|
|
76
|
-
const
|
|
77
|
-
|
|
76
|
+
const k = n.onClick, L = e.onSelect, K = n.id;
|
|
77
|
+
n.onClick ? W(() => k()) : L(K);
|
|
78
78
|
},
|
|
79
|
-
onKeyboardSelect: (
|
|
79
|
+
onKeyboardSelect: (k) => I(k)
|
|
80
80
|
})
|
|
81
|
-
})),
|
|
82
|
-
|
|
81
|
+
})), u(a, d(S, {
|
|
82
|
+
get when() {
|
|
83
|
+
return e.actions?.length;
|
|
84
|
+
},
|
|
85
|
+
get children() {
|
|
86
|
+
var n = T();
|
|
87
|
+
return u(n, d(F, {
|
|
88
|
+
get each() {
|
|
89
|
+
return e.actions;
|
|
90
|
+
},
|
|
91
|
+
children: (c) => d(M, {
|
|
92
|
+
item: c,
|
|
93
|
+
action: !0,
|
|
94
|
+
isActive: !1,
|
|
95
|
+
index: 0,
|
|
96
|
+
itemCount: 1,
|
|
97
|
+
onKeyboardSelect: () => {
|
|
98
|
+
},
|
|
99
|
+
onClick: () => c.onClick?.()
|
|
100
|
+
})
|
|
101
|
+
})), n;
|
|
102
|
+
}
|
|
103
|
+
}), null), _((n) => {
|
|
104
|
+
var c = e.hidden, k = A(
|
|
83
105
|
// Same safe-area rule as TopBar: keep the visual bar height stable, and
|
|
84
106
|
// add safe-area padding on an outer wrapper (avoid squeezing content).
|
|
85
107
|
"relative shrink-0 bg-background border-t border-border safe-bottom safe-left safe-right",
|
|
86
108
|
e.class
|
|
87
|
-
),
|
|
88
|
-
return
|
|
109
|
+
), L = e.ariaLabel;
|
|
110
|
+
return c !== n.e && (l.hidden = n.e = c), k !== n.t && C(l, n.t = k), L !== n.a && s(l, "aria-label", n.a = L), n;
|
|
89
111
|
}, {
|
|
90
112
|
e: void 0,
|
|
91
113
|
t: void 0,
|
|
92
114
|
a: void 0
|
|
93
|
-
}),
|
|
115
|
+
}), l;
|
|
94
116
|
})();
|
|
95
117
|
}
|
|
96
|
-
function
|
|
97
|
-
let
|
|
98
|
-
const
|
|
99
|
-
|
|
118
|
+
function M(e) {
|
|
119
|
+
let r;
|
|
120
|
+
const $ = () => typeof e.item.ariaExpanded == "function" ? e.item.ariaExpanded() : e.item.ariaExpanded;
|
|
121
|
+
z(() => e.item.buttonRef?.(r ?? null)), D(() => e.item.buttonRef?.(null));
|
|
100
122
|
const b = () => typeof e.item.badge == "function" ? e.item.badge() : e.item.badge;
|
|
101
123
|
return (() => {
|
|
102
|
-
var
|
|
103
|
-
|
|
124
|
+
var i = G(), h = i.firstChild, f = h.nextSibling;
|
|
125
|
+
i.$$keydown = (t) => {
|
|
126
|
+
if (e.action) return;
|
|
104
127
|
let o = null;
|
|
105
128
|
switch (t.key) {
|
|
106
129
|
case "ArrowRight":
|
|
@@ -121,34 +144,34 @@ function P(e) {
|
|
|
121
144
|
return;
|
|
122
145
|
}
|
|
123
146
|
t.preventDefault(), e.onKeyboardSelect(o);
|
|
124
|
-
},
|
|
125
|
-
var g =
|
|
126
|
-
return typeof g == "function" ?
|
|
147
|
+
}, i.$$click = () => e.onClick();
|
|
148
|
+
var g = r;
|
|
149
|
+
return typeof g == "function" ? R(g, i) : r = i, u(h, d(j, {
|
|
127
150
|
get component() {
|
|
128
151
|
return e.item.icon;
|
|
129
152
|
},
|
|
130
153
|
class: "w-6 h-6"
|
|
131
|
-
}), null),
|
|
154
|
+
}), null), u(h, d(S, {
|
|
132
155
|
get when() {
|
|
133
156
|
return b();
|
|
134
157
|
},
|
|
135
158
|
get children() {
|
|
136
|
-
var t =
|
|
137
|
-
return
|
|
138
|
-
var o =
|
|
159
|
+
var t = U();
|
|
160
|
+
return u(t, (() => {
|
|
161
|
+
var o = q(() => typeof b() == "number" && b() > 99);
|
|
139
162
|
return () => o() ? "99+" : b();
|
|
140
|
-
})()),
|
|
163
|
+
})()), _(() => C(t, A("absolute -top-1 -right-2 min-w-4 h-4 px-1", "flex items-center justify-center", "text-[10px] font-medium rounded-full", "bg-primary text-primary-foreground"))), t;
|
|
141
164
|
}
|
|
142
|
-
}), null),
|
|
165
|
+
}), null), u(f, () => e.item.label), u(i, d(S, {
|
|
143
166
|
get when() {
|
|
144
167
|
return e.isActive;
|
|
145
168
|
},
|
|
146
169
|
get children() {
|
|
147
|
-
return
|
|
170
|
+
return V();
|
|
148
171
|
}
|
|
149
|
-
}), null),
|
|
150
|
-
var o =
|
|
151
|
-
return o !== t.e &&
|
|
172
|
+
}), null), _((t) => {
|
|
173
|
+
var o = A("relative flex-shrink-0 flex flex-col items-center justify-center", "min-w-16 h-full px-4 snap-center", "transition-[color] duration-150", "focus:outline-none focus-visible:bg-muted", e.action && "w-16 px-1", $() && "bg-muted text-foreground", e.isActive ? "text-primary" : "text-muted-foreground active:text-foreground"), I = e.item.label, l = e.action ? void 0 : e.isActive, a = $(), x = e.item.ariaControls, m = e.item.ariaHasPopup, w = e.action ? void 0 : "tab", y = e.action || e.isActive ? 0 : -1, n = A("relative transition-transform duration-150", e.isActive && "scale-110"), c = A("mt-1 text-[10px] font-medium truncate max-w-full", e.isActive && "font-semibold");
|
|
174
|
+
return o !== t.e && C(i, t.e = o), I !== t.t && s(i, "aria-label", t.t = I), l !== t.a && s(i, "aria-selected", t.a = l), a !== t.o && s(i, "aria-expanded", t.o = a), x !== t.i && s(i, "aria-controls", t.i = x), m !== t.n && s(i, "aria-haspopup", t.n = m), w !== t.s && s(i, "role", t.s = w), y !== t.h && s(i, "tabindex", t.h = y), n !== t.r && C(h, t.r = n), c !== t.d && C(f, t.d = c), t;
|
|
152
175
|
}, {
|
|
153
176
|
e: void 0,
|
|
154
177
|
t: void 0,
|
|
@@ -158,11 +181,12 @@ function P(e) {
|
|
|
158
181
|
n: void 0,
|
|
159
182
|
s: void 0,
|
|
160
183
|
h: void 0,
|
|
161
|
-
r: void 0
|
|
162
|
-
|
|
184
|
+
r: void 0,
|
|
185
|
+
d: void 0
|
|
186
|
+
}), i;
|
|
163
187
|
})();
|
|
164
188
|
}
|
|
165
|
-
|
|
189
|
+
B(["click", "keydown"]);
|
|
166
190
|
export {
|
|
167
|
-
|
|
191
|
+
Y as MobileTabBar
|
|
168
192
|
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type JSX } from 'solid-js';
|
|
2
|
+
import { type MobileTabBarItem } from './MobileTabBar';
|
|
3
|
+
import { type MobileNavigationPanelProps } from './MobileNavigationPanel';
|
|
2
4
|
import { type ActivityBarItem } from './ActivityBar';
|
|
3
5
|
import type { SidebarVisibilityMotion } from '../../context/LayoutContext';
|
|
4
6
|
import { type UIFirstSelectionEvent } from '../../utils/uiFirstSelection';
|
|
@@ -25,6 +27,12 @@ export interface ShellSlotClassNames {
|
|
|
25
27
|
mobileTabBar?: string;
|
|
26
28
|
}
|
|
27
29
|
export interface ShellProps {
|
|
30
|
+
/** Defaults to visible; hidden transfers the top safe area to Shell. */
|
|
31
|
+
topBarMobileMode?: 'visible' | 'hidden';
|
|
32
|
+
/** Fixed actions outside the horizontally scrolling mobile tabs. */
|
|
33
|
+
mobileNavigationActions?: MobileTabBarItem[];
|
|
34
|
+
/** A controlled navigation surface above the persistent mobile tab bar. */
|
|
35
|
+
mobileNavigationPanel?: MobileNavigationPanelProps;
|
|
28
36
|
children: JSX.Element;
|
|
29
37
|
/** Fill a containing AppViewport or embedded host instead of the document viewport. */
|
|
30
38
|
fillParent?: boolean;
|