@momo-kits/foundation 0.169.7-beta.1 → 0.169.7-beta.2

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.
@@ -2,20 +2,6 @@ import { StyleSheet } from 'react-native';
2
2
  import { Colors, Spacing } from '../../Consts';
3
3
  import { CTA_SHADOW, TabBarMetrics } from './metrics';
4
4
 
5
- const ITEM_HEIGHT =
6
- TabBarMetrics.indicatorHeight +
7
- TabBarMetrics.itemIconLabelGap +
8
- TabBarMetrics.labelHeight;
9
- const CONTENT_HEIGHT = TabBarMetrics.height - 2 * TabBarMetrics.paddingVertical;
10
- // the items are centered in the content, so their label starts this far below the content top
11
- const ITEM_LABEL_TOP =
12
- (CONTENT_HEIGHT - ITEM_HEIGHT) / 2 +
13
- TabBarMetrics.indicatorHeight +
14
- TabBarMetrics.itemIconLabelGap;
15
- // the center action column is placed so its label starts on the same line as the tab labels
16
- const CTA_TOP =
17
- ITEM_LABEL_TOP - TabBarMetrics.ctaLabelGap - TabBarMetrics.ctaSize;
18
-
19
5
  export const styles = StyleSheet.create({
20
6
  bar: {
21
7
  position: 'absolute',
@@ -51,7 +37,7 @@ export const styles = StyleSheet.create({
51
37
  position: 'absolute',
52
38
  left: 0,
53
39
  right: 0,
54
- top: CTA_TOP,
40
+ top: -TabBarMetrics.ctaLift - TabBarMetrics.paddingVertical,
55
41
  alignItems: 'center',
56
42
  gap: TabBarMetrics.ctaLabelGap,
57
43
  },
@@ -60,9 +46,6 @@ export const styles = StyleSheet.create({
60
46
  width: TabBarMetrics.ctaSize,
61
47
  height: TabBarMetrics.ctaSize,
62
48
  borderRadius: TabBarMetrics.ctaSize / 2,
63
- // Figma Icon Button border: white 60% hairline
64
- borderWidth: 1,
65
- borderColor: `rgba(255, 255, 255, ${TabBarMetrics.ctaBorderOpacity})`,
66
49
  alignItems: 'center',
67
50
  justifyContent: 'center',
68
51
  },
@@ -181,17 +181,21 @@ const HorizontalTabBar: React.FC<{
181
181
  return renderItems(items);
182
182
  };
183
183
 
184
+ const customContainer = withCta && floatingButton?.container;
185
+
184
186
  return (
185
187
  <View
186
188
  style={[styles.container, { width }]}
187
189
  accessibilityLabel={'bottom_tab_bar'}
188
190
  >
189
- <CurvedContainer
190
- width={width}
191
- height={TabBarMetrics.height}
192
- radius={TabBarMetrics.height / 2}
193
- notchCenterX={withCta ? width / 2 : undefined}
194
- />
191
+ {customContainer || (
192
+ <CurvedContainer
193
+ width={width}
194
+ height={TabBarMetrics.height}
195
+ radius={TabBarMetrics.height / 2}
196
+ notchCenterX={withCta ? width / 2 : undefined}
197
+ />
198
+ )}
195
199
  <View style={styles.content}>
196
200
  <ActiveIndicator
197
201
  axis={'x'}
@@ -224,8 +228,6 @@ export default function BottomTabBar(props: Props) {
224
228
  window.height,
225
229
  insets.left,
226
230
  insets.right,
227
- state.routes.length,
228
- withCta,
229
231
  );
230
232
 
231
233
  return (
@@ -3,7 +3,7 @@ import { StyleSheet } from 'react-native';
3
3
  import Svg, { Defs, FeGaussianBlur, Filter, Path } from 'react-native-svg';
4
4
  import { Colors } from '../../Consts';
5
5
  import { ApplicationContext } from '../../Context';
6
- import { NOTCH_CURVES, NOTCH_HALF_WIDTH, TabBarMetrics } from './metrics';
6
+ import { NOTCH_CURVES, NOTCH_HALF_WIDTH } from './metrics';
7
7
 
8
8
  type Props = {
9
9
  width: number;
@@ -139,13 +139,7 @@ const CurvedContainer: React.FC<Props> = ({
139
139
  filter={'url(#keyShadow)'}
140
140
  />
141
141
  )}
142
- <Path
143
- d={path}
144
- fill={theme.colors.background.surface}
145
- fillOpacity={TabBarMetrics.backgroundOpacity}
146
- stroke={theme.colors.border.default}
147
- strokeWidth={1}
148
- />
142
+ <Path d={path} fill={theme.colors.background.surface} />
149
143
  </Svg>
150
144
  );
151
145
  };
@@ -13,7 +13,7 @@ import Animated, {
13
13
  import { TabBarIcon } from './TabBarIcon';
14
14
  import { Text } from '../../Text';
15
15
  import { MiniAppContext } from '../../Context';
16
- import { Colors } from '../../Consts';
16
+ import { Colors, Spacing } from '../../Consts';
17
17
  import { TabBarMetrics, TabBarMotion } from './metrics';
18
18
 
19
19
  type IconRenderer = (props: {
@@ -143,7 +143,7 @@ const styles = StyleSheet.create({
143
143
  minWidth: 1,
144
144
  alignItems: 'center',
145
145
  justifyContent: 'center',
146
- gap: TabBarMetrics.itemIconLabelGap,
146
+ gap: Spacing.XXS,
147
147
  },
148
148
  slot: {
149
149
  height: TabBarMetrics.indicatorHeight,
@@ -3,11 +3,7 @@ import React from 'react';
3
3
  import { useWindowDimensions, View } from 'react-native';
4
4
  import { useScreenLayout } from '../../Layout/utils';
5
5
  import { FloatingButtonProps } from '../types';
6
- import {
7
- getSystemIndicatorHeight,
8
- hasCenterAction,
9
- HorizontalTabBar,
10
- } from './BottomTabBar';
6
+ import { getSystemIndicatorHeight, HorizontalTabBar } from './BottomTabBar';
11
7
  import { getHorizontalBarWidth, TabBarMetrics } from './metrics';
12
8
  import { getTabItems } from './tabItems';
13
9
  import { DuoRailTabBar } from './DuoRailTabBar';
@@ -38,7 +34,6 @@ const DuoFloatingTabBar: React.FC<DuoTabBarProps> = props => {
38
34
  const { insets } = useScreenLayout();
39
35
  const { width, height } = useWindowDimensions();
40
36
  const { floatingButton, activeTintColor, inactiveTintColor } = props;
41
- const tabItems = getTabItems(props);
42
37
 
43
38
  return (
44
39
  <View
@@ -49,15 +44,8 @@ const DuoFloatingTabBar: React.FC<DuoTabBarProps> = props => {
49
44
  ]}
50
45
  >
51
46
  <HorizontalTabBar
52
- items={tabItems}
53
- width={getHorizontalBarWidth(
54
- width,
55
- height,
56
- insets.left,
57
- insets.right,
58
- tabItems.length,
59
- hasCenterAction(floatingButton, tabItems.length),
60
- )}
47
+ items={getTabItems(props)}
48
+ width={getHorizontalBarWidth(width, height, insets.left, insets.right)}
61
49
  floatingButton={floatingButton}
62
50
  activeTintColor={activeTintColor}
63
51
  inactiveTintColor={inactiveTintColor}
@@ -8,18 +8,11 @@ import { Colors, Radius, Spacing } from '../../Consts';
8
8
  * iPhone Duo rail (center action under the container).
9
9
  */
10
10
  const TabBarMetrics = {
11
- height: 60,
11
+ height: 68,
12
12
  margin: Spacing.S,
13
- paddingVertical: Spacing.XS,
13
+ paddingVertical: Spacing.S,
14
14
  paddingHorizontal: Spacing.M,
15
- itemGap: 1,
16
- // gap between the icon slot and the label inside a tab (Figma: none)
17
- itemIconLabelGap: 0,
18
- // .Nav/Background: no backdrop blur, so use the Figma Blur=Off spec (opacity 95%, no blur) plus the 1px
19
- // border — nearly solid, matching the frosted sample; surface keeps dark-mode support
20
- backgroundOpacity: 0.95,
21
- // white 60% hairline around the center action button (Figma Icon Button border)
22
- ctaBorderOpacity: 0.6,
15
+ itemGap: Spacing.XS,
23
16
  iconSize: 24,
24
17
  // active indicator behind the icon: 24 icon + XS·M padding
25
18
  indicatorPaddingVertical: Spacing.XS,
@@ -32,9 +25,6 @@ const TabBarMetrics = {
32
25
  systemIndicatorHeight: 24,
33
26
  foldableMinShortSide: 600,
34
27
  foldableWidthRatio: 0.65,
35
- // a 2-tab bar doesn't stretch to the full width: each item is this fixed width and the bar is
36
- // sized to its content, centered (Figma Navigation · 2 Tab: item 100, bar ~225)
37
- twoTabItemWidth: 100,
38
28
  ctaSlotWidth: 92,
39
29
  ctaSize: 48,
40
30
  ctaIconSize: 28,
@@ -142,17 +132,7 @@ const getHorizontalBarWidth = (
142
132
  height: number,
143
133
  insetLeft: number,
144
134
  insetRight: number,
145
- itemCount: number,
146
- hasCta: boolean,
147
135
  ) => {
148
- // 2 tabs (no center action) stay content-sized and centered instead of filling the window
149
- if (itemCount === 2 && !hasCta) {
150
- return (
151
- TabBarMetrics.twoTabItemWidth * 2 +
152
- TabBarMetrics.paddingHorizontal * 2 +
153
- TabBarMetrics.itemGap
154
- );
155
- }
156
136
  const shortSide = Math.min(width, height);
157
137
  if (shortSide >= TabBarMetrics.foldableMinShortSide) {
158
138
  return shortSide * TabBarMetrics.foldableWidthRatio;
@@ -73,6 +73,9 @@ type ModalLayoutInput = {
73
73
  hinge?: ReservedRegion;
74
74
  };
75
75
 
76
+ /**
77
+ * `value` limited to the `[min, max]` range.
78
+ */
76
79
  const clamp = (value: number, min: number, max: number) => {
77
80
  return Math.min(Math.max(value, min), max);
78
81
  };
@@ -36,6 +36,7 @@ export type BottomTabProps = {
36
36
  };
37
37
 
38
38
  export type FloatingButtonProps = {
39
+ container?: React.ReactNode;
39
40
  icon: string | React.ReactNode;
40
41
  label: string;
41
42
  onPress: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/foundation",
3
- "version": "0.169.7-beta.1",
3
+ "version": "0.169.7-beta.2",
4
4
  "description": "React Native Component Kits",
5
5
  "main": "index.ts",
6
6
  "scripts": {},