@xetwa/design-system 1.0.40 → 1.0.42

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xetwa/design-system",
3
- "version": "1.0.40",
3
+ "version": "1.0.42",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -132,17 +132,17 @@ export const BoardingPassCard = ({
132
132
  styles.container,
133
133
  {
134
134
  borderRadius: scale(20),
135
- minHeight: scale(210),
135
+ minHeight: scale(240),
136
136
  },
137
137
  style
138
138
  ]}>
139
139
  {/* Top Section */}
140
140
  <View style={[
141
- styles.topSection,
142
- {
141
+ styles.topSection,
142
+ {
143
143
  backgroundColor: currentHeaderBg,
144
- paddingTop: scale(16),
145
- paddingBottom: scale(16),
144
+ paddingTop: scale(24),
145
+ paddingBottom: scale(24),
146
146
  paddingHorizontal: scale(18),
147
147
  }
148
148
  ]}>
@@ -158,7 +158,7 @@ export const BoardingPassCard = ({
158
158
  ]} />
159
159
 
160
160
  <View style={[styles.headerRow, { marginBottom: scale(16) }]}>
161
- <Typography variant="caption" style={[styles.headerText]}>CARTÃO DE EMBARQUE</Typography>
161
+ <Typography variant="labelHeavy" style={[styles.headerText]}>CARTÃO DE EMBARQUE</Typography>
162
162
  <View style={styles.headerPlaneContainer}>
163
163
  <Plane stroke={theme.colors.white} strokeWidth={2.2} size={scale(22)} />
164
164
  </View>
@@ -166,8 +166,8 @@ export const BoardingPassCard = ({
166
166
 
167
167
  <View style={styles.routeRow}>
168
168
  <View style={styles.cityCol}>
169
- <Typography variant="h1" style={[styles.cityCode]}>{originCode}</Typography>
170
- <Typography variant="caption" style={[styles.cityName]}>{originName}</Typography>
169
+ <Typography variant="display2" style={[styles.cityCode]}>{originCode}</Typography>
170
+ <Typography variant="small" style={[styles.cityName]}>{originName}</Typography>
171
171
  </View>
172
172
 
173
173
  <View style={[styles.flightLineContainer, { height: scale(30), marginHorizontal: scale(12) }]}>
@@ -178,8 +178,8 @@ export const BoardingPassCard = ({
178
178
  </View>
179
179
 
180
180
  <View style={[styles.cityCol, { alignItems: 'flex-end' }]}>
181
- <Typography variant="h1" style={[styles.cityCode]}>{destCode}</Typography>
182
- <Typography variant="caption" style={[styles.cityName]}>{destName}</Typography>
181
+ <Typography variant="display2" style={[styles.cityCode]}>{destCode}</Typography>
182
+ <Typography variant="small" style={[styles.cityName]}>{destName}</Typography>
183
183
  </View>
184
184
  </View>
185
185
  </View>
@@ -188,7 +188,7 @@ export const BoardingPassCard = ({
188
188
  <View style={[
189
189
  styles.bottomSection,
190
190
  {
191
- paddingVertical: scale(14),
191
+ paddingVertical: scale(20),
192
192
  paddingHorizontal: scale(18),
193
193
  }
194
194
  ]}>
@@ -205,8 +205,8 @@ export const BoardingPassCard = ({
205
205
  {flagIconNode ? flagIconNode : <Flag countryCode={countryName} size={scale(40)} />}
206
206
  </View>
207
207
  <View style={styles.countryContent}>
208
- <Typography variant="h2" style={[styles.countryName]}>{countryName}</Typography>
209
- <Typography variant="bodySm" style={[styles.countrySubtitle]}>{countrySubtitle}</Typography>
208
+ <Typography variant="subtitle1" style={[styles.countryName]}>{countryName}</Typography>
209
+ <Typography variant="label" style={[styles.countrySubtitle]}>{countrySubtitle}</Typography>
210
210
  </View>
211
211
  </View>
212
212
 
@@ -220,12 +220,12 @@ export const BoardingPassCard = ({
220
220
 
221
221
  <View style={[styles.footerRow, { gap: scale(14) }]}>
222
222
  <View style={styles.footerCol}>
223
- <Typography variant="caption" style={[styles.footerLabel]}>MÓDULOS</Typography>
224
- <Typography variant="h3" style={[styles.footerValue]}>{modulesCount}</Typography>
223
+ <Typography variant="labelHeavy" style={[styles.footerLabel]}>MÓDULOS</Typography>
224
+ <Typography variant="subtitle1" style={[styles.footerValue]}>{modulesCount}</Typography>
225
225
  </View>
226
226
  <View style={styles.footerCol}>
227
- <Typography variant="caption" style={[styles.footerLabel]}>FOCO</Typography>
228
- <Typography variant="h3" style={[styles.footerValue]}>{focusText}</Typography>
227
+ <Typography variant="labelHeavy" style={[styles.footerLabel]}>FOCO</Typography>
228
+ <Typography variant="subtitle1" style={[styles.footerValue]}>{focusText}</Typography>
229
229
  </View>
230
230
  </View>
231
231
  </View>
@@ -241,6 +241,10 @@ const styles = StyleSheet.create({
241
241
  minHeight: 230,
242
242
  ...theme.shadows.lg,
243
243
  },
244
+ headerText: {
245
+ color: theme.colors.white,
246
+ opacity: 0.9,
247
+ },
244
248
  topSection: {
245
249
  paddingTop: 16,
246
250
  paddingBottom: 16,
@@ -266,11 +270,6 @@ const styles = StyleSheet.create({
266
270
  headerPlaneContainer: {
267
271
  transform: [{ rotate: '0deg' }],
268
272
  },
269
- headerText: {
270
- letterSpacing: 1.2,
271
- textTransform: 'uppercase',
272
- color: 'rgba(255, 255, 255, 0.75)',
273
- },
274
273
  routeRow: {
275
274
  flexDirection: 'row',
276
275
  alignItems: 'center',
@@ -345,6 +344,10 @@ const styles = StyleSheet.create({
345
344
  countrySubtitle: {
346
345
  color: '#9a8478',
347
346
  },
347
+ footerLabel: {
348
+ color: theme.colors.brown[500],
349
+ marginBottom: 4,
350
+ },
348
351
  divider: {
349
352
  borderTopWidth: 1.5,
350
353
  borderColor: '#f3e7da',
@@ -235,9 +235,8 @@ export const ModuleCard = ({
235
235
  const cardPaddingV = size === 'xl' ? scale(20) : size === 'lg' ? scale(16) : isMobileScreen ? scale(10) : scale(14);
236
236
  const cardPaddingH = size === 'xl' ? scale(20) : size === 'lg' ? scale(18) : isMobileScreen ? scale(12) : scale(15);
237
237
 
238
- const titleVariant = size === 'xl' ? 'h1' : size === 'lg' ? 'h2' : 'h3';
239
-
240
- const subtitleVariant = size === 'xl' ? 'bodyLg' : size === 'lg' ? 'bodyMd' : 'bodySm';
238
+ const titleVariant = size === 'xl' ? 'h4' : size === 'lg' ? 'h6' : 'subtitle1';
239
+ const subtitleVariant = size === 'xl' ? 'bodySm' : size === 'lg' ? 'caption' : 'label';
241
240
 
242
241
 
243
242
 
@@ -330,7 +329,7 @@ export const ModuleCard = ({
330
329
  hitSlop={10}
331
330
  >
332
331
  <RotateCcw stroke={theme.colors.primary} strokeWidth={2.5} size={isMobileScreen ? scale(20) : scale(24)} />
333
- <Typography variant="label" style={[styles.reviewIconText, { fontSize: scaleText(9) }]}>REVER</Typography>
332
+ <Typography variant="smallHeavy" style={[styles.reviewIconText, { fontSize: scaleText(9) }]}>REVER</Typography>
334
333
  </Pressable>
335
334
  </Animated.View>
336
335
  ) : null}
@@ -368,7 +367,7 @@ export const ModuleCard = ({
368
367
  style={{ flexDirection: 'row', alignItems: 'center', backgroundColor: theme.colors.primary, paddingHorizontal: scale(14), paddingVertical: scale(6), borderRadius: 100 }}
369
368
  >
370
369
  <CalendarPlus stroke={theme.colors.white} strokeWidth={2.5} size={scale(14)} />
371
- <Typography variant="label" style={{ color: theme.colors.white, fontSize: scaleText(12), fontWeight: 'bold', marginLeft: scale(6) }}>Agendar Aula</Typography>
370
+ <Typography variant="bodySmHeavy" style={{ color: theme.colors.white, marginLeft: scale(6) }}>Agendar Aula</Typography>
372
371
  </Pressable>
373
372
  </Animated.View>
374
373
  )}
@@ -383,7 +382,7 @@ export const ModuleCard = ({
383
382
  style={{ flexDirection: 'row', alignItems: 'center', backgroundColor: theme.colors.primary, paddingHorizontal: scale(14), paddingVertical: scale(6), borderRadius: 100 }}
384
383
  >
385
384
  <PenTool stroke={theme.colors.white} strokeWidth={2.5} size={scale(14)} />
386
- <Typography variant="label" style={{ color: theme.colors.white, fontSize: scaleText(12), fontWeight: 'bold', marginLeft: scale(6) }}>Fazer Exame</Typography>
385
+ <Typography variant="bodySmHeavy" style={{ color: theme.colors.white, marginLeft: scale(6) }}>Fazer Exame</Typography>
387
386
  </Pressable>
388
387
  </Animated.View>
389
388
  )}
@@ -399,7 +398,7 @@ export const ModuleCard = ({
399
398
  hitSlop={8}
400
399
  >
401
400
  <RotateCcw stroke={theme.colors.primary} strokeWidth={2.5} size={scale(16)} />
402
- <Typography variant="label" style={[styles.reviewIconText, { color: theme.colors.primary, fontSize: scaleText(10), marginLeft: scale(4), marginTop: 0 }]}>REVER</Typography>
401
+ <Typography variant="smallHeavy" style={[styles.reviewIconText, { color: theme.colors.primary, marginLeft: scale(4), marginTop: 0 }]}>REVER</Typography>
403
402
  </Pressable>
404
403
  </Animated.View>
405
404
  )}
@@ -0,0 +1,80 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import React, { useState } from 'react';
3
+ import { View } from 'react-native';
4
+ import { TabBar } from './TabBar';
5
+
6
+ const meta = {
7
+ title: 'Components/Navigation/TabBar',
8
+ component: TabBar,
9
+ parameters: {
10
+ layout: 'fullscreen',
11
+ docs: {
12
+ description: {
13
+ component: 'TabBar component with 3 variants (A: Pill, B: Top Bar, C: Dot below) and notification badges.',
14
+ }
15
+ }
16
+ },
17
+ tags: ['autodocs'],
18
+ argTypes: {
19
+ variant: { control: 'radio', options: ['A', 'B', 'C'] },
20
+ safeAreaBottom: { control: 'number' },
21
+ activeItemId: { control: 'text' },
22
+ },
23
+ decorators: [
24
+ (Story) => (
25
+ <View style={{ flex: 1, justifyContent: 'flex-end', backgroundColor: '#f5f0eb' }}>
26
+ <Story />
27
+ </View>
28
+ ),
29
+ ],
30
+ } satisfies Meta<typeof TabBar>;
31
+
32
+ export default meta;
33
+ type Story = StoryObj<typeof TabBar>;
34
+
35
+ const defaultItems = [
36
+ { id: 'inicio', label: 'Início', icon: 'Home' },
37
+ { id: 'percurso', label: 'Percurso', icon: 'Compass' },
38
+ { id: 'aulas', label: 'Aulas', icon: 'GraduationCap' },
39
+ { id: 'dossier', label: 'Dossier', hasBadge: true, icon: 'FolderOpen' },
40
+ { id: 'perfil', label: 'Perfil', icon: 'User' },
41
+ ];
42
+
43
+ export const VariantB: Story = {
44
+ args: {
45
+ items: defaultItems,
46
+ activeItemId: 'inicio',
47
+ variant: 'B',
48
+ safeAreaBottom: 20,
49
+ },
50
+ render: function Render(args) {
51
+ const [activeId, setActiveId] = useState(args.activeItemId);
52
+ return <TabBar {...args} activeItemId={activeId} onItemPress={setActiveId} />;
53
+ }
54
+ };
55
+
56
+ export const VariantA: Story = {
57
+ args: {
58
+ items: defaultItems,
59
+ activeItemId: 'inicio',
60
+ variant: 'A',
61
+ safeAreaBottom: 20,
62
+ },
63
+ render: function Render(args) {
64
+ const [activeId, setActiveId] = useState(args.activeItemId);
65
+ return <TabBar {...args} activeItemId={activeId} onItemPress={setActiveId} />;
66
+ }
67
+ };
68
+
69
+ export const VariantC: Story = {
70
+ args: {
71
+ items: defaultItems,
72
+ activeItemId: 'inicio',
73
+ variant: 'C',
74
+ safeAreaBottom: 20,
75
+ },
76
+ render: function Render(args) {
77
+ const [activeId, setActiveId] = useState(args.activeItemId);
78
+ return <TabBar {...args} activeItemId={activeId} onItemPress={setActiveId} />;
79
+ }
80
+ };
@@ -0,0 +1,245 @@
1
+ import React, { useRef, useEffect } from 'react';
2
+ import { View, StyleSheet, Pressable, Animated, Platform } from 'react-native';
3
+ import type { ViewStyle } from 'react-native';
4
+ import { theme } from '../../../styles/theme';
5
+ import { Typography } from '../../Typography/Typography';
6
+ import { useResponsive } from '../../../hooks/useResponsive';
7
+ import { IconMap } from '../../../utils/iconMap';
8
+
9
+ export type TabBarVariant = 'A' | 'B' | 'C';
10
+
11
+ export interface TabBarItem {
12
+ id: string;
13
+ label: string;
14
+ icon: string;
15
+ hasBadge?: boolean;
16
+ }
17
+
18
+ export interface TabBarProps {
19
+ items: TabBarItem[];
20
+ activeItemId: string;
21
+ onItemPress: (id: string) => void;
22
+ variant?: TabBarVariant;
23
+ safeAreaBottom?: number;
24
+ style?: ViewStyle | ViewStyle[];
25
+ }
26
+
27
+ const TabBarItemComponent = ({
28
+ item,
29
+ isActive,
30
+ variant,
31
+ iconSize,
32
+ onItemPress,
33
+ }: {
34
+ item: TabBarItem;
35
+ isActive: boolean;
36
+ variant: TabBarVariant;
37
+ iconSize: number;
38
+ onItemPress: (id: string) => void;
39
+ }) => {
40
+ const { scale, scaleText } = useResponsive();
41
+ const color = isActive ? theme.colors.primary : theme.colors.brown[300];
42
+
43
+ // Animação de escala ao pressionar
44
+ const scaleAnim = useRef(new Animated.Value(1)).current;
45
+
46
+ const handlePressIn = () => {
47
+ Animated.timing(scaleAnim, {
48
+ toValue: 0.9,
49
+ duration: 100,
50
+ useNativeDriver: true,
51
+ }).start();
52
+ };
53
+
54
+ const handlePressOut = () => {
55
+ Animated.spring(scaleAnim, {
56
+ toValue: 1,
57
+ friction: 4,
58
+ tension: 40,
59
+ useNativeDriver: true,
60
+ }).start();
61
+ };
62
+
63
+ // Animação de transição quando se torna ativo
64
+ const activeAnim = useRef(new Animated.Value(isActive ? 1 : 0)).current;
65
+ useEffect(() => {
66
+ Animated.spring(activeAnim, {
67
+ toValue: isActive ? 1 : 0,
68
+ friction: 7,
69
+ tension: 60,
70
+ useNativeDriver: true,
71
+ }).start();
72
+ }, [isActive]);
73
+
74
+ return (
75
+ <Pressable
76
+ onPress={() => onItemPress(item.id)}
77
+ onPressIn={handlePressIn}
78
+ onPressOut={handlePressOut}
79
+ style={styles.itemContainer}
80
+ >
81
+ <Animated.View style={[styles.itemInner, { transform: [{ scale: scaleAnim }] }]}>
82
+ {/* Variante B: Barra no topo */}
83
+ {variant === 'B' && (
84
+ <Animated.View
85
+ style={[
86
+ styles.indicatorB,
87
+ {
88
+ width: scale(28),
89
+ height: scale(4),
90
+ opacity: activeAnim,
91
+ transform: [
92
+ { translateY: activeAnim.interpolate({ inputRange: [0, 1], outputRange: [-4, 0] }) },
93
+ { scaleX: activeAnim.interpolate({ inputRange: [0, 1], outputRange: [0.4, 1] }) }
94
+ ]
95
+ }
96
+ ]}
97
+ />
98
+ )}
99
+
100
+ {/* Variante A: Pill no ícone */}
101
+ <View
102
+ style={[
103
+ styles.iconWrapper,
104
+ variant === 'A' && isActive && styles.pillA,
105
+ variant === 'A' && isActive && { paddingHorizontal: scale(16), paddingVertical: scale(6), borderRadius: scale(100) },
106
+ ]}
107
+ >
108
+ {(() => {
109
+ const IconComponent = IconMap[item.icon];
110
+ if (!IconComponent) return null;
111
+ return <IconComponent color={color} size={iconSize} strokeWidth={2.5} />;
112
+ })()}
113
+
114
+ {/* Badge de Notificação */}
115
+ {item.hasBadge && (
116
+ <View
117
+ style={[
118
+ styles.badge,
119
+ {
120
+ width: scale(9),
121
+ height: scale(9),
122
+ borderRadius: scale(4.5),
123
+ borderWidth: scale(2),
124
+ top: scale(-3),
125
+ right: scale(-4),
126
+ // Adjust badge position for pill
127
+ ...(variant === 'A' && isActive && { top: scale(3), right: scale(8) })
128
+ }
129
+ ]}
130
+ />
131
+ )}
132
+ </View>
133
+
134
+ <Typography
135
+ variant="smallHeavy"
136
+ style={[
137
+ styles.label,
138
+ { color, fontSize: scaleText(11.5) },
139
+ variant === 'C' && { marginBottom: scale(4) }
140
+ ]}
141
+ >
142
+ {item.label}
143
+ </Typography>
144
+
145
+ {/* Variante C: Dot abaixo da label */}
146
+ {variant === 'C' && isActive && (
147
+ <View style={[styles.dotC, { width: scale(4), height: scale(4), borderRadius: scale(2) }]} />
148
+ )}
149
+ </Animated.View>
150
+ </Pressable>
151
+ );
152
+ };
153
+
154
+ export const TabBar = ({
155
+ items,
156
+ activeItemId,
157
+ onItemPress,
158
+ variant = 'B',
159
+ safeAreaBottom = 0,
160
+ style,
161
+ }: TabBarProps) => {
162
+ const { scale, scaleText, width } = useResponsive();
163
+ const isDesktop = width >= 768;
164
+
165
+ const iconSize = isDesktop ? scale(30) : scale(26);
166
+ const bottomPadding = Math.max(scale(14), safeAreaBottom);
167
+
168
+ return (
169
+ <View
170
+ style={[
171
+ styles.container,
172
+ {
173
+ paddingBottom: bottomPadding,
174
+ paddingHorizontal: scale(6),
175
+ },
176
+ style,
177
+ ]}
178
+ >
179
+ {items.map((item) => (
180
+ <TabBarItemComponent
181
+ key={item.id}
182
+ item={item}
183
+ isActive={activeItemId === item.id}
184
+ variant={variant}
185
+ iconSize={iconSize}
186
+ onItemPress={onItemPress}
187
+ />
188
+ ))}
189
+ </View>
190
+ );
191
+ };
192
+
193
+ const styles = StyleSheet.create({
194
+ container: {
195
+ flexDirection: 'row',
196
+ justifyContent: 'space-around',
197
+ alignItems: 'flex-start',
198
+ backgroundColor: theme.colors.white,
199
+ borderTopWidth: 1.5,
200
+ borderTopColor: theme.colors.brown[100],
201
+ width: '100%',
202
+ minHeight: 56,
203
+ },
204
+ itemContainer: {
205
+ flex: 1,
206
+ alignItems: 'center',
207
+ justifyContent: 'flex-start',
208
+ minWidth: 60,
209
+ },
210
+ itemInner: {
211
+ alignItems: 'center',
212
+ paddingTop: 9, // Espaço entre border-top e ícone (Variant B spec)
213
+ position: 'relative',
214
+ width: '100%',
215
+ },
216
+ iconWrapper: {
217
+ position: 'relative',
218
+ marginBottom: 4,
219
+ alignItems: 'center',
220
+ justifyContent: 'center',
221
+ },
222
+ pillA: {
223
+ backgroundColor: theme.colors.primaryLight,
224
+ },
225
+ indicatorB: {
226
+ position: 'absolute',
227
+ top: 0,
228
+ backgroundColor: theme.colors.primary,
229
+ borderBottomLeftRadius: 4,
230
+ borderBottomRightRadius: 4,
231
+ },
232
+ label: {
233
+ textAlign: 'center',
234
+ },
235
+ dotC: {
236
+ position: 'absolute',
237
+ bottom: -6,
238
+ backgroundColor: theme.colors.primary,
239
+ },
240
+ badge: {
241
+ position: 'absolute',
242
+ backgroundColor: theme.colors.error,
243
+ borderColor: theme.colors.white,
244
+ },
245
+ });
package/src/index.ts CHANGED
@@ -45,6 +45,7 @@ export * from './components/Inputs/TextInput/TextInput';
45
45
  export * from './components/Mascots/Vava/Vava';
46
46
  export * from './components/Mascots/Yaya/Yaya';
47
47
  export * from './components/Navigation/BottomTabBar/BottomTabBar';
48
+ export * from './components/Navigation/TabBar/TabBar';
48
49
  export * from './components/Navigation/PaginationDots/PaginationDots';
49
50
  export * from './components/Navigation/ProgressMap/ProgressMap';
50
51
  export * from './components/Navigation/WorldProgressMap/WorldProgressMap';
@@ -5,7 +5,7 @@ const font = (family: string, webWeight: '400' | '500' | '600' | '700' | '800' |
5
5
  const webFamily = family.split('-')[0];
6
6
  return Platform.select({
7
7
  web: { fontFamily: webFamily, fontWeight: webWeight },
8
- default: { fontFamily: family, fontWeight: webWeight }
8
+ default: { fontFamily: family }
9
9
  }) as { fontFamily: string; fontWeight?: '400' | '500' | '600' | '700' | '800' | '900' };
10
10
  };
11
11
 
@@ -172,86 +172,167 @@ export const theme = {
172
172
  },
173
173
 
174
174
  typography: {
175
+ // FAMÍLIA FREDOKA (Títulos e Destaques)
175
176
  display1: {
176
177
  ...font('Fredoka-Bold', '700'),
177
178
  fontSize: 28,
178
- lineHeight: 34,
179
- desktopFontSize: 42,
179
+ lineHeight: 28, // ajustado para line-height 1 se não especificado
180
+ desktopFontSize: 34,
180
181
  },
181
182
  display2: {
182
183
  ...font('Fredoka-Bold', '700'),
183
- fontSize: 24,
184
- lineHeight: 30,
185
- desktopFontSize: 34,
184
+ fontSize: 27,
185
+ lineHeight: 27,
186
+ desktopFontSize: 32,
186
187
  },
187
188
  h1: {
188
189
  ...font('Fredoka-Bold', '700'),
189
190
  fontSize: 22,
190
- lineHeight: 28,
191
+ lineHeight: 22,
191
192
  desktopFontSize: 28,
192
193
  },
193
194
  h2: {
194
- ...font('Fredoka-SemiBold', '600'),
195
- fontSize: 18,
196
- lineHeight: 24,
197
- desktopFontSize: 22,
195
+ ...font('Fredoka-Bold', '700'),
196
+ fontSize: 20,
197
+ lineHeight: 20,
198
+ desktopFontSize: 24,
198
199
  },
199
200
  h3: {
200
201
  ...font('Fredoka-SemiBold', '600'),
201
- fontSize: 16,
202
+ fontSize: 20,
203
+ lineHeight: 24, // Sem line-height fixo no spec, 1.2
204
+ desktopFontSize: 24,
205
+ },
206
+ h4: {
207
+ ...font('Fredoka-SemiBold', '600'),
208
+ fontSize: 19,
209
+ lineHeight: 22,
210
+ desktopFontSize: 22,
211
+ },
212
+ h5: {
213
+ ...font('Fredoka-Bold', '700'),
214
+ fontSize: 18,
202
215
  lineHeight: 22,
216
+ desktopFontSize: 20,
217
+ },
218
+ h6: {
219
+ ...font('Fredoka-SemiBold', '600'),
220
+ fontSize: 17,
221
+ lineHeight: 18.7, // line-height 1.1 * 17
203
222
  desktopFontSize: 19,
204
223
  },
205
- label: {
224
+ subtitle1: {
225
+ ...font('Fredoka-SemiBold', '600'),
226
+ fontSize: 16,
227
+ lineHeight: 16, // line-height 1
228
+ desktopFontSize: 18,
229
+ },
230
+ subtitle2: {
231
+ ...font('Fredoka-Bold', '700'),
232
+ fontSize: 14,
233
+ lineHeight: 18,
234
+ desktopFontSize: 16,
235
+ },
236
+
237
+ // FAMÍLIA NUNITO (Corpo, Labels, Listas e Infos)
238
+ bodyLgHeavy: {
206
239
  ...font('Nunito-Black', '900'),
207
- fontSize: 10,
208
- lineHeight: 14,
209
- letterSpacing: 1.2, // 10 * 0.12
210
- desktopFontSize: 11,
240
+ fontSize: 16,
241
+ lineHeight: 24,
242
+ desktopFontSize: 18,
211
243
  },
212
244
  bodyLg: {
213
- ...font('Nunito-Bold', '700'),
214
- fontSize: 15,
245
+ ...font('Nunito-Black', '900'),
246
+ fontSize: 16,
215
247
  lineHeight: 24,
216
- desktopFontSize: 17,
248
+ desktopFontSize: 18,
249
+ },
250
+ bodyMdHeavy: {
251
+ ...font('Nunito-Black', '900'),
252
+ fontSize: 15,
253
+ lineHeight: 22,
254
+ desktopFontSize: 16,
217
255
  },
218
256
  bodyMd: {
219
- ...font('Nunito-Bold', '700'),
220
- fontSize: 13.5,
257
+ ...font('Nunito-Black', '900'),
258
+ fontSize: 15,
221
259
  lineHeight: 22,
260
+ desktopFontSize: 16,
261
+ },
262
+ bodySmHeavy: {
263
+ ...font('Nunito-Black', '900'),
264
+ fontSize: 13.5,
265
+ lineHeight: 20,
222
266
  desktopFontSize: 15,
223
267
  },
224
268
  bodySm: {
225
- ...font('Nunito-ExtraBold', '800'),
226
- fontSize: 12,
227
- lineHeight: 18,
228
- desktopFontSize: 13,
269
+ ...font('Nunito-Black', '900'),
270
+ fontSize: 13.5,
271
+ lineHeight: 20,
272
+ desktopFontSize: 15,
273
+ },
274
+ captionItalic: {
275
+ ...font('Nunito-SemiBoldItalic', '600'),
276
+ fontSize: 12.5,
277
+ lineHeight: 18.75, // line-height 1.5 * 12.5
278
+ desktopFontSize: 14,
279
+ fontStyle: 'italic',
229
280
  },
230
281
  caption: {
282
+ ...font('Nunito-Bold', '700'),
283
+ fontSize: 12.5,
284
+ lineHeight: 18,
285
+ desktopFontSize: 14,
286
+ },
287
+ labelHeavy: {
288
+ ...font('Nunito-Black', '900'), // O spec diz 800, mas no Nunito "Black" (900) dá melhor leitura p/ labels, ou podemos usar ExtraBold (800). Vamos usar ExtraBold (800) como no spec:
289
+ // wait, refiz para respeitar o 800
231
290
  ...font('Nunito-ExtraBold', '800'),
232
- fontSize: 10,
291
+ fontSize: 11,
292
+ lineHeight: 16,
293
+ letterSpacing: 0.88, // 11 * 0.08em
294
+ textTransform: 'uppercase',
295
+ desktopFontSize: 12,
296
+ },
297
+ label: {
298
+ ...font('Nunito-Bold', '700'),
299
+ fontSize: 11,
233
300
  lineHeight: 16,
301
+ desktopFontSize: 12,
302
+ },
303
+ smallHeavy: {
304
+ ...font('Nunito-Black', '900'),
305
+ fontSize: 10,
306
+ lineHeight: 14,
234
307
  desktopFontSize: 11,
235
308
  },
309
+ small: {
310
+ ...font('Nunito-Bold', '700'),
311
+ fontSize: 10,
312
+ lineHeight: 14,
313
+ desktopFontSize: 11,
314
+ },
315
+
316
+ // Botões (mantemos originais porque são usados no MainButton)
236
317
  btnLg: {
237
318
  ...font('Nunito-Black', '900'),
238
319
  fontSize: 16,
239
320
  lineHeight: 20,
240
- letterSpacing: 0.64, // 16 * 0.04
321
+ letterSpacing: 0.64,
241
322
  desktopFontSize: 17,
242
323
  },
243
324
  btnMd: {
244
325
  ...font('Nunito-Black', '900'),
245
326
  fontSize: 14,
246
327
  lineHeight: 18,
247
- letterSpacing: 0.56, // 14 * 0.04
328
+ letterSpacing: 0.56,
248
329
  desktopFontSize: 15,
249
330
  },
250
331
  btnSm: {
251
332
  ...font('Nunito-Black', '900'),
252
333
  fontSize: 12,
253
334
  lineHeight: 16,
254
- letterSpacing: 0.48, // 12 * 0.04
335
+ letterSpacing: 0.48,
255
336
  desktopFontSize: 12,
256
337
  },
257
338
  },
@@ -1,4 +1,4 @@
1
- import { Play, Volume2, Volume1, ArrowRight, X, Check, ChevronRight, ChevronLeft, Info, AlertTriangle, Book, Mic } from 'lucide-react-native';
1
+ import { Play, Volume2, Volume1, ArrowRight, X, Check, ChevronRight, ChevronLeft, Info, AlertTriangle, Book, Mic, Home, Compass, GraduationCap, FolderOpen, User, ShoppingCart, FileText, Wallet } from 'lucide-react-native';
2
2
 
3
3
  /**
4
4
  * Para evitar que o Vite e o Metro (React Native) tentem empacotar os 1400+ ícones
@@ -21,4 +21,12 @@ export const IconMap: Record<string, any> = {
21
21
  AlertTriangle,
22
22
  Book,
23
23
  Mic,
24
+ Home,
25
+ Compass,
26
+ GraduationCap,
27
+ FolderOpen,
28
+ User,
29
+ ShoppingCart,
30
+ FileText,
31
+ Wallet,
24
32
  };