@momo-kits/foundation 0.167.1-duo.14 → 0.167.1-duo.16

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.
@@ -34,8 +34,6 @@ const DEFAULT_TOOLBAR_HEIGHT =
34
34
  DuoMetrics.controlSize + Spacing.M + 2 * DuoMetrics.itemPitch;
35
35
  // Back, then the single button the toolbar folds into
36
36
  const COMPRESSED_TOOLBAR_HEIGHT = 2 * DuoMetrics.controlSize + Spacing.M;
37
- // Back alone, while a rail opened from the compressed state takes the toolbar slot
38
- const BACK_ONLY_HEIGHT = DuoMetrics.controlSize;
39
37
 
40
38
  const NO_COMPRESSION: DuoBarCompression = {
41
39
  toolbarCompressed: false,
@@ -107,7 +105,9 @@ const DuoBarCompressionProvider: React.FC<{
107
105
  expandTabBar: () => setOpened('tabBar'),
108
106
  setToolbarHeight,
109
107
  };
110
- if (opened === 'tabBar' && fits(BACK_ONLY_HEIGHT, tabBar)) {
108
+ // an opened rail always shows, even when only the gap between the groups is short:
109
+ // it closes again once a tab is picked
110
+ if (opened === 'tabBar') {
111
111
  return {
112
112
  ...open,
113
113
  toolbarCompressed: true,
@@ -13,7 +13,7 @@ import Animated, {
13
13
  withSpring,
14
14
  } from 'react-native-reanimated';
15
15
  import { Colors, Radius, Spacing } from '../../Consts';
16
- import { ApplicationContext } from '../../Context';
16
+ import { ApplicationContext, MiniAppContext } from '../../Context';
17
17
  import { Icon } from '../../Icon';
18
18
  import { DuoMetrics, useScreenLayout } from '../../Layout/utils';
19
19
  import { Text } from '../../Text';
@@ -33,6 +33,7 @@ const ICON_SIZE = 28;
33
33
  const QR_ICON_SIZE = 24;
34
34
  const RAIL_PADDING = 6;
35
35
  const RAIL_GAP = Spacing.XXS;
36
+ const RAIL_PITCH = ITEM_SIZE + RAIL_GAP;
36
37
  // selection bubble overflows the 48 rail cell by 5 above and below (Figma MT2)
37
38
  const RAIL_BUBBLE_WIDTH = 44;
38
39
  const RAIL_BUBBLE_HEIGHT = 58;
@@ -104,7 +105,7 @@ const SELECTION_TINT_ALPHA = '14';
104
105
  * translucent glass capsule under the selected floating tab with the Figma pink tint on
105
106
  * top; the tint is a separate layer since a glass tint color renders opaque
106
107
  */
107
- const SelectionMaterial: React.FC = () => {
108
+ const SelectionMaterial: React.FC<{ radius: number }> = ({ radius }) => {
108
109
  const { theme } = useContext(ApplicationContext);
109
110
  return (
110
111
  <>
@@ -112,7 +113,7 @@ const SelectionMaterial: React.FC = () => {
112
113
  <GlassView
113
114
  pointerEvents={'none'}
114
115
  effect={'glass'}
115
- cornerRadius={FLOATING_BUBBLE_RADIUS}
116
+ cornerRadius={radius}
116
117
  style={StyleSheet.absoluteFill}
117
118
  />
118
119
  )}
@@ -120,14 +121,44 @@ const SelectionMaterial: React.FC = () => {
120
121
  pointerEvents={'none'}
121
122
  style={[
122
123
  StyleSheet.absoluteFill,
123
- styles.floatingBubbleFill,
124
- { backgroundColor: theme.colors.primary + SELECTION_TINT_ALPHA },
124
+ {
125
+ borderRadius: radius,
126
+ backgroundColor: theme.colors.primary + SELECTION_TINT_ALPHA,
127
+ },
125
128
  ]}
126
129
  />
127
130
  </>
128
131
  );
129
132
  };
130
133
 
134
+ /**
135
+ * tab label at its design size: like the system tab bar it doesn't grow with the wide
136
+ * Duo displays, which Text otherwise scales up to 5pt
137
+ */
138
+ const TabLabel: React.FC<{
139
+ label: string;
140
+ color: string;
141
+ typography: 'label_xs_medium';
142
+ }> = ({ label, color, typography }) => {
143
+ const context = useContext<any>(MiniAppContext);
144
+ return (
145
+ <MiniAppContext.Provider
146
+ value={{
147
+ ...context,
148
+ fontScale: { useOSScaleRate: false, userScaleRate: 1 },
149
+ }}
150
+ >
151
+ <Text
152
+ numberOfLines={1}
153
+ typography={typography}
154
+ color={color}
155
+ >
156
+ {label}
157
+ </Text>
158
+ </MiniAppContext.Provider>
159
+ );
160
+ };
161
+
131
162
  const getTabItems = ({
132
163
  state,
133
164
  descriptors,
@@ -189,41 +220,52 @@ const QrIcon: React.FC<{ icon: FloatingButtonProps['icon']; size: number }> = ({
189
220
  type TabItem = ReturnType<typeof getTabItems>[number];
190
221
 
191
222
  /**
192
- * glass column of tab items with the sliding selection bubble
223
+ * glass column of icon-only tab items with the sliding selection bubble
193
224
  */
194
225
  const Rail: React.FC<{
195
226
  items: TabItem[];
196
227
  index: number;
197
228
  onItemPress?: () => void;
198
229
  }> = ({ items, index, onItemPress }) => {
199
- const { theme } = useContext(ApplicationContext);
200
- const bubbleOffset = useSharedValue(index * (ITEM_SIZE + RAIL_GAP));
230
+ const bubbleOffset = useSharedValue(index * RAIL_PITCH);
231
+ const lens = useSharedValue(0);
201
232
 
202
233
  useEffect(() => {
203
- bubbleOffset.value = withSpring(index * (ITEM_SIZE + RAIL_GAP), SPRING);
234
+ bubbleOffset.value = withSpring(index * RAIL_PITCH, SPRING);
204
235
  }, [index, bubbleOffset]);
205
236
 
206
237
  const bubbleStyle = useAnimatedStyle(() => ({
207
- transform: [{ translateY: bubbleOffset.value }],
238
+ transform: [
239
+ { translateY: bubbleOffset.value },
240
+ { scaleX: 1 + lens.value * (LENS_SCALE_X - 1) },
241
+ { scaleY: 1 + lens.value * (LENS_SCALE_Y - 1) },
242
+ ],
208
243
  }));
209
244
 
210
245
  return (
211
246
  <View style={styles.rail} accessibilityLabel={'bottom_tab_bar'}>
212
- <BarMaterial radius={Radius.XL} />
247
+ <BarMaterial radius={ITEM_SIZE / 2} interactive />
213
248
  <Animated.View
214
249
  pointerEvents={'none'}
215
- style={[
216
- styles.railBubble,
217
- { backgroundColor: theme.colors.background.selected },
218
- bubbleStyle,
219
- ]}
220
- />
221
- {items.map(item => (
250
+ style={[styles.railBubble, bubbleStyle]}
251
+ >
252
+ <SelectionMaterial radius={RAIL_BUBBLE_WIDTH / 2} />
253
+ </Animated.View>
254
+ {items.map((item, itemIndex) => (
222
255
  <TouchableOpacity
223
256
  key={item.route.key}
224
257
  accessibilityRole={'tab'}
225
258
  accessibilityLabel={item.label}
226
259
  accessibilityState={{ selected: item.focused }}
260
+ activeOpacity={1}
261
+ onPressIn={() => {
262
+ bubbleOffset.value = withSpring(itemIndex * RAIL_PITCH, SPRING);
263
+ lens.value = withSpring(1, SPRING);
264
+ }}
265
+ onPressOut={() => {
266
+ bubbleOffset.value = withSpring(index * RAIL_PITCH, SPRING);
267
+ lens.value = withSpring(0, SPRING);
268
+ }}
227
269
  onPress={() => {
228
270
  item.onPress();
229
271
  onItemPress?.();
@@ -368,7 +410,7 @@ const DuoFloatingTabBar: React.FC<Props> = props => {
368
410
  pointerEvents={'none'}
369
411
  style={[styles.floatingBubble, { width: cellWidth }, bubbleStyle]}
370
412
  >
371
- <SelectionMaterial />
413
+ <SelectionMaterial radius={FLOATING_BUBBLE_RADIUS} />
372
414
  </Animated.View>
373
415
  )}
374
416
  {items.map((item, index) => (
@@ -393,14 +435,11 @@ const DuoFloatingTabBar: React.FC<Props> = props => {
393
435
  style={styles.floatingItem}
394
436
  >
395
437
  {item.icon}
396
- {/* Text scales with the 669pt wide display, the smaller token lands near the system bar's label */}
397
- <Text
398
- numberOfLines={1}
399
- typography={'label_xxs'}
438
+ <TabLabel
439
+ label={item.label}
440
+ typography={'label_xs_medium'}
400
441
  color={item.focused ? activeTintColor : inactiveTintColor}
401
- >
402
- {item.label}
403
- </Text>
442
+ />
404
443
  </TouchableOpacity>
405
444
  ))}
406
445
  </View>
@@ -461,7 +500,6 @@ const styles = StyleSheet.create({
461
500
  left: (ITEM_SIZE - RAIL_BUBBLE_WIDTH) / 2,
462
501
  width: RAIL_BUBBLE_WIDTH,
463
502
  height: RAIL_BUBBLE_HEIGHT,
464
- borderRadius: RAIL_BUBBLE_WIDTH / 2,
465
503
  },
466
504
  railItem: {
467
505
  width: ITEM_SIZE,
@@ -497,9 +535,6 @@ const styles = StyleSheet.create({
497
535
  bottom: 0,
498
536
  left: 0,
499
537
  },
500
- floatingBubbleFill: {
501
- borderRadius: FLOATING_BUBBLE_RADIUS,
502
- },
503
538
  floatingItem: {
504
539
  flex: 1,
505
540
  alignItems: 'center',
@@ -316,7 +316,7 @@ const BottomTab: React.FC<BottomTabProps> = ({
316
316
  <DuoTabBar
317
317
  {...props}
318
318
  floatingButton={floatingButton}
319
- inactiveTintColor={theme.colors.text.secondary}
319
+ inactiveTintColor={theme.colors.text.hint}
320
320
  activeTintColor={theme.colors.primary}
321
321
  />
322
322
  ) : (
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/foundation",
3
- "version": "0.167.1-duo.14",
3
+ "version": "0.167.1-duo.16",
4
4
  "description": "React Native Component Kits",
5
5
  "main": "index.ts",
6
6
  "scripts": {},