@oxy.so/bloom 4.1.0 → 4.2.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/docs/adoption-matrix.mdx +2 -2
- package/docs/app-shell.mdx +7 -0
- package/docs/bottom-bar.mdx +6 -0
- package/docs/settings-modal.mdx +8 -5
- package/lib/commonjs/app-shell/AppShellBars.js +8 -2
- package/lib/commonjs/app-shell/AppShellBars.js.map +1 -1
- package/lib/commonjs/app-shell/AppShellEngine.js +29 -6
- package/lib/commonjs/app-shell/AppShellEngine.js.map +1 -1
- package/lib/commonjs/bottom-bar/BottomBarBase.js +10 -2
- package/lib/commonjs/bottom-bar/BottomBarBase.js.map +1 -1
- package/lib/commonjs/layout/bottom-bar-slot.js +10 -0
- package/lib/commonjs/layout/bottom-bar-slot.js.map +1 -0
- package/lib/commonjs/settings-modal/SettingsModal.js +50 -135
- package/lib/commonjs/settings-modal/SettingsModal.js.map +1 -1
- package/lib/commonjs/sidebar/Sidebar.js +1 -1
- package/lib/commonjs/sidebar/Sidebar.js.map +1 -1
- package/lib/module/app-shell/AppShellBars.js +8 -2
- package/lib/module/app-shell/AppShellBars.js.map +1 -1
- package/lib/module/app-shell/AppShellEngine.js +30 -7
- package/lib/module/app-shell/AppShellEngine.js.map +1 -1
- package/lib/module/bottom-bar/BottomBarBase.js +11 -3
- package/lib/module/bottom-bar/BottomBarBase.js.map +1 -1
- package/lib/module/layout/bottom-bar-slot.js +7 -0
- package/lib/module/layout/bottom-bar-slot.js.map +1 -0
- package/lib/module/settings-modal/SettingsModal.js +43 -128
- package/lib/module/settings-modal/SettingsModal.js.map +1 -1
- package/lib/module/sidebar/Sidebar.js +1 -1
- package/lib/module/sidebar/Sidebar.js.map +1 -1
- package/lib/typescript/commonjs/app-shell/AppShellBars.d.ts +1 -0
- package/lib/typescript/commonjs/app-shell/AppShellBars.d.ts.map +1 -1
- package/lib/typescript/commonjs/app-shell/AppShellEngine.d.ts.map +1 -1
- package/lib/typescript/commonjs/bottom-bar/BottomBarBase.d.ts +1 -1
- package/lib/typescript/commonjs/bottom-bar/BottomBarBase.d.ts.map +1 -1
- package/lib/typescript/commonjs/bottom-bar/types.d.ts +4 -0
- package/lib/typescript/commonjs/bottom-bar/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/layout/bottom-bar-slot.d.ts +3 -0
- package/lib/typescript/commonjs/layout/bottom-bar-slot.d.ts.map +1 -0
- package/lib/typescript/commonjs/settings-modal/SettingsModal.d.ts +1 -1
- package/lib/typescript/commonjs/settings-modal/SettingsModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/settings-modal/types.d.ts +4 -2
- package/lib/typescript/commonjs/settings-modal/types.d.ts.map +1 -1
- package/lib/typescript/module/app-shell/AppShellBars.d.ts +1 -0
- package/lib/typescript/module/app-shell/AppShellBars.d.ts.map +1 -1
- package/lib/typescript/module/app-shell/AppShellEngine.d.ts.map +1 -1
- package/lib/typescript/module/bottom-bar/BottomBarBase.d.ts +1 -1
- package/lib/typescript/module/bottom-bar/BottomBarBase.d.ts.map +1 -1
- package/lib/typescript/module/bottom-bar/types.d.ts +4 -0
- package/lib/typescript/module/bottom-bar/types.d.ts.map +1 -1
- package/lib/typescript/module/layout/bottom-bar-slot.d.ts +3 -0
- package/lib/typescript/module/layout/bottom-bar-slot.d.ts.map +1 -0
- package/lib/typescript/module/settings-modal/SettingsModal.d.ts +1 -1
- package/lib/typescript/module/settings-modal/SettingsModal.d.ts.map +1 -1
- package/lib/typescript/module/settings-modal/types.d.ts +4 -2
- package/lib/typescript/module/settings-modal/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/app-shell/AppShellBars.tsx +5 -3
- package/src/app-shell/AppShellEngine.tsx +23 -8
- package/src/bottom-bar/BottomBarBase.tsx +7 -4
- package/src/bottom-bar/types.ts +4 -0
- package/src/layout/bottom-bar-slot.ts +4 -0
- package/src/settings-modal/SettingsModal.tsx +48 -136
- package/src/settings-modal/types.ts +4 -2
- package/src/sidebar/Sidebar.tsx +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { useRef, useState, type ComponentType } from 'react';
|
|
1
|
+
import { useContext, useRef, useState, type ComponentType } from 'react';
|
|
2
2
|
import { View, ScrollView, Keyboard, Platform } from 'react-native';
|
|
3
3
|
import { useEffect } from 'react';
|
|
4
4
|
import Animated, { useAnimatedReaction, useAnimatedStyle, interpolate, runOnJS, useReducedMotion } from 'react-native-reanimated';
|
|
5
5
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
6
|
+
import { BottomBarSlotContext } from '../layout/bottom-bar-slot';
|
|
6
7
|
import { useClaimBottomEdge } from '../layout/bottom-edge';
|
|
7
8
|
import { FAB_METRICS } from '../fab/constants';
|
|
8
9
|
import { windowEdgeGap } from '../layout/edge';
|
|
@@ -17,7 +18,7 @@ interface Props extends BottomBarProps {
|
|
|
17
18
|
Item: ComponentType<TabBarButtonProps>;
|
|
18
19
|
Blur: ComponentType<ProgressiveBlurProps>;
|
|
19
20
|
}
|
|
20
|
-
export function BottomBarBase({ Navigation, Item, Blur, items, value, onValueChange, action,
|
|
21
|
+
export function BottomBarBase({ Navigation, Item, Blur, items, value, onValueChange, activeProgress, onValueLongPress, action,
|
|
21
22
|
actionPlacement = 'auto', actionBehavior = 'hide', material = 'translucent', minimizeProgress, blur = true, maxWidth = 560, style, testID }: Props) {
|
|
22
23
|
const insets = useSafeAreaInsets();
|
|
23
24
|
const minimize = useMinimizeState();
|
|
@@ -45,14 +46,15 @@ export function BottomBarBase({ Navigation, Item, Blur, items, value, onValueCha
|
|
|
45
46
|
node.inert = actionHidden;
|
|
46
47
|
}, [actionHidden]);
|
|
47
48
|
const [keyboardVisible, setKeyboardVisible] = useState(false);
|
|
48
|
-
const
|
|
49
|
+
const suppliedBottomInset = useContext(BottomBarSlotContext);
|
|
50
|
+
const bottom = Math.max(0, windowEdgeGap(insets.bottom) - (suppliedBottomInset ?? 0));
|
|
49
51
|
useEffect(() => {
|
|
50
52
|
if (Platform.OS === 'web') return;
|
|
51
53
|
const show = Keyboard.addListener('keyboardDidShow', () => setKeyboardVisible(true));
|
|
52
54
|
const hide = Keyboard.addListener('keyboardDidHide', () => setKeyboardVisible(false));
|
|
53
55
|
return () => { show.remove(); hide.remove(); };
|
|
54
56
|
}, []);
|
|
55
|
-
useClaimBottomEdge(keyboardVisible ? 0 : bottom + footprint);
|
|
57
|
+
useClaimBottomEdge(keyboardVisible || suppliedBottomInset !== undefined ? 0 : bottom + footprint);
|
|
56
58
|
const rowStyle = useAnimatedStyle(() => ({
|
|
57
59
|
height: interpolate(reducedMotion ? Number(progress.value > 0.01) : progress.value, [0, 1], [EXPANDED_HEIGHT, MINIMIZED_HEIGHT], 'clamp'),
|
|
58
60
|
}), [progress, reducedMotion]);
|
|
@@ -70,6 +72,7 @@ export function BottomBarBase({ Navigation, Item, Blur, items, value, onValueCha
|
|
|
70
72
|
{blur && material === 'translucent' && <Blur direction="bottom" style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: bottom + footprint + BLUR_BLEED }} />}
|
|
71
73
|
<Animated.View testID={testID ? `${testID}-row` : undefined} onLayout={event => setRowWidth(event.nativeEvent.layout.width)} pointerEvents="box-none" style={[{ justifyContent: items.length ? 'center' : 'flex-end', alignSelf: 'center', width: '100%', maxWidth, paddingLeft: 12, paddingRight: 12, marginBottom: bottom, flexDirection: 'row', alignItems: 'center' }, rowStyle]}>
|
|
72
74
|
{items.length > 0 && <View testID={testID ? `${testID}-navigation` : undefined} style={{ width: navigationWidth, minWidth: 0 }}><ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ minWidth: '100%' }}><View style={{ width: Math.max(navigationWidth, items.length * 44 + 8) }}><Navigation scrollable={navigationWidth > 0 && navigationWidth < items.length * 44 + 8} embedded blur={false} material={material} minimizeProgress={progress}
|
|
75
|
+
activeProgress={activeProgress} onIndexLongPress={onValueLongPress ? index => { if (items[index]) onValueLongPress(items[index].name); } : undefined}
|
|
73
76
|
activeIndex={items.findIndex(item => item.name === value)} onIndexChange={index => { if (items[index]) onValueChange(items[index].name); }}>
|
|
74
77
|
{items.map((item, index) => <Item key={item.name} item={item} index={index} />)}
|
|
75
78
|
</Navigation></View></ScrollView></View>}
|
package/src/bottom-bar/types.ts
CHANGED
|
@@ -7,6 +7,10 @@ export interface BottomBarProps {
|
|
|
7
7
|
items: TabBarItem[];
|
|
8
8
|
value: string;
|
|
9
9
|
onValueChange: (value: string) => void;
|
|
10
|
+
/** Optional continuous selection supplied by a swipe pager, in item-index space. */
|
|
11
|
+
activeProgress?: SharedValue<number>;
|
|
12
|
+
/** Long press on a destination (for example an account switcher). */
|
|
13
|
+
onValueLongPress?: (value: string) => void;
|
|
10
14
|
/** Static action sibling; outside the navigation scrub detector. */
|
|
11
15
|
action?: ReactNode;
|
|
12
16
|
/** Auto places the action above navigation when side-by-side targets would be cramped. */
|
|
@@ -26,9 +26,10 @@ import Animated, {
|
|
|
26
26
|
|
|
27
27
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
28
28
|
|
|
29
|
-
import { RiArrowLeftSLine } from '../icons/remix/RiArrowLeftSLine';
|
|
30
29
|
import { RiArrowRightSLine } from '../icons/remix/RiArrowRightSLine';
|
|
31
30
|
import { RiCheckboxCircleFill } from '../icons/remix/RiCheckboxCircleFill';
|
|
31
|
+
import { PageHeader } from '../page-header';
|
|
32
|
+
import { ButtonGroup, ButtonGroupItem } from '../button-group';
|
|
32
33
|
import { RiCloseLine } from '../icons/remix/RiCloseLine';
|
|
33
34
|
import { VerticalFade } from './SettingsArt';
|
|
34
35
|
import { Backdrop, OverlayRoot } from '../overlay';
|
|
@@ -58,9 +59,7 @@ import { IS_WEB, useSettingsWebCss } from './web-css';
|
|
|
58
59
|
* 20px icon (icon/secondary) + 8 + body-medium label
|
|
59
60
|
* (selected: background/secondary/hover + text/primary;
|
|
60
61
|
* hover: background/secondary/hover @ 60%)
|
|
61
|
-
* content
|
|
62
|
-
* 24px round close (background/tertiary, hover tertiary/hover,
|
|
63
|
-
* 16px glyph); the page scrolls under a 40px top fade that eases
|
|
62
|
+
* content shared inline PageHeader and close ButtonGroup island; the page scrolls under a 40px top fade that eases
|
|
64
63
|
* in (200ms) once it is scrolled; px 32 pb 32
|
|
65
64
|
* toast "Saved" pill straddling the panel's bottom edge: 1px
|
|
66
65
|
* border/button, background/primary, py 4 pr 10 pl 6, gap 4,
|
|
@@ -133,6 +132,7 @@ export function SettingsModal({
|
|
|
133
132
|
page: controlledPage,
|
|
134
133
|
defaultPage,
|
|
135
134
|
onPageChange,
|
|
135
|
+
initialView = 'navigation',
|
|
136
136
|
labels,
|
|
137
137
|
testID,
|
|
138
138
|
}: SettingsModalProps) {
|
|
@@ -156,7 +156,9 @@ export function SettingsModal({
|
|
|
156
156
|
const insets = useSafeAreaInsets();
|
|
157
157
|
|
|
158
158
|
// `compact` layout is two levels: the section list, then a page pushed over it.
|
|
159
|
-
const [compactPageOpen, setCompactPageOpen] = useState(
|
|
159
|
+
const [compactPageOpen, setCompactPageOpen] = useState(initialView === 'page');
|
|
160
|
+
const initialViewRef = useRef(initialView);
|
|
161
|
+
initialViewRef.current = initialView;
|
|
160
162
|
|
|
161
163
|
const onCloseRef = useRef(onClose);
|
|
162
164
|
onCloseRef.current = onClose;
|
|
@@ -167,7 +169,7 @@ export function SettingsModal({
|
|
|
167
169
|
|
|
168
170
|
const show = useCallback(() => {
|
|
169
171
|
setInternalPage(defaultPageRef.current);
|
|
170
|
-
setCompactPageOpen(
|
|
172
|
+
setCompactPageOpen(initialViewRef.current === 'page');
|
|
171
173
|
setMounted(true);
|
|
172
174
|
setOpenCount((count) => count + 1);
|
|
173
175
|
}, []);
|
|
@@ -398,7 +400,7 @@ export function SettingsModal({
|
|
|
398
400
|
{layout === 'compact' ? (
|
|
399
401
|
compactPageOpen && pageConfig ? (
|
|
400
402
|
<View style={styles.content}>
|
|
401
|
-
<
|
|
403
|
+
<SettingsHeader
|
|
402
404
|
title={pageConfig.title}
|
|
403
405
|
onBack={() => setCompactPageOpen(false)}
|
|
404
406
|
backLabel={labels?.back ?? 'Back'}
|
|
@@ -419,7 +421,7 @@ export function SettingsModal({
|
|
|
419
421
|
</View>
|
|
420
422
|
) : (
|
|
421
423
|
<View style={styles.content}>
|
|
422
|
-
<
|
|
424
|
+
<SettingsHeader
|
|
423
425
|
title={labels?.dialog ?? 'Settings'}
|
|
424
426
|
closeLabel={closeLabel}
|
|
425
427
|
onClose={requestClose}
|
|
@@ -449,36 +451,18 @@ export function SettingsModal({
|
|
|
449
451
|
testID={testID}
|
|
450
452
|
/>
|
|
451
453
|
<View style={styles.content}>
|
|
452
|
-
<
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
paddingBottom: pageConfig?.compactTitle ? 6 : 12,
|
|
460
|
-
},
|
|
461
|
-
]}
|
|
462
|
-
testID={testID ? `${testID}-title-row` : undefined}
|
|
463
|
-
>
|
|
464
|
-
<Text
|
|
465
|
-
variant="title-3-medium"
|
|
466
|
-
role="heading"
|
|
467
|
-
style={{ color: palette.text }}
|
|
468
|
-
>
|
|
469
|
-
{pageConfig?.title ?? ''}
|
|
470
|
-
</Text>
|
|
471
|
-
<SettingsCloseButton
|
|
472
|
-
label={closeLabel}
|
|
473
|
-
onPress={requestClose}
|
|
474
|
-
palette={palette}
|
|
475
|
-
testID={testID ? `${testID}-close` : undefined}
|
|
476
|
-
/>
|
|
477
|
-
</View>
|
|
454
|
+
<SettingsHeader
|
|
455
|
+
title={pageConfig?.title ?? ''}
|
|
456
|
+
closeLabel={closeLabel}
|
|
457
|
+
onClose={requestClose}
|
|
458
|
+
palette={palette}
|
|
459
|
+
testID={testID}
|
|
460
|
+
/>
|
|
478
461
|
<PageScroller
|
|
479
462
|
key={currentPage}
|
|
480
463
|
palette={palette}
|
|
481
464
|
inset={CONTENT_INSET[layout]}
|
|
465
|
+
insetTop={pageConfig?.compactTitle ? 6 : 12}
|
|
482
466
|
testID={testID}
|
|
483
467
|
>
|
|
484
468
|
{pageConfig?.content}
|
|
@@ -638,42 +622,8 @@ function RailRow({
|
|
|
638
622
|
// Close button, scroller, toast
|
|
639
623
|
// ---------------------------------------------------------------------------
|
|
640
624
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
onPress,
|
|
644
|
-
palette,
|
|
645
|
-
testID,
|
|
646
|
-
}: {
|
|
647
|
-
label: string;
|
|
648
|
-
onPress: () => void;
|
|
649
|
-
palette: SettingsPalette;
|
|
650
|
-
testID?: string;
|
|
651
|
-
}) {
|
|
652
|
-
const [hovered, setHovered] = useState(false);
|
|
653
|
-
return (
|
|
654
|
-
<Pressable
|
|
655
|
-
role="button"
|
|
656
|
-
accessibilityLabel={label}
|
|
657
|
-
{...webDataSet({ bloomSettingsPress: '' })}
|
|
658
|
-
onPress={onPress}
|
|
659
|
-
onHoverIn={() => setHovered(true)}
|
|
660
|
-
onHoverOut={() => setHovered(false)}
|
|
661
|
-
testID={testID}
|
|
662
|
-
style={[
|
|
663
|
-
styles.close,
|
|
664
|
-
{ backgroundColor: hovered ? palette.tertiaryHover : palette.tertiary },
|
|
665
|
-
]}
|
|
666
|
-
>
|
|
667
|
-
<RiCloseLine width={16} height={16} fill={palette.iconSecondary} />
|
|
668
|
-
</Pressable>
|
|
669
|
-
);
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
/**
|
|
673
|
-
* The `compact` title bar: optional back chevron, the title, the close button —
|
|
674
|
-
* 56px, the page's 16px inset, hairline under it.
|
|
675
|
-
*/
|
|
676
|
-
function CompactHeader({
|
|
625
|
+
/** Shared header on every layout; the modal already owns safe-area insets. */
|
|
626
|
+
function SettingsHeader({
|
|
677
627
|
title,
|
|
678
628
|
onBack,
|
|
679
629
|
backLabel,
|
|
@@ -690,39 +640,34 @@ function CompactHeader({
|
|
|
690
640
|
palette: SettingsPalette;
|
|
691
641
|
testID?: string;
|
|
692
642
|
}) {
|
|
643
|
+
// Inline chrome does not reveal with scroll. An explicit local offset keeps
|
|
644
|
+
// the page behind the modal from influencing this header's paint or title.
|
|
645
|
+
const scrollY = useSharedValue(0);
|
|
693
646
|
return (
|
|
694
|
-
<
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
{
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
</Text>
|
|
719
|
-
<SettingsCloseButton
|
|
720
|
-
label={closeLabel}
|
|
721
|
-
onPress={onClose}
|
|
722
|
-
palette={palette}
|
|
723
|
-
testID={testID ? `${testID}-close` : undefined}
|
|
724
|
-
/>
|
|
725
|
-
</View>
|
|
647
|
+
<PageHeader
|
|
648
|
+
title={title}
|
|
649
|
+
headingLevel={2}
|
|
650
|
+
onBack={onBack}
|
|
651
|
+
backLabel={backLabel}
|
|
652
|
+
safeArea={false}
|
|
653
|
+
sticky={false}
|
|
654
|
+
placement="inline"
|
|
655
|
+
scrim="none"
|
|
656
|
+
scrimColor={palette.full}
|
|
657
|
+
scrollY={scrollY}
|
|
658
|
+
actions={
|
|
659
|
+
<ButtonGroup accessibilityLabel={closeLabel}>
|
|
660
|
+
<ButtonGroupItem
|
|
661
|
+
iconOnly
|
|
662
|
+
leadingIcon={RiCloseLine}
|
|
663
|
+
accessibilityLabel={closeLabel}
|
|
664
|
+
onPress={onClose}
|
|
665
|
+
testID={testID ? `${testID}-close` : undefined}
|
|
666
|
+
/>
|
|
667
|
+
</ButtonGroup>
|
|
668
|
+
}
|
|
669
|
+
testID={testID ? `${testID}-header` : undefined}
|
|
670
|
+
/>
|
|
726
671
|
);
|
|
727
672
|
}
|
|
728
673
|
|
|
@@ -736,7 +681,7 @@ function PageScroller({
|
|
|
736
681
|
children: React.ReactNode;
|
|
737
682
|
palette: SettingsPalette;
|
|
738
683
|
inset: number;
|
|
739
|
-
/**
|
|
684
|
+
/** Content gap below PageHeader; desktop Storage uses the compact 6px gap. */
|
|
740
685
|
insetTop?: number;
|
|
741
686
|
testID?: string;
|
|
742
687
|
}) {
|
|
@@ -865,27 +810,6 @@ const styles = StyleSheet.create({
|
|
|
865
810
|
railChevron: {
|
|
866
811
|
marginLeft: 'auto',
|
|
867
812
|
},
|
|
868
|
-
compactHeader: {
|
|
869
|
-
flexDirection: 'row',
|
|
870
|
-
alignItems: 'center',
|
|
871
|
-
gap: 8,
|
|
872
|
-
height: 56,
|
|
873
|
-
paddingLeft: 16,
|
|
874
|
-
paddingRight: 16,
|
|
875
|
-
borderBottomWidth: 1,
|
|
876
|
-
},
|
|
877
|
-
compactBack: {
|
|
878
|
-
width: 32,
|
|
879
|
-
height: 32,
|
|
880
|
-
marginLeft: -8,
|
|
881
|
-
alignItems: 'center',
|
|
882
|
-
justifyContent: 'center',
|
|
883
|
-
borderRadius: 9999,
|
|
884
|
-
},
|
|
885
|
-
compactTitle: {
|
|
886
|
-
flex: 1,
|
|
887
|
-
minWidth: 0,
|
|
888
|
-
},
|
|
889
813
|
panel: {
|
|
890
814
|
flexDirection: 'row',
|
|
891
815
|
borderRadius: 24,
|
|
@@ -924,18 +848,6 @@ const styles = StyleSheet.create({
|
|
|
924
848
|
flex: 1,
|
|
925
849
|
minWidth: 0,
|
|
926
850
|
},
|
|
927
|
-
titleRow: {
|
|
928
|
-
flexDirection: 'row',
|
|
929
|
-
alignItems: 'center',
|
|
930
|
-
justifyContent: 'space-between',
|
|
931
|
-
},
|
|
932
|
-
close: {
|
|
933
|
-
width: 24,
|
|
934
|
-
height: 24,
|
|
935
|
-
borderRadius: 9999,
|
|
936
|
-
alignItems: 'center',
|
|
937
|
-
justifyContent: 'center',
|
|
938
|
-
},
|
|
939
851
|
scrollHost: {
|
|
940
852
|
flex: 1,
|
|
941
853
|
minHeight: 0,
|
|
@@ -33,11 +33,11 @@ export interface SettingsNavGroup {
|
|
|
33
33
|
|
|
34
34
|
/** One page of the content pane. */
|
|
35
35
|
export interface SettingsModalPage {
|
|
36
|
-
/** Heading of the
|
|
36
|
+
/** Heading of the shared PageHeader. */
|
|
37
37
|
title: string;
|
|
38
38
|
content: ReactNode;
|
|
39
39
|
/**
|
|
40
|
-
* Used on the Storage page: a 6px
|
|
40
|
+
* Used on the Storage page: a 6px gap below PageHeader instead of 12px, because the page
|
|
41
41
|
* already carries 10px of headroom for the dropzone's progress badge.
|
|
42
42
|
*/
|
|
43
43
|
compactTitle?: boolean;
|
|
@@ -73,6 +73,8 @@ export interface SettingsModalProps {
|
|
|
73
73
|
/** Page selected every time the modal opens. Defaults to the first navigable row. */
|
|
74
74
|
defaultPage?: string;
|
|
75
75
|
onPageChange?: (page: string) => void;
|
|
76
|
+
/** Compact layout: start at the section list (default) or open the selected page directly. Resets on each open. */
|
|
77
|
+
initialView?: 'navigation' | 'page';
|
|
76
78
|
labels?: SettingsModalLabels;
|
|
77
79
|
testID?: string;
|
|
78
80
|
}
|
package/src/sidebar/Sidebar.tsx
CHANGED