@storybook/react-native-ui 8.3.10 → 8.4.0-alpha.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/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as _storybook_react_native_theming from '@storybook/react-native-theming';
2
2
  import * as react_native from 'react-native';
3
- import { PressableProps, View, TouchableOpacityProps, TouchableOpacity } from 'react-native';
3
+ import { PressableProps, View, TouchableOpacityProps } from 'react-native';
4
4
  import * as React$1 from 'react';
5
5
  import React__default, { FC, ComponentProps, ReactElement, PropsWithChildren, ReactNode } from 'react';
6
6
  import { State, StoriesHash, API } from '@storybook/core/manager-api';
@@ -15,7 +15,7 @@ interface NodeProps$1 {
15
15
  isExpandable?: boolean;
16
16
  isExpanded?: boolean;
17
17
  }
18
- declare const BranchNode: _storybook_react_native_theming.StyledComponent<react_native.TouchableOpacityProps & {
18
+ declare const BranchNode: _storybook_react_native_theming.StyledComponent<react_native.TouchableOpacityProps & React__default.RefAttributes<react_native.View> & {
19
19
  theme?: _storybook_react_native_theming.Theme;
20
20
  as?: React__default.ElementType;
21
21
  } & {
@@ -25,16 +25,16 @@ declare const BranchNode: _storybook_react_native_theming.StyledComponent<react_
25
25
  isComponent?: boolean;
26
26
  isSelected?: boolean;
27
27
  }, {}, {
28
- ref?: React__default.Ref<react_native.TouchableOpacity>;
28
+ ref?: React__default.Ref<any>;
29
29
  }>;
30
- declare const LeafNode: _storybook_react_native_theming.StyledComponent<react_native.TouchableOpacityProps & {
30
+ declare const LeafNode: _storybook_react_native_theming.StyledComponent<react_native.TouchableOpacityProps & React__default.RefAttributes<react_native.View> & {
31
31
  theme?: _storybook_react_native_theming.Theme;
32
32
  as?: React__default.ElementType;
33
33
  } & {
34
34
  depth?: number;
35
35
  selected?: boolean;
36
36
  }, {}, {
37
- ref?: React__default.Ref<react_native.TouchableOpacity>;
37
+ ref?: React__default.Ref<any>;
38
38
  }>;
39
39
  declare const GroupNode: FC<ComponentProps<typeof BranchNode> & {
40
40
  isExpanded?: boolean;
@@ -156,7 +156,7 @@ interface ButtonProps extends TouchableOpacityProps {
156
156
  text?: string;
157
157
  Icon?: (props: SvgProps) => ReactElement;
158
158
  }
159
- declare const Button: React$1.ForwardRefExoticComponent<ButtonProps & React$1.RefAttributes<TouchableOpacity>>;
159
+ declare const Button: React$1.ForwardRefExoticComponent<ButtonProps & React$1.RefAttributes<any>>;
160
160
  declare const ButtonText: _storybook_react_native_theming.StyledComponent<react_native.TextProps & {
161
161
  theme?: _storybook_react_native_theming.Theme;
162
162
  as?: React.ElementType;
@@ -172,7 +172,7 @@ declare const ButtonIcon: ({ Icon, active, variant, }: {
172
172
  active: ButtonProps["active"];
173
173
  }) => react_jsx_runtime.JSX.Element;
174
174
 
175
- declare const IconButton: React$1.ForwardRefExoticComponent<ButtonProps & React$1.RefAttributes<TouchableOpacity>>;
175
+ declare const IconButton: React$1.ForwardRefExoticComponent<ButtonProps & React$1.RefAttributes<unknown>>;
176
176
 
177
177
  type LayoutContextType = {
178
178
  isDesktop: boolean;
package/dist/index.js CHANGED
@@ -4506,70 +4506,66 @@ var import_react_native_reanimated = __toESM(require("react-native-reanimated"))
4506
4506
  var import_react_native_safe_area_context = require("react-native-safe-area-context");
4507
4507
  var import_react_native_theming13 = require("@storybook/react-native-theming");
4508
4508
  var import_jsx_runtime20 = require("react/jsx-runtime");
4509
- var MobileAddonsPanel = (0, import_react15.forwardRef)(({ storyId, onStateChange }, ref) => {
4510
- const theme = (0, import_react_native_theming13.useTheme)();
4511
- const reducedMotion = (0, import_react_native_reanimated.useReducedMotion)();
4512
- const addonsPanelBottomSheetRef = (0, import_react15.useRef)(null);
4513
- const insets = (0, import_react_native_safe_area_context.useSafeAreaInsets)();
4514
- const animatedPosition = (0, import_react_native_reanimated.useSharedValue)(0);
4515
- (0, import_react_native_reanimated.useAnimatedKeyboard)();
4516
- (0, import_react15.useImperativeHandle)(ref, () => ({
4517
- setAddonsPanelOpen: (open) => {
4518
- if (open) {
4519
- onStateChange(true);
4520
- addonsPanelBottomSheetRef.current?.present();
4521
- } else {
4522
- onStateChange(false);
4523
- addonsPanelBottomSheetRef.current?.dismiss();
4524
- }
4525
- }
4526
- }));
4527
- const { height } = (0, import_react_native6.useWindowDimensions)();
4528
- const adjustedBottomSheetSize = (0, import_react_native_reanimated.useAnimatedStyle)(() => {
4529
- return {
4530
- maxHeight: height - animatedPosition.value - insets.bottom
4531
- };
4532
- }, [animatedPosition.value, height, insets.bottom]);
4533
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4534
- import_bottom_sheet2.BottomSheetModal,
4535
- {
4536
- ref: addonsPanelBottomSheetRef,
4537
- index: 1,
4538
- animateOnMount: !reducedMotion,
4539
- onDismiss: () => {
4540
- onStateChange(false);
4541
- },
4542
- snapPoints: ["25%", "50%", "75%"],
4543
- style: {
4544
- paddingTop: 8
4545
- },
4546
- animatedPosition,
4547
- containerStyle: {},
4548
- backgroundStyle: {
4549
- borderRadius: 0,
4550
- borderTopColor: theme.appBorderColor,
4551
- borderTopWidth: 1,
4552
- backgroundColor: theme.background.content
4553
- },
4554
- handleIndicatorStyle: { backgroundColor: theme.textMutedColor },
4555
- keyboardBehavior: "extend",
4556
- enableDismissOnClose: true,
4557
- enableHandlePanningGesture: true,
4558
- stackBehavior: "replace",
4559
- enableDynamicSizing: false,
4560
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_reanimated.default.View, { style: [{ flex: 1 }, adjustedBottomSheetSize], children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4561
- AddonsTabs,
4562
- {
4563
- onClose: () => {
4564
- onStateChange(false);
4565
- addonsPanelBottomSheetRef.current?.dismiss();
4566
- },
4567
- storyId
4509
+ var MobileAddonsPanel = (0, import_react15.forwardRef)(
4510
+ ({ storyId }, ref) => {
4511
+ const theme = (0, import_react_native_theming13.useTheme)();
4512
+ const reducedMotion = (0, import_react_native_reanimated.useReducedMotion)();
4513
+ const addonsPanelBottomSheetRef = (0, import_react15.useRef)(null);
4514
+ const insets = (0, import_react_native_safe_area_context.useSafeAreaInsets)();
4515
+ const animatedPosition = (0, import_react_native_reanimated.useSharedValue)(0);
4516
+ (0, import_react_native_reanimated.useAnimatedKeyboard)();
4517
+ (0, import_react15.useImperativeHandle)(ref, () => ({
4518
+ setAddonsPanelOpen: (open) => {
4519
+ if (open) {
4520
+ addonsPanelBottomSheetRef.current?.present();
4521
+ } else {
4522
+ addonsPanelBottomSheetRef.current?.dismiss();
4568
4523
  }
4569
- ) })
4570
- }
4571
- );
4572
- });
4524
+ }
4525
+ }));
4526
+ const { height } = (0, import_react_native6.useWindowDimensions)();
4527
+ const adjustedBottomSheetSize = (0, import_react_native_reanimated.useAnimatedStyle)(() => {
4528
+ return {
4529
+ maxHeight: height - animatedPosition.value - insets.bottom
4530
+ };
4531
+ }, [animatedPosition.value, height, insets.bottom]);
4532
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4533
+ import_bottom_sheet2.BottomSheetModal,
4534
+ {
4535
+ ref: addonsPanelBottomSheetRef,
4536
+ index: 1,
4537
+ animateOnMount: !reducedMotion,
4538
+ snapPoints: ["25%", "50%", "75%"],
4539
+ style: {
4540
+ paddingTop: 8
4541
+ },
4542
+ animatedPosition,
4543
+ containerStyle: {},
4544
+ backgroundStyle: {
4545
+ borderRadius: 0,
4546
+ borderTopColor: theme.appBorderColor,
4547
+ borderTopWidth: 1,
4548
+ backgroundColor: theme.background.content
4549
+ },
4550
+ handleIndicatorStyle: { backgroundColor: theme.textMutedColor },
4551
+ keyboardBehavior: "extend",
4552
+ enableDismissOnClose: true,
4553
+ enableHandlePanningGesture: true,
4554
+ stackBehavior: "replace",
4555
+ enableDynamicSizing: false,
4556
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_reanimated.default.View, { style: [{ flex: 1 }, adjustedBottomSheetSize], children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4557
+ AddonsTabs,
4558
+ {
4559
+ onClose: () => {
4560
+ addonsPanelBottomSheetRef.current?.dismiss();
4561
+ },
4562
+ storyId
4563
+ }
4564
+ ) })
4565
+ }
4566
+ );
4567
+ }
4568
+ );
4573
4569
  var AddonsTabs = ({ onClose, storyId }) => {
4574
4570
  const panels = import_manager_api.addons.getElements(import_types3.Addon_TypesEnum.PANEL);
4575
4571
  const [addonSelected, setAddonSelected] = (0, import_react15.useState)(Object.keys(panels)[0]);
@@ -4671,7 +4667,7 @@ var BottomSheetBackdropComponent = (backdropComponentProps) => /* @__PURE__ */ (
4671
4667
  }
4672
4668
  );
4673
4669
  var MobileMenuDrawer = (0, import_react16.forwardRef)(
4674
- ({ children, onStateChange }, ref) => {
4670
+ ({ children }, ref) => {
4675
4671
  const reducedMotion = (0, import_react_native_reanimated2.useReducedMotion)();
4676
4672
  const insets = (0, import_react_native_safe_area_context2.useSafeAreaInsets)();
4677
4673
  const theme = (0, import_react_native_theming14.useTheme)();
@@ -4679,11 +4675,9 @@ var MobileMenuDrawer = (0, import_react16.forwardRef)(
4679
4675
  (0, import_react16.useImperativeHandle)(ref, () => ({
4680
4676
  setMobileMenuOpen: (open) => {
4681
4677
  if (open) {
4682
- onStateChange(true);
4683
4678
  menuBottomSheetRef.current?.present();
4684
4679
  } else {
4685
4680
  import_react_native7.Keyboard.dismiss();
4686
- onStateChange(false);
4687
4681
  menuBottomSheetRef.current?.dismiss();
4688
4682
  }
4689
4683
  }
@@ -4694,9 +4688,6 @@ var MobileMenuDrawer = (0, import_react16.forwardRef)(
4694
4688
  ref: menuBottomSheetRef,
4695
4689
  index: 1,
4696
4690
  animateOnMount: !reducedMotion,
4697
- onDismiss: () => {
4698
- onStateChange(false);
4699
- },
4700
4691
  snapPoints: ["50%", "75%"],
4701
4692
  enableDismissOnClose: true,
4702
4693
  enableHandlePanningGesture: true,
@@ -4911,8 +4902,6 @@ var Layout = ({
4911
4902
  }) => {
4912
4903
  const theme = (0, import_react_native_theming15.useTheme)();
4913
4904
  const mobileMenuDrawerRef = (0, import_react17.useRef)(null);
4914
- const [menuOpen, setMenuOpen] = (0, import_react17.useState)(false);
4915
- const [drawerOpen, setDrawerOpen] = (0, import_react17.useState)(false);
4916
4905
  const addonPanelRef = (0, import_react17.useRef)(null);
4917
4906
  const insets = (0, import_react_native_safe_area_context3.useSafeAreaInsets)();
4918
4907
  const { isDesktop } = useLayout();
@@ -4987,7 +4976,7 @@ var Layout = ({
4987
4976
  }
4988
4977
  ),
4989
4978
  /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_react_native8.View, { style: { flex: 1 }, children: [
4990
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native8.View, { style: { flex: 1 }, children }),
4979
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native8.View, { style: { flex: 1, overflow: "hidden" }, children }),
4991
4980
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4992
4981
  import_react_native8.View,
4993
4982
  {
@@ -5014,29 +5003,8 @@ var Layout = ({
5014
5003
  );
5015
5004
  }
5016
5005
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_react_native8.View, { style: { flex: 1, paddingTop: insets.top, backgroundColor: theme.background.content }, children: [
5017
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native8.View, { style: { flex: 1 }, children }),
5018
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(MobileMenuDrawer, { ref: mobileMenuDrawerRef, onStateChange: setDrawerOpen, children: [
5019
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native8.View, { style: { paddingLeft: 16, paddingTop: 4, paddingBottom: 4 }, children: theme.base === "light" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Logo, { height: 25, width: 125 }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DarkLogo, { height: 25, width: 125 }) }),
5020
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5021
- Sidebar,
5022
- {
5023
- extra: [],
5024
- previewInitialized: true,
5025
- indexError: void 0,
5026
- refs: {},
5027
- setSelection: ({ storyId: newStoryId }) => {
5028
- const channel = import_manager_api2.addons.getChannel();
5029
- channel.emit(import_core_events.SET_CURRENT_STORY, { storyId: newStoryId });
5030
- },
5031
- status: {},
5032
- index: storyHash,
5033
- storyId: story?.id,
5034
- refId: DEFAULT_REF_ID
5035
- }
5036
- )
5037
- ] }),
5038
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MobileAddonsPanel, { ref: addonPanelRef, storyId: story?.id, onStateChange: setMenuOpen }),
5039
- (import_react_native8.Platform.OS !== "android" || !menuOpen && !drawerOpen) && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Container3, { style: { marginBottom: insets.bottom }, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Nav, { children: [
5006
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native8.View, { style: { flex: 1, overflow: "hidden" }, children }),
5007
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Container3, { style: { marginBottom: insets.bottom }, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Nav, { children: [
5040
5008
  /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5041
5009
  Button2,
5042
5010
  {
@@ -5062,7 +5030,28 @@ var Layout = ({
5062
5030
  Icon: BottomBarToggleIcon
5063
5031
  }
5064
5032
  )
5065
- ] }) })
5033
+ ] }) }),
5034
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(MobileMenuDrawer, { ref: mobileMenuDrawerRef, children: [
5035
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_native8.View, { style: { paddingLeft: 16, paddingTop: 4, paddingBottom: 4 }, children: theme.base === "light" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Logo, { height: 25, width: 125 }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DarkLogo, { height: 25, width: 125 }) }),
5036
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5037
+ Sidebar,
5038
+ {
5039
+ extra: [],
5040
+ previewInitialized: true,
5041
+ indexError: void 0,
5042
+ refs: {},
5043
+ setSelection: ({ storyId: newStoryId }) => {
5044
+ const channel = import_manager_api2.addons.getChannel();
5045
+ channel.emit(import_core_events.SET_CURRENT_STORY, { storyId: newStoryId });
5046
+ },
5047
+ status: {},
5048
+ index: storyHash,
5049
+ storyId: story?.id,
5050
+ refId: DEFAULT_REF_ID
5051
+ }
5052
+ )
5053
+ ] }),
5054
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MobileAddonsPanel, { ref: addonPanelRef, storyId: story?.id })
5066
5055
  ] });
5067
5056
  };
5068
5057
  var Nav = import_react_native_theming15.styled.View({
@@ -5077,7 +5066,6 @@ var Nav = import_react_native_theming15.styled.View({
5077
5066
  var Container3 = import_react_native_theming15.styled.View(({ theme }) => ({
5078
5067
  alignSelf: "flex-end",
5079
5068
  width: "100%",
5080
- zIndex: 10,
5081
5069
  backgroundColor: theme.barBg,
5082
5070
  borderTopColor: theme.appBorderColor,
5083
5071
  borderTopWidth: 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/react-native-ui",
3
- "version": "8.3.10",
3
+ "version": "8.4.0-alpha.0",
4
4
  "description": "ui components for react native storybook",
5
5
  "keywords": [
6
6
  "react",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/jest": "^29.4.3",
52
- "@types/react": "~18.2.79",
52
+ "@types/react": "~18.3.12",
53
53
  "babel-jest": "^29.4.3",
54
54
  "jest": "29.7.0",
55
55
  "react-test-renderer": "18.2.0",
@@ -57,9 +57,9 @@
57
57
  "typescript": "^5.3.3"
58
58
  },
59
59
  "dependencies": {
60
- "@storybook/core": "^8.3.5",
61
- "@storybook/react": "^8.3.5",
62
- "@storybook/react-native-theming": "^8.3.10",
60
+ "@storybook/core": "^8.4.0-beta.0",
61
+ "@storybook/react": "^8.4.0-beta.0",
62
+ "@storybook/react-native-theming": "^8.4.0-alpha.0",
63
63
  "fuse.js": "^7.0.0",
64
64
  "memoizerific": "^1.11.3",
65
65
  "polished": "^4.3.1",
@@ -80,5 +80,5 @@
80
80
  "publishConfig": {
81
81
  "access": "public"
82
82
  },
83
- "gitHead": "df58f982babc3080187a88c9959d56d18eff82e4"
83
+ "gitHead": "11531d9d55c0c933feb61d507595da80becb0b4a"
84
84
  }
package/src/Button.tsx CHANGED
@@ -1,6 +1,6 @@
1
1
  import { styled, useTheme } from '@storybook/react-native-theming';
2
2
  import { ReactElement, forwardRef, useEffect, useMemo, useState } from 'react';
3
- import { TouchableOpacity, TouchableOpacityProps } from 'react-native';
3
+ import type { TouchableOpacityProps } from 'react-native';
4
4
  import { SvgProps } from 'react-native-svg';
5
5
 
6
6
  export interface ButtonProps extends TouchableOpacityProps {
@@ -15,7 +15,8 @@ export interface ButtonProps extends TouchableOpacityProps {
15
15
  Icon?: (props: SvgProps) => ReactElement;
16
16
  }
17
17
 
18
- export const Button = forwardRef<TouchableOpacity, ButtonProps>(
18
+ // TODO fix this type
19
+ export const Button = forwardRef<any, ButtonProps>(
19
20
  (
20
21
  {
21
22
  Icon,
@@ -29,7 +30,7 @@ export const Button = forwardRef<TouchableOpacity, ButtonProps>(
29
30
  children,
30
31
  text,
31
32
  ...props
32
- },
33
+ }: ButtonProps,
33
34
  ref
34
35
  ) => {
35
36
  // let Comp: 'button' | 'a' | typeof Slot = 'button';
@@ -1,9 +1,8 @@
1
- import { TouchableOpacity } from 'react-native';
2
1
  import { Button, ButtonProps } from './Button';
3
2
  import { forwardRef } from 'react';
4
3
 
5
- export const IconButton = forwardRef<TouchableOpacity, ButtonProps>(
6
- ({ padding = 'small', variant = 'ghost', ...props }, ref) => {
4
+ export const IconButton = forwardRef(
5
+ ({ padding = 'small', variant = 'ghost', ...props }: ButtonProps, ref) => {
7
6
  return <Button padding={padding} variant={variant} ref={ref} {...props} />;
8
7
  }
9
8
  );
@@ -1,9 +1,10 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
2
  import { Layout } from './Layout';
3
3
  import { mockDataset } from './mockdata';
4
- import { Text } from 'react-native';
4
+ import { Text, View } from 'react-native';
5
5
  import { GestureHandlerRootView } from 'react-native-gesture-handler';
6
6
  import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
7
+ import { LayoutProvider } from './LayoutProvider';
7
8
 
8
9
  const meta = {
9
10
  title: 'components/Layout',
@@ -12,7 +13,9 @@ const meta = {
12
13
  (Story) => (
13
14
  <GestureHandlerRootView style={{ flex: 1 }}>
14
15
  <BottomSheetModalProvider>
15
- <Story />
16
+ <LayoutProvider>
17
+ <Story />
18
+ </LayoutProvider>
16
19
  </BottomSheetModalProvider>
17
20
  </GestureHandlerRootView>
18
21
  ),
@@ -31,3 +34,44 @@ export const Basic: Story = {
31
34
  storyId: 'emails-buildnotification--with-changes',
32
35
  },
33
36
  };
37
+
38
+ export const OverflowSidebarExample: Story = {
39
+ args: {
40
+ children: (
41
+ <View
42
+ style={{
43
+ width: '100%',
44
+ backgroundColor: 'lightgreen',
45
+ alignItems: 'flex-end',
46
+ left: '-50%',
47
+ }}
48
+ >
49
+ <Text style={{ width: '50%', textAlign: 'right' }}>
50
+ This box should not overflow the side navigation in desktop mode
51
+ </Text>
52
+ </View>
53
+ ),
54
+ //@ts-ignore
55
+ storyHash: mockDataset.withRoot,
56
+ storyId: 'emails-buildnotification--with-changes',
57
+ },
58
+ };
59
+
60
+ export const OverflowAddonsExample: Story = {
61
+ args: {
62
+ children: (
63
+ <View
64
+ style={{
65
+ height: '100%',
66
+ backgroundColor: 'lightgreen',
67
+ bottom: '-50%',
68
+ }}
69
+ >
70
+ <Text style={{ height: '50%' }}>This box should not overflow the addons panel</Text>
71
+ </View>
72
+ ),
73
+ //@ts-ignore
74
+ storyHash: mockDataset.withRoot,
75
+ storyId: 'emails-buildnotification--with-changes',
76
+ },
77
+ };
package/src/Layout.tsx CHANGED
@@ -4,7 +4,7 @@ import { type API_IndexHash, type Args, type StoryContext } from '@storybook/cor
4
4
  import type { ReactRenderer } from '@storybook/react';
5
5
  import { styled, useTheme } from '@storybook/react-native-theming';
6
6
  import { ReactNode, useRef, useState } from 'react';
7
- import { Platform, ScrollView, Text, View } from 'react-native';
7
+ import { ScrollView, Text, View } from 'react-native';
8
8
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
9
9
  import { IconButton } from './IconButton';
10
10
  import { useLayout } from './LayoutProvider';
@@ -28,8 +28,6 @@ export const Layout = ({
28
28
  }) => {
29
29
  const theme = useTheme();
30
30
  const mobileMenuDrawerRef = useRef<MobileMenuDrawerRef>(null);
31
- const [menuOpen, setMenuOpen] = useState(false);
32
- const [drawerOpen, setDrawerOpen] = useState(false);
33
31
  const addonPanelRef = useRef<MobileAddonsPanelRef>(null);
34
32
  const insets = useSafeAreaInsets();
35
33
  const { isDesktop } = useLayout();
@@ -105,7 +103,7 @@ export const Layout = ({
105
103
  </View>
106
104
 
107
105
  <View style={{ flex: 1 }}>
108
- <View style={{ flex: 1 }}>{children}</View>
106
+ <View style={{ flex: 1, overflow: 'hidden' }}>{children}</View>
109
107
 
110
108
  <View
111
109
  style={{
@@ -133,9 +131,31 @@ export const Layout = ({
133
131
 
134
132
  return (
135
133
  <View style={{ flex: 1, paddingTop: insets.top, backgroundColor: theme.background.content }}>
136
- <View style={{ flex: 1 }}>{children}</View>
137
-
138
- <MobileMenuDrawer ref={mobileMenuDrawerRef} onStateChange={setDrawerOpen}>
134
+ <View style={{ flex: 1, overflow: 'hidden' }}>{children}</View>
135
+
136
+ <Container style={{ marginBottom: insets.bottom }}>
137
+ <Nav>
138
+ <Button
139
+ style={{ flexShrink: 1 }}
140
+ hitSlop={{ bottom: 10, left: 10, right: 10, top: 10 }}
141
+ onPress={() => {
142
+ mobileMenuDrawerRef.current.setMobileMenuOpen(true);
143
+ }}
144
+ >
145
+ <MenuIcon color={theme.color.mediumdark} />
146
+ <Text style={{ flexShrink: 1, color: theme.color.defaultText }} numberOfLines={1}>
147
+ {story?.title}/{story?.name}
148
+ </Text>
149
+ </Button>
150
+
151
+ <IconButton
152
+ onPress={() => addonPanelRef.current.setAddonsPanelOpen(true)}
153
+ Icon={BottomBarToggleIcon}
154
+ />
155
+ </Nav>
156
+ </Container>
157
+
158
+ <MobileMenuDrawer ref={mobileMenuDrawerRef}>
139
159
  <View style={{ paddingLeft: 16, paddingTop: 4, paddingBottom: 4 }}>
140
160
  {theme.base === 'light' ? (
141
161
  <Logo height={25} width={125} />
@@ -160,30 +180,7 @@ export const Layout = ({
160
180
  />
161
181
  </MobileMenuDrawer>
162
182
 
163
- <MobileAddonsPanel ref={addonPanelRef} storyId={story?.id} onStateChange={setMenuOpen} />
164
- {(Platform.OS !== 'android' || (!menuOpen && !drawerOpen)) && (
165
- <Container style={{ marginBottom: insets.bottom }}>
166
- <Nav>
167
- <Button
168
- style={{ flexShrink: 1 }}
169
- hitSlop={{ bottom: 10, left: 10, right: 10, top: 10 }}
170
- onPress={() => {
171
- mobileMenuDrawerRef.current.setMobileMenuOpen(true);
172
- }}
173
- >
174
- <MenuIcon color={theme.color.mediumdark} />
175
- <Text style={{ flexShrink: 1, color: theme.color.defaultText }} numberOfLines={1}>
176
- {story?.title}/{story?.name}
177
- </Text>
178
- </Button>
179
-
180
- <IconButton
181
- onPress={() => addonPanelRef.current.setAddonsPanelOpen(true)}
182
- Icon={BottomBarToggleIcon}
183
- />
184
- </Nav>
185
- </Container>
186
- )}
183
+ <MobileAddonsPanel ref={addonPanelRef} storyId={story?.id} />
187
184
  </View>
188
185
  );
189
186
  };
@@ -201,7 +198,6 @@ const Nav = styled.View({
201
198
  const Container = styled.View(({ theme }) => ({
202
199
  alignSelf: 'flex-end',
203
200
  width: '100%',
204
- zIndex: 10,
205
201
  backgroundColor: theme.barBg,
206
202
  borderTopColor: theme.appBorderColor,
207
203
  borderTopWidth: 1,
@@ -20,83 +20,76 @@ export interface MobileAddonsPanelRef {
20
20
  setAddonsPanelOpen: (isOpen: boolean) => void;
21
21
  }
22
22
 
23
- export const MobileAddonsPanel = forwardRef<
24
- MobileAddonsPanelRef,
25
- { storyId?: string; onStateChange: (open: boolean) => void }
26
- >(({ storyId, onStateChange }, ref) => {
27
- const theme = useTheme();
28
- const reducedMotion = useReducedMotion();
29
-
30
- const addonsPanelBottomSheetRef = useRef<BottomSheetModal>(null);
31
- const insets = useSafeAreaInsets();
32
-
33
- const animatedPosition = useSharedValue(0);
34
-
35
- // bringing in animated keyboard disables android resizing
36
- // TODO replicate functionality without this
37
- useAnimatedKeyboard();
38
-
39
- useImperativeHandle(ref, () => ({
40
- setAddonsPanelOpen: (open: boolean) => {
41
- if (open) {
42
- onStateChange(true);
43
- addonsPanelBottomSheetRef.current?.present();
44
- } else {
45
- onStateChange(false);
46
- addonsPanelBottomSheetRef.current?.dismiss();
47
- }
48
- },
49
- }));
50
-
51
- const { height } = useWindowDimensions();
52
-
53
- const adjustedBottomSheetSize = useAnimatedStyle(() => {
54
- return {
55
- maxHeight: height - animatedPosition.value - insets.bottom,
56
- };
57
- }, [animatedPosition.value, height, insets.bottom]);
58
-
59
- return (
60
- <BottomSheetModal
61
- ref={addonsPanelBottomSheetRef}
62
- index={1}
63
- animateOnMount={!reducedMotion}
64
- onDismiss={() => {
65
- onStateChange(false);
66
- }}
67
- snapPoints={['25%', '50%', '75%']}
68
- style={{
69
- paddingTop: 8,
70
- }}
71
- animatedPosition={animatedPosition}
72
- containerStyle={{}}
73
- backgroundStyle={{
74
- borderRadius: 0,
75
- borderTopColor: theme.appBorderColor,
76
- borderTopWidth: 1,
77
- backgroundColor: theme.background.content,
78
- }}
79
- handleIndicatorStyle={{ backgroundColor: theme.textMutedColor }}
80
- keyboardBehavior="extend"
81
- // keyboardBlurBehavior="restore"
82
- enableDismissOnClose
83
- enableHandlePanningGesture={true}
84
- // enableContentPanningGesture={true}
85
- stackBehavior="replace"
86
- enableDynamicSizing={false}
87
- >
88
- <Animated.View style={[{ flex: 1 }, adjustedBottomSheetSize]}>
89
- <AddonsTabs
90
- onClose={() => {
91
- onStateChange(false);
92
- addonsPanelBottomSheetRef.current?.dismiss();
93
- }}
94
- storyId={storyId}
95
- />
96
- </Animated.View>
97
- </BottomSheetModal>
98
- );
99
- });
23
+ export const MobileAddonsPanel = forwardRef<MobileAddonsPanelRef, { storyId?: string }>(
24
+ ({ storyId }, ref) => {
25
+ const theme = useTheme();
26
+ const reducedMotion = useReducedMotion();
27
+
28
+ const addonsPanelBottomSheetRef = useRef<BottomSheetModal>(null);
29
+ const insets = useSafeAreaInsets();
30
+
31
+ const animatedPosition = useSharedValue(0);
32
+
33
+ // bringing in animated keyboard disables android resizing
34
+ // TODO replicate functionality without this
35
+ useAnimatedKeyboard();
36
+
37
+ useImperativeHandle(ref, () => ({
38
+ setAddonsPanelOpen: (open: boolean) => {
39
+ if (open) {
40
+ addonsPanelBottomSheetRef.current?.present();
41
+ } else {
42
+ addonsPanelBottomSheetRef.current?.dismiss();
43
+ }
44
+ },
45
+ }));
46
+
47
+ const { height } = useWindowDimensions();
48
+
49
+ const adjustedBottomSheetSize = useAnimatedStyle(() => {
50
+ return {
51
+ maxHeight: height - animatedPosition.value - insets.bottom,
52
+ };
53
+ }, [animatedPosition.value, height, insets.bottom]);
54
+
55
+ return (
56
+ <BottomSheetModal
57
+ ref={addonsPanelBottomSheetRef}
58
+ index={1}
59
+ animateOnMount={!reducedMotion}
60
+ snapPoints={['25%', '50%', '75%']}
61
+ style={{
62
+ paddingTop: 8,
63
+ }}
64
+ animatedPosition={animatedPosition}
65
+ containerStyle={{}}
66
+ backgroundStyle={{
67
+ borderRadius: 0,
68
+ borderTopColor: theme.appBorderColor,
69
+ borderTopWidth: 1,
70
+ backgroundColor: theme.background.content,
71
+ }}
72
+ handleIndicatorStyle={{ backgroundColor: theme.textMutedColor }}
73
+ keyboardBehavior="extend"
74
+ // keyboardBlurBehavior="restore"
75
+ enableDismissOnClose
76
+ enableHandlePanningGesture={true}
77
+ // enableContentPanningGesture={true}
78
+ stackBehavior="replace"
79
+ enableDynamicSizing={false}
80
+ >
81
+ <Animated.View style={[{ flex: 1 }, adjustedBottomSheetSize]}>
82
+ <AddonsTabs
83
+ onClose={() => {
84
+ addonsPanelBottomSheetRef.current?.dismiss();
85
+ }}
86
+ storyId={storyId}
87
+ />
88
+ </Animated.View>
89
+ </BottomSheetModal>
90
+ );
91
+ }
92
+ );
100
93
 
101
94
  export const AddonsTabs = ({ onClose, storyId }: { onClose?: () => void; storyId?: string }) => {
102
95
  const panels = addons.getElements(Addon_TypesEnum.PANEL);
@@ -12,7 +12,6 @@ import { useTheme } from '@storybook/react-native-theming';
12
12
 
13
13
  interface MobileMenuDrawerProps {
14
14
  children: ReactNode | ReactNode[];
15
- onStateChange: (isOpen: boolean) => void;
16
15
  }
17
16
 
18
17
  export interface MobileMenuDrawerRef {
@@ -30,7 +29,7 @@ export const BottomSheetBackdropComponent = (backdropComponentProps: BottomSheet
30
29
  );
31
30
 
32
31
  export const MobileMenuDrawer = forwardRef<MobileMenuDrawerRef, MobileMenuDrawerProps>(
33
- ({ children, onStateChange }, ref) => {
32
+ ({ children }, ref) => {
34
33
  const reducedMotion = useReducedMotion();
35
34
  const insets = useSafeAreaInsets();
36
35
  const theme = useTheme();
@@ -40,12 +39,10 @@ export const MobileMenuDrawer = forwardRef<MobileMenuDrawerRef, MobileMenuDrawer
40
39
  useImperativeHandle(ref, () => ({
41
40
  setMobileMenuOpen: (open: boolean) => {
42
41
  if (open) {
43
- onStateChange(true);
44
-
45
42
  menuBottomSheetRef.current?.present();
46
43
  } else {
47
44
  Keyboard.dismiss();
48
- onStateChange(false);
45
+
49
46
  menuBottomSheetRef.current?.dismiss();
50
47
  }
51
48
  },
@@ -56,9 +53,6 @@ export const MobileMenuDrawer = forwardRef<MobileMenuDrawerRef, MobileMenuDrawer
56
53
  ref={menuBottomSheetRef}
57
54
  index={1}
58
55
  animateOnMount={!reducedMotion}
59
- onDismiss={() => {
60
- onStateChange(false);
61
- }}
62
56
  snapPoints={['50%', '75%']}
63
57
  enableDismissOnClose
64
58
  enableHandlePanningGesture