@momo-kits/foundation 0.169.4-beta.5 → 0.169.4-beta.7

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.
@@ -46,6 +46,9 @@ export const styles = StyleSheet.create({
46
46
  width: TabBarMetrics.ctaSize,
47
47
  height: TabBarMetrics.ctaSize,
48
48
  borderRadius: TabBarMetrics.ctaSize / 2,
49
+ // Figma Icon Button border: white 60% hairline
50
+ borderWidth: 1,
51
+ borderColor: `rgba(255, 255, 255, ${TabBarMetrics.ctaBorderOpacity})`,
49
52
  alignItems: 'center',
50
53
  justifyContent: 'center',
51
54
  },
@@ -237,6 +237,8 @@ export default function BottomTabBar(props: Props) {
237
237
  window.height,
238
238
  insets.left,
239
239
  insets.right,
240
+ state.routes.length,
241
+ withCta,
240
242
  );
241
243
 
242
244
  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 } from './metrics';
6
+ import { NOTCH_CURVES, NOTCH_HALF_WIDTH, TabBarMetrics } from './metrics';
7
7
 
8
8
  type Props = {
9
9
  width: number;
@@ -137,7 +137,13 @@ const CurvedContainer: React.FC<Props> = ({
137
137
  filter={'url(#keyShadow)'}
138
138
  />
139
139
  )}
140
- <Path d={path} fill={theme.colors.background.surface} />
140
+ <Path
141
+ d={path}
142
+ fill={theme.colors.background.surface}
143
+ fillOpacity={TabBarMetrics.backgroundOpacity}
144
+ stroke={theme.colors.border.default}
145
+ strokeWidth={1}
146
+ />
141
147
  </Svg>
142
148
  );
143
149
  };
@@ -13,7 +13,7 @@ import Animated, {
13
13
  import { CappedScaleText, TabBarIcon } from './TabBarIcon';
14
14
  import { Text } from '../../Text';
15
15
  import { MiniAppContext } from '../../Context';
16
- import { Colors, Spacing } from '../../Consts';
16
+ import { Colors } from '../../Consts';
17
17
  import { TabBarMetrics, TabBarMotion } from './metrics';
18
18
 
19
19
  type IconRenderer = (props: {
@@ -147,7 +147,7 @@ const styles = StyleSheet.create({
147
147
  minWidth: 1,
148
148
  alignItems: 'center',
149
149
  justifyContent: 'center',
150
- gap: Spacing.XXS,
150
+ gap: TabBarMetrics.itemIconLabelGap,
151
151
  },
152
152
  slot: {
153
153
  height: TabBarMetrics.indicatorHeight,
@@ -3,7 +3,11 @@ 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 { getSystemIndicatorHeight, HorizontalTabBar } from './BottomTabBar';
6
+ import {
7
+ getSystemIndicatorHeight,
8
+ hasCenterAction,
9
+ HorizontalTabBar,
10
+ } from './BottomTabBar';
7
11
  import { getHorizontalBarWidth, TabBarMetrics } from './metrics';
8
12
  import { getTabItems } from './tabItems';
9
13
  import { DuoRailTabBar } from './DuoRailTabBar';
@@ -34,6 +38,7 @@ const DuoFloatingTabBar: React.FC<DuoTabBarProps> = props => {
34
38
  const { insets } = useScreenLayout();
35
39
  const { width, height } = useWindowDimensions();
36
40
  const { floatingButton, activeTintColor, inactiveTintColor } = props;
41
+ const tabItems = getTabItems(props);
37
42
 
38
43
  return (
39
44
  <View
@@ -45,8 +50,15 @@ const DuoFloatingTabBar: React.FC<DuoTabBarProps> = props => {
45
50
  >
46
51
  <HorizontalTabBar
47
52
  fixedFontScale
48
- items={getTabItems(props)}
49
- width={getHorizontalBarWidth(width, height, insets.left, insets.right)}
53
+ items={tabItems}
54
+ width={getHorizontalBarWidth(
55
+ width,
56
+ height,
57
+ insets.left,
58
+ insets.right,
59
+ tabItems.length,
60
+ hasCenterAction(floatingButton, tabItems.length),
61
+ )}
50
62
  floatingButton={floatingButton}
51
63
  activeTintColor={activeTintColor}
52
64
  inactiveTintColor={inactiveTintColor}
@@ -9,11 +9,18 @@ import { Colors, Radius, Spacing } from '../../Consts';
9
9
  * - vertical: iPhone Duo rail, center action under the container
10
10
  */
11
11
  const TabBarMetrics = {
12
- height: 68,
12
+ height: 60,
13
13
  margin: Spacing.S,
14
- paddingVertical: Spacing.S,
14
+ paddingVertical: Spacing.XS,
15
15
  paddingHorizontal: Spacing.M,
16
- itemGap: Spacing.XS,
16
+ itemGap: 1,
17
+ // gap between the icon slot and the label inside a tab (Figma: none)
18
+ itemIconLabelGap: 0,
19
+ // .Nav/Background: no backdrop blur, so use the Figma Blur=Off spec (opacity 95%, no blur) plus the 1px
20
+ // border — nearly solid, matching the frosted sample; surface keeps dark-mode support
21
+ backgroundOpacity: 0.95,
22
+ // white 60% hairline around the center action button (Figma Icon Button border)
23
+ ctaBorderOpacity: 0.6,
17
24
  iconSize: 24,
18
25
  // active indicator behind the icon: 24 icon + XS·M padding
19
26
  indicatorPaddingVertical: Spacing.XS,
@@ -29,6 +36,9 @@ const TabBarMetrics = {
29
36
  // side, centered; phones and folded outer displays fill the window
30
37
  foldableMinShortSide: 600,
31
38
  foldableWidthRatio: 0.65,
39
+ // a 2-tab bar doesn't stretch to the full width: each item is this fixed width and the bar is
40
+ // sized to its content, centered (Figma Navigation · 2 Tab: item 100, bar ~225)
41
+ twoTabItemWidth: 100,
32
42
  ctaSlotWidth: 92,
33
43
  ctaSize: 48,
34
44
  // the icon sits 10 inside the 48 button (prototype .cta: 28 icon), 12 inside the 52 rail one
@@ -139,7 +149,17 @@ const getHorizontalBarWidth = (
139
149
  height: number,
140
150
  insetLeft: number,
141
151
  insetRight: number,
152
+ itemCount: number,
153
+ hasCta: boolean,
142
154
  ) => {
155
+ // 2 tabs (no center action) stay content-sized and centered instead of filling the window
156
+ if (itemCount === 2 && !hasCta) {
157
+ return (
158
+ TabBarMetrics.twoTabItemWidth * 2 +
159
+ TabBarMetrics.paddingHorizontal * 2 +
160
+ TabBarMetrics.itemGap
161
+ );
162
+ }
143
163
  const shortSide = Math.min(width, height);
144
164
  if (shortSide >= TabBarMetrics.foldableMinShortSide) {
145
165
  return shortSide * TabBarMetrics.foldableWidthRatio;
@@ -16,10 +16,10 @@ describe('getModalLayout', () => {
16
16
  expect(layout.isFoldable).toBe(false);
17
17
  expect(layout.popup.width).toBe(342);
18
18
  expect(layout.popup.maxHeight).toBeUndefined();
19
- expect(layout.popup.radius).toBe(24);
19
+ expect(layout.popup.radius).toBe(16);
20
20
  expect(layout.sheet.width).toBeUndefined();
21
21
  expect(layout.sheet.maxHeight).toBeUndefined();
22
- expect(layout.sheet.radius).toBe(24);
22
+ expect(layout.sheet.radius).toBe(12);
23
23
  expect(layout.scrimOpacity).toBe(0.6);
24
24
  });
25
25
 
@@ -33,7 +33,7 @@ describe('getModalLayout', () => {
33
33
  expect(layout.isFoldable).toBe(false);
34
34
  expect(layout.popup.width).toBe(844 - 48);
35
35
  expect(layout.popup.maxHeight).toBeUndefined();
36
- expect(layout.popup.radius).toBe(24);
36
+ expect(layout.popup.radius).toBe(16);
37
37
  expect(layout.sheet.width).toBeUndefined();
38
38
  expect(layout.scrimOpacity).toBe(0.6);
39
39
  });
@@ -112,9 +112,9 @@ const getModalLayout = ({
112
112
  minWidth: popupWidth,
113
113
  maxWidth: popupWidth,
114
114
  margin: Spacing.XL,
115
- radius: Radius.XL,
115
+ radius: Radius.L,
116
116
  },
117
- sheet: { margin: 0, radius: Radius.XL },
117
+ sheet: { margin: 0, radius: Radius.M },
118
118
  scrimOpacity: SCRIM_OPACITY,
119
119
  };
120
120
  }
@@ -183,12 +183,18 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
183
183
  const body = (
184
184
  <>
185
185
  {!!image && (
186
- <Image source={{ uri: image }} style={styles.image} />
186
+ <Image
187
+ source={{ uri: image }}
188
+ style={[
189
+ styles.image,
190
+ { borderTopLeftRadius: radius, borderTopRightRadius: radius },
191
+ ]}
192
+ />
187
193
  )}
188
194
  <View style={[styles.content, isFoldable && styles.shrink]}>
189
195
  <Text
190
196
  typography={'header_default_bold'}
191
- numberOfLines={2}
197
+ numberOfLines={3}
192
198
  accessibilityLabel={'title_popup_notify'}
193
199
  // keeps the title clear of the close button on a text only popup
194
200
  style={
@@ -244,7 +250,6 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
244
250
  width: popupWidth,
245
251
  maxHeight,
246
252
  },
247
- styles.card,
248
253
  showBaseLineDebug && styles.debugBaseLine,
249
254
  ]}
250
255
  >
@@ -257,10 +262,9 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
257
262
 
258
263
  const styles = StyleSheet.create({
259
264
  debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
260
- // clips the image and content to the card radius
261
- card: { overflow: 'hidden' },
262
265
  image: {
263
266
  aspectRatio: 1.7777,
267
+ overflow: 'hidden',
264
268
  },
265
269
  shrink: { flexShrink: 1 },
266
270
  content: { padding: Spacing.XL },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/foundation",
3
- "version": "0.169.4-beta.5",
3
+ "version": "0.169.4-beta.7",
4
4
  "description": "React Native Component Kits",
5
5
  "main": "index.ts",
6
6
  "scripts": {},