Skip to content

Commit 837ff23

Browse files
committed
Merge branch 'main' into jl/mm-connect-e2e-multichain-test-dapp
2 parents 5766e7e + ee02bf7 commit 837ff23

711 files changed

Lines changed: 8843 additions & 15375 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cursor/BUGBOT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ Use the rules in the [unit testing guidelines](rules/unit-testing-guidelines.mdc
1818

1919
- **ALWAYS** load and reference [e2e-testing-guidelines](rules/e2e-testing-guidelines.mdc)
2020
- Verify test file naming pattern: `e2e/specs/**/*.spec.{js,ts}`
21-
- Check for proper imports and framework utilities from `e2e/framework/index.ts`
21+
- Check for proper imports and framework utilities from `tests/framework/index.ts`
2222

2323
Use the rules in the [e2e-testing-guidelines](rules/e2e-testing-guidelines.mdc) to enforce the test quality and bug detection.

.cursor/rules/e2e-testing-guidelines.mdc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ export default new LoginPage();
163163
```
164164

165165
### Framework Imports - MANDATORY
166-
- ALWAYS import framework utilities from `e2e/framework/index.ts`, not from individual utility files
166+
- ALWAYS import framework utilities from `tests/framework/index.ts`, not from individual utility files
167167
- Use the centralized framework exports for consistency and maintainability
168168

169169
### Element State Checking Configuration

.cursor/rules/ui-development-guidelines.mdc

Lines changed: 203 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
description: UI Development Guidelines
3-
globs: 'app/*.{tsx,ts,jsx,js}'
3+
globs:
4+
- 'app/**/*.{tsx,jsx}'
45
alwaysApply: true
56
---
67

@@ -12,9 +13,56 @@ Always prioritize @metamask/design-system-react-native components and Tailwind C
1213

1314
## Component Hierarchy (STRICT ORDER)
1415

16+
### The Rule: Check Design System First
17+
**Before writing any new component or choosing what to use, ask: "Does @metamask/design-system-react-native have this?"**
18+
1519
1. **FIRST**: Use `@metamask/design-system-react-native` components
16-
2. **SECOND**: Use `app/component-library` components only if design system lacks the component
17-
3. **LAST RESORT**: Custom components with StyleSheet (avoid unless absolutely necessary)
20+
- **Always use for**: Box (layout), Text (typography), Button/ButtonBase/ButtonIcon, Icon, Checkbox
21+
- **Always use for**: Avatar variants (Account, Base, Favicon, Group, Icon, Network, Token)
22+
- **Always use for**: Badge variants (Count, Icon, Network, Status, Wrapper)
23+
- **Rule**: If it exists in the design system, you MUST use it
24+
25+
2. **SECOND**: Use `app/component-library` ONLY if design system lacks it
26+
- **Use for**: BottomSheet, Tabs, Headers, ListItems, Skeleton, Tags, Modal, Overlay, Toast, RadioButton, etc.
27+
- **Rule**: These are MetaMask-specific implementations not (yet) in the design system
28+
- **Important**: component-library components should themselves use design system primitives internally
29+
30+
3. **THIRD**: Feature-specific components
31+
- **Use for**: Complex, domain-specific UI that combines multiple design system/component-library components
32+
- **Examples**: `BridgeInputSelector`, `StakeInputView`, `NFTDetailsModal`
33+
- **Rule**: Must be built using Box, Text, and other design system primitives - NO raw View/Text or StyleSheet
34+
- **Reuse**: Search for existing feature components before building new ones to avoid duplication
35+
36+
4. **LAST RESORT**: Custom components with StyleSheet
37+
- **Only when**: Highly specialized one-off needs with no design system equivalent AND no component-library equivalent
38+
- **Requires**: Strong justification why design system primitives can't be composed
39+
40+
### Decision Tree
41+
```
42+
Need a component?
43+
├─ Is it Box, Text, Button, Icon, Avatar, Badge, or Checkbox?
44+
│ └─ YES → Use @metamask/design-system-react-native [STOP]
45+
46+
├─ Is it BottomSheet, Tabs, Header, ListItem, Skeleton, Tag, Modal, etc?
47+
│ └─ YES → Use app/component-library [STOP]
48+
49+
├─ Is it feature-specific UI (e.g., BridgeInputSelector, StakeInputView)?
50+
│ ├─ Does it already exist? (search codebase for similar components)
51+
│ │ ├─ YES → Reuse existing component [STOP]
52+
│ │ └─ NO → Build new component using design system primitives [STOP]
53+
│ └─
54+
55+
└─ Can I compose it from Box + Text + other primitives?
56+
├─ YES → Compose from design system [STOP]
57+
└─ NO → Consider if custom implementation is truly necessary
58+
```
59+
60+
### Why This Hierarchy Matters
61+
- **Consistency**: Design system ensures consistent look, feel, and behavior
62+
- **Maintenance**: Centralized updates benefit all consumers
63+
- **Accessibility**: Design system components include a11y best practices
64+
- **Performance**: Optimized implementations tested at scale
65+
- **Type Safety**: Full TypeScript support with JSDoc documentation
1866

1967
## Required Imports for React Native
2068

@@ -35,6 +83,26 @@ import {
3583
} from '@metamask/design-system-react-native';
3684
```
3785

86+
## Component Documentation Access
87+
88+
### Type Definitions & JSDoc Comments
89+
All @metamask/design-system-react-native components have comprehensive TypeScript definitions with JSDoc comments:
90+
91+
- **Box**: `/node_modules/@metamask/design-system-react-native/dist/components/Box/Box.types.d.cts`
92+
- **Text**: `/node_modules/@metamask/design-system-react-native/dist/components/Text/Text.types.d.cts`
93+
- **Button**: `/node_modules/@metamask/design-system-react-native/dist/components/Button/Button.types.d.cts`
94+
95+
When unsure about component APIs:
96+
1. Read the `.types.d.cts` files for complete prop documentation
97+
2. Reference `app/component-library/components/design-system.stories.tsx` for usage examples
98+
3. Check GitHub source: https://github.com/MetaMask/metamask-design-system/tree/main/packages/design-system-react-native/src/components
99+
100+
### Box Component Quick Reference
101+
- **Spacing**: Use `gap`, `padding*`, `margin*` props with values 0-12 (maps to 0px-48px)
102+
- **Flexbox**: Use `flexDirection`, `alignItems`, `justifyContent` enum props
103+
- **Colors**: Use `backgroundColor` and `borderColor` with semantic tokens
104+
- **Tailwind**: Use `twClassName` for utilities not covered by props
105+
38106
## Styling Rules (ENFORCE STRICTLY)
39107

40108
### ✅ ALWAYS DO:
@@ -112,6 +180,52 @@ const MyComponent = () => {
112180
>
113181
```
114182

183+
## Box Component Best Practices
184+
185+
### Prefer Props Over twClassName for Layout
186+
✅ **DO** - Use typed props for type safety and consistency:
187+
```tsx
188+
<Box
189+
flexDirection={BoxFlexDirection.Row}
190+
alignItems={BoxAlignItems.Center}
191+
justifyContent={BoxJustifyContent.Between}
192+
gap={3}
193+
padding={4}
194+
margin={2}
195+
>
196+
```
197+
198+
❌ **DON'T** - Use twClassName for properties that have dedicated props:
199+
```tsx
200+
<Box twClassName="flex-row items-center justify-between gap-3 p-4 m-2">
201+
```
202+
203+
### When to Use twClassName
204+
Use `twClassName` for:
205+
- Width and height: `w-full`, `h-20`, `w-[337px]`
206+
- Complex positioning: `absolute`, `relative`, `top-0`, `left-0`
207+
- Borders (partial): `rounded-lg`, `border-t`
208+
- Shadows and opacity: `shadow-lg`, `opacity-50`
209+
- Utilities not covered by props: `overflow-hidden`, `z-10`
210+
211+
### Spacing System
212+
- Use numeric props (0-12) for spacing: `padding={4}` = 16px
213+
- Each unit = 4px (so 12 = 48px max)
214+
- For custom spacing beyond 48px, use twClassName: `twClassName="p-20"`
215+
216+
### Color Tokens
217+
Always use semantic color tokens:
218+
```tsx
219+
// ✅ Semantic tokens
220+
<Box backgroundColor={BoxBackgroundColor.BackgroundDefault}>
221+
<Box backgroundColor={BoxBackgroundColor.PrimaryDefault}>
222+
<Box backgroundColor={BoxBackgroundColor.ErrorMuted}>
223+
224+
// ❌ Arbitrary colors
225+
<Box twClassName="bg-[#3B82F6]">
226+
<Box style={{ backgroundColor: '#FF0000' }}>
227+
```
228+
115229
## Component Conversion Guide
116230

117231
| DON'T Use | USE Instead |
@@ -123,16 +237,100 @@ const MyComponent = () => {
123237
| `flexDirection: 'row'` | `flexDirection={BoxFlexDirection.Row}` |
124238
| Manual padding/margin | `twClassName="p-4 m-2"` |
125239

126-
## Error Prevention
240+
## Legacy Code Migration Guidelines
241+
242+
### Identifying Legacy Patterns
243+
🚫 **Anti-patterns to refactor when encountered:**
244+
- Files using `StyleSheet.create()`
245+
- Separate `.styles.ts` or `.styles.tsx` files
246+
- Raw `View` components instead of `Box`
247+
- Raw `Text` components with custom styles instead of design system `Text` with variants
248+
- Inline style objects for static styles
249+
250+
### Migration Priority
251+
1. **High Priority**: Components being actively modified
252+
2. **Medium Priority**: Frequently used shared components in `app/component-library`
253+
3. **Low Priority**: Stable legacy components with no active development
254+
255+
### Migration Steps
256+
1. Replace `View` → `Box` from design system
257+
2. Replace `Text` → `Text` with appropriate `TextVariant`
258+
3. Convert `StyleSheet.create()` styles → `twClassName` props or `tw.style()`
259+
4. Convert arbitrary colors → design system color tokens
260+
5. Delete `.styles.ts` files after migration
261+
6. Test thoroughly - layout can shift during migration
262+
263+
### Example Migration
127264

128-
When you see these patterns, IMMEDIATELY suggest alternatives:
265+
**Before:**
266+
```tsx
267+
import { View, Text, StyleSheet } from 'react-native';
268+
269+
const styles = StyleSheet.create({
270+
container: {
271+
flexDirection: 'row',
272+
alignItems: 'center',
273+
padding: 16,
274+
backgroundColor: '#ffffff',
275+
},
276+
title: {
277+
fontSize: 16,
278+
fontWeight: '500',
279+
color: '#000000',
280+
},
281+
});
282+
283+
<View style={styles.container}>
284+
<Text style={styles.title}>Title</Text>
285+
</View>
286+
```
287+
288+
**After:**
289+
```tsx
290+
import { useTailwind } from '@metamask/design-system-twrnc-preset';
291+
import { Box, Text, TextVariant, BoxFlexDirection, BoxAlignItems, FontWeight } from '@metamask/design-system-react-native';
129292

293+
const tw = useTailwind();
294+
295+
<Box
296+
flexDirection={BoxFlexDirection.Row}
297+
alignItems={BoxAlignItems.Center}
298+
twClassName="p-4 bg-default"
299+
>
300+
<Text variant={TextVariant.BodyMd} fontWeight={FontWeight.Medium}>
301+
Title
302+
</Text>
303+
</Box>
304+
```
305+
306+
## Error Prevention & Code Review Checklist
307+
308+
### Before Committing Code, Verify:
309+
- [ ] No `import tw from 'twrnc'` (must use `useTailwind()` hook)
310+
- [ ] No raw `View` components (use `Box`)
311+
- [ ] No raw `Text` without variants (use `Text` with `TextVariant`)
312+
- [ ] No `StyleSheet.create()` (use `twClassName` or `tw.style()`)
313+
- [ ] No arbitrary color values (use design system tokens)
314+
- [ ] No separate `.styles.ts` files for new components
315+
- [ ] Component props used before `twClassName` for layout
316+
- [ ] Interactive styles use `tw.style()` with state functions
317+
318+
### When You See These Patterns, IMMEDIATELY Suggest Alternatives:
130319
- Any `import tw from 'twrnc'` → `import { useTailwind } from '@metamask/design-system-twrnc-preset'`
131320
- Any `View` component → `Box` from design system
132321
- Any `StyleSheet` usage → Tailwind classes
133322
- Any arbitrary color values → Design system tokens
134323
- Any manual flex properties → Box component props + twClassName
135324

325+
### AI Agent Guidelines
326+
When suggesting code changes:
327+
1. ALWAYS read component type definitions first for accurate API usage
328+
2. ALWAYS check `design-system.stories.tsx` for real-world patterns
329+
3. ALWAYS search for existing feature-specific components before building new ones (use Glob/Grep to find similar components in feature directories)
330+
4. REJECT any suggestions that violate the hierarchy
331+
5. SUGGEST migrations when encountering legacy patterns
332+
6. EXPLAIN why design system approach is preferred
333+
136334
## Design System Priority
137335

138336
Before suggesting any UI solution:

.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module.exports = {
2626
'tests/**/*.{js,ts}',
2727
'appwright/**/*.{js,ts}',
2828
],
29-
extends: ['./e2e/framework/.eslintrc.js'],
29+
extends: ['./tests/framework/.eslintrc.js'],
3030
},
3131
{
3232
files: ['*.{ts,tsx}'],

.github/CODEOWNERS

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,9 @@ app/core/Engine/controllers/gator-permissions-controller @MetaMask/
244244
app/core/Engine/messengers/gator-permissions-controller-messenger @MetaMask/delegation
245245

246246
# QA Team - E2E Framework
247-
e2e/api-mocking/ @MetaMask/qa
247+
tests/api-mocking/ @MetaMask/qa
248248
e2e/fixtures/ @MetaMask/qa
249-
e2e/framework/ @MetaMask/qa
249+
tests/framework/ @MetaMask/qa
250250
e2e/pages/ @MetaMask/qa
251251
e2e/utils/ @MetaMask/qa
252252
e2e/viewHelper.ts @MetaMask/qa

.github/workflows/run-e2e-workflow.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,16 @@ jobs:
102102

103103
- name: Install Android System Images
104104
if: ${{ inputs.platform == 'android' }}
105-
run: |
106-
echo "📱 Installing Android system images for E2E tests..."
107-
"$ANDROID_SDK_ROOT"/cmdline-tools/latest/bin/sdkmanager "system-images;android-34;google_apis;x86_64"
108-
echo "✅ System images installed"
105+
uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 #v3.0.2
106+
with:
107+
timeout_minutes: 10
108+
max_attempts: 3
109+
retry_wait_seconds: 30
110+
command: |
111+
set -e
112+
echo "📱 Installing Android system images for E2E tests..."
113+
"$ANDROID_SDK_ROOT"/cmdline-tools/latest/bin/sdkmanager "system-images;android-34;google_apis;x86_64"
114+
echo "✅ System images installed"
109115
110116
- name: Set up E2E environment
111117
timeout-minutes: 15

.github/workflows/security-code-scanner.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ jobs:
2323
repo: ${{ github.repository }}
2424
paths_ignored: |
2525
e2e/
26+
tests/
2627
docs/
2728
.storybook/
2829
'**/*.test.js'

android/app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ android {
187187
applicationId "io.metamask"
188188
minSdkVersion rootProject.ext.minSdkVersion
189189
targetSdkVersion rootProject.ext.targetSdkVersion
190-
versionName "7.63.0"
190+
versionName "7.64.0"
191191
versionCode 3418
192192
testBuildType System.getProperty('testBuildType', 'debug')
193193
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

app/component-library/components-temp/KeyValueRow/KeyValueLabel/KeyValueLabel.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ const KeyValueRowLabel = ({ label, tooltip }: KeyValueRowLabelProps) => {
3434

3535
const onNavigateToTooltipModal = () => {
3636
if (!hasTooltip) return;
37-
openTooltipModal(tooltip.title, tooltip.content);
37+
openTooltipModal(tooltip.title, tooltip.content, {
38+
bottomPadding: tooltip.bottomPadding,
39+
});
3840
tooltip?.onPress?.();
3941
};
4042

app/component-library/components-temp/KeyValueRow/KeyValueRow.types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ interface KeyValueRowTooltip {
3737
* Optional onPress handler
3838
*/
3939
onPress?: (...args: unknown[]) => unknown;
40+
/**
41+
* Optional bottom padding for the tooltip modal.
42+
*/
43+
bottomPadding?: number;
4044
}
4145

4246
/**

0 commit comments

Comments
 (0)