• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

agentic-dev-library / thumbcode / 21961208242

12 Feb 2026 07:29PM UTC coverage: 51.569% (-13.4%) from 64.947%
21961208242

push

github

web-flow
feat: complete Expo → Capacitor/Vite migration (#130)

## Summary

Full framework migration from Expo/React Native to Vite + Capacitor + React Router:

- **Framework**: Expo SDK 52 → Vite 6 + Capacitor 7
- **Routing**: expo-router → react-router-dom v7
- **Styling**: NativeWind → Tailwind CSS v4
- **Testing**: Jest → Vitest + @testing-library/react
- **Components**: React Native primitives → HTML/JSX (View→div, Text→span, etc.)
- **Build**: Metro bundler → Vite with HMR

### Key changes
- Removed all React Native and Expo dependencies
- Migrated 50+ components from RN to web HTML/JSX
- Rewrote 70 test files (844 tests passing)
- Replaced deploy-gh-pages.yml: Astro docs → Vite static site deployment
- Added android-release.yml: per-architecture debug APKs on GitHub releases
- Added ABI splits to build.gradle (armeabi-v7a, arm64-v8a, x86_64, universal)
- Fixed all biome lint, TypeScript, and E2E test issues
- Deleted dead `app/` directory (old Expo Router screens)

### CI Status
All critical checks passing: Lint & Type Check, Run Tests (844 passing), Build Web, Build Web + Capacitor Sync, E2E Tests (Web), Security Scan, CodeQL, Validate PR.

1329 of 2944 branches covered (45.14%)

Branch coverage included in aggregate %.

138 of 866 new or added lines in 82 files covered. (15.94%)

120 existing lines in 23 files now uncovered.

2188 of 3876 relevant lines covered (56.45%)

9.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

66.67
/src/components/ui/Text.tsx
1
/** Props for the Text component */
2
interface TextProps extends React.HTMLAttributes<HTMLSpanElement> {
3
  /** Font family variant (display, body, or monospace) */
4
  variant?: 'display' | 'body' | 'mono';
5
  /** Text size preset */
6
  size?: 'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl';
7
  /** Font weight */
8
  weight?: 'normal' | 'medium' | 'semibold' | 'bold';
9
  /** Additional Tailwind class names */
10
  className?: string;
11
  /** Truncation - max number of lines (maps to CSS line-clamp) */
12
  numberOfLines?: number;
13
  /** Test ID */
14
  testID?: string;
15
  /** Accessibility role */
16
  accessibilityRole?: string;
17
  /** Accessibility label */
18
  accessibilityLabel?: string;
19
  /** Accessibility elements hidden */
20
  accessibilityElementsHidden?: boolean;
21
}
22

23
/**
24
 * A Text component that standardizes typography by applying font variant, size, and weight classes.
25
 *
26
 * @param variant - Font variant to use; one of `"display"`, `"body"`, or `"mono"`. Defaults to `"body"`.
27
 * @param size - Text size to apply. Defaults to `"base"`.
28
 * @param weight - Font weight to apply. Defaults to `"normal"`.
29
 * @param className - Additional class names to append to the computed classes.
30
 * @returns A span element with class names composed from `variant`, `size`, `weight`, and `className`.
31
 */
32
export function Text({
33
  variant = 'body',
132✔
34
  size = 'base',
132✔
35
  weight = 'normal',
132✔
36
  className = '',
132✔
37
  children,
38
  numberOfLines,
39
  testID,
40
  accessibilityRole,
41
  accessibilityLabel,
42
  accessibilityElementsHidden,
43
  style,
44
  ...props
45
}: Readonly<TextProps>) {
46
  const variantClass = {
132✔
47
    display: 'font-display',
48
    body: 'font-body',
49
    mono: 'font-mono',
50
  }[variant];
51

52
  const sizeClass = {
132✔
53
    xs: 'text-xs',
54
    sm: 'text-sm',
55
    base: 'text-base',
56
    lg: 'text-lg',
57
    xl: 'text-xl',
58
    '2xl': 'text-2xl',
59
    '3xl': 'text-3xl',
60
    '4xl': 'text-4xl',
61
    '5xl': 'text-5xl',
62
  }[size];
63

64
  const weightClass = {
132✔
65
    normal: 'font-normal',
66
    medium: 'font-medium',
67
    semibold: 'font-semibold',
68
    bold: 'font-bold',
69
  }[weight];
70

71
  const lineClampStyle: React.CSSProperties | undefined = numberOfLines
132✔
72
    ? {
73
        overflow: 'hidden',
74
        display: '-webkit-box',
75
        WebkitLineClamp: numberOfLines,
76
        WebkitBoxOrient: 'vertical',
77
      }
78
    : undefined;
79

80
  const ariaProps: Record<string, unknown> = {};
132✔
81
  if (accessibilityRole) {
132!
NEW
82
    ariaProps.role = accessibilityRole as React.AriaRole;
×
NEW
83
    if (accessibilityLabel) {
×
NEW
84
      ariaProps['aria-label'] = accessibilityLabel;
×
85
    }
86
  }
87
  if (accessibilityElementsHidden !== undefined) {
132!
NEW
88
    ariaProps['aria-hidden'] = accessibilityElementsHidden;
×
89
  }
90

91
  return (
132✔
92
    <span
93
      className={`${variantClass} ${sizeClass} ${weightClass} ${className}`}
94
      style={{ ...lineClampStyle, ...style }}
95
      data-testid={testID}
96
      {...ariaProps}
97
      {...props}
98
    >
99
      {children}
100
    </span>
101
  );
102
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc