npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@yahoo/uds-mobile

v2.3.3

Published

- [Overview](#overview) - [Installation](#installation) - [Quick Start](#quick-start) - [Components](#components) - [Icons](#icons) - [Fonts](#fonts) - [CLI](#cli) - [Testing](#testing) - [Contributing](#contributing) - [API Reference](#api-reference)

Downloads

2,036

Readme

@yahoo/uds-mobile

Table of Contents

Overview

@yahoo/uds-mobile brings UDS to React Native. It provides:

  • Pre-built Components: Avatar, Badge, Button, Checkbox, Chip, Icon, IconButton, Image, Input, Link, Radio, Switch, Text, and layout primitives (Box, VStack, HStack, Screen)
  • Theming: Full light/dark mode support with automatic system preference detection
  • Design Token Integration: Colors, typography, spacing, and motion configs synced from UDS tokens
  • Animations: Smooth, physics-based animations using Reanimated with motion parity to web
  • Icon Support: Icon font and SVG icon rendering with full UDS icon library

Key Dependencies

| Package | Purpose | Required | | ---------------------------- | -------------------------------------------- | -------- | | react-native-unistyles | Styling and theming engine | Yes | | react-native-reanimated | Animations | Yes | | react-native-svg | SVG icon rendering | Yes | | react-native-nitro-modules | Native module system (required by Unistyles) | Yes | | react-native-edge-to-edge | Edge-to-edge display (required by Unistyles) | Yes | | expo-font | Font loading (for bundled UDS fonts) | Optional |

Installation

# npm
npm install @yahoo/uds-mobile

Supported Versions

| Dependency | Supported Version | | ----------------------- | ----------------- | | Expo SDK | 55 | | React Native | ≥ 0.83.0 | | React | ≥ 19.0.0 | | react-native-unistyles | ≥ 3.0.0 | | react-native-reanimated | ≥ 4.0.0 |

[!NOTE] This package is tested against Expo SDK 55. While it may work with other versions, we cannot guarantee compatibility. If you encounter issues on a different Expo SDK version, please check for peer dependency conflicts.

Peer Dependencies

This package requires specific versions of React Native libraries as peer dependencies. Your project must have compatible versions installed for @yahoo/uds-mobile to work correctly.

Install the required peer dependencies:

# Required peer dependencies
expo install react-native-unistyles react-native-reanimated react-native-svg react-native-nitro-modules react-native-edge-to-edge

# Optional: For using bundled UDS fonts via expo-font plugin
expo install expo-font

Using expo install ensures you get versions compatible with your Expo SDK. If you encounter version conflicts, check the peerDependencies in the package's package.json for the exact version ranges required.

Expo Configuration

For Expo apps, add the expo-font plugin to your app.config.ts and import fonts from the mobile package:

import { fonts } from '@yahoo/uds-mobile/fonts';

export default {
  plugins: [
    ['expo-font', { fonts }],
    // ... other plugins
  ],
};

[!WARNING] Development Build Required: react-native-unistyles uses native modules and does not work with Expo Go. You must use a development build or prebuild your app. See the Unistyles setup guide for detailed instructions.

Quick Start

1. Configure Babel

Add the Unistyles and Reanimated babel plugins to your babel.config.js:

module.exports = function (api) {
  api.cache(true);
  return {
    presets: ['babel-preset-expo'],
    plugins: [
      [
        'react-native-unistyles/plugin',
        {
          root: 'src',
          autoProcessImports: ['@yahoo/uds-mobile'],
          autoProcessPaths: ['@yahoo/uds-mobile'],
        },
      ],
      ['react-native-reanimated/plugin'], // Must be last
    ],
  };
};

2. Generate Theme

Run the CLI to generate theme files from your UDS config:

# Using a config ID from UDS API
npx uds-mobile sync --id YOUR_CONFIG_ID

# Or using a local config file
npx uds-mobile sync ./uds.config.ts

This generates src/lib/unistyles.uds.ts containing your theme tokens.

3. Configure Unistyles

Create a configuration file that initializes Unistyles with your generated theme:

// src/lib/unistyles.ts
import { StyleSheet } from 'react-native-unistyles';
import { themes, breakpoints } from './unistyles.uds'; // Generated file

StyleSheet.configure({
  themes,
  breakpoints,
  settings: {
    adaptiveThemes: true, // Auto-switch based on system preference
  },
});

// Type augmentation for TypeScript support
declare module 'react-native-unistyles' {
  export interface UnistylesBreakpoints extends typeof breakpoints {}
  export interface UnistylesThemes extends typeof themes {}
}

Update your entry point to import Unistyles before any other imports:

// src/index.ts
import './lib/unistyles'; // Must be first!
// ... your app's existing entry code

[!NOTE] Why? Unistyles must be configured before any StyleSheet.create() calls execute. Since UDS Mobile components use Unistyles internally, the configuration must happen before any component imports.

4. Rebuild Your App

After adding native modules, rebuild your app:

npx expo prebuild --clean
npx expo run:ios  # or run:android

5. Use Components

import { VStack } from '@yahoo/uds-mobile/VStack';
import { Text } from '@yahoo/uds-mobile/Text';
import { Button } from '@yahoo/uds-mobile/Button';
import { Badge } from '@yahoo/uds-mobile/Badge';
import { Avatar } from '@yahoo/uds-mobile/Avatar';

function MyComponent() {
  return (
    <VStack spacing="4">
      <Text variant="title1">Welcome!</Text>
      <Avatar name="John Doe" size="lg" />
      <Badge variant="success">Active</Badge>
      <Button onPress={() => console.log('pressed')}>Get Started</Button>
    </VStack>
  );
}

Benefits of deep imports:

  • Smaller bundle size — Only loads components you actually use
  • Faster builds — Tree-shaking eliminates unused code
  • Optional dependencies — Future components with optional peer deps won't affect your app

6. Toggle Light/Dark Mode

Use useUnistyles to subscribe to theme changes and UnistylesRuntime to toggle:

import { Icon } from '@yahoo/uds-mobile/Icon';
import { Pressable } from '@yahoo/uds-mobile/Pressable';
import { UnistylesRuntime, useUnistyles } from 'react-native-unistyles';

function ThemeToggle() {
  const { rt } = useUnistyles();
  const isDark = rt.themeName === 'dark';

  const toggleTheme = () => {
    UnistylesRuntime.setTheme(isDark ? 'light' : 'dark');
  };

  return (
    <Pressable onPress={toggleTheme} hitSlop={20}>
      <Icon name={isDark ? 'CrescentMoon' : 'Sun'} size="sm" color="primary" variant="outline" />
    </Pressable>
  );
}

If you configured adaptiveThemes: true, the theme automatically follows the system preference. Calling UnistylesRuntime.setTheme() will override this until the app restarts.

[!WARNING] Performance: Using useUnistyles() causes component re-renders on theme changes, which negates Unistyles' performance benefits. For theme-aware styles, prefer StyleSheet.create with a dynamic function instead:

// ✅ Preferred: No re-renders, styles update automatically
const styles = StyleSheet.create((theme) => ({
  container: { backgroundColor: theme.colors.background.primary },
}));

// ⚠️ Avoid in hot paths: Causes re-renders
const { theme } = useUnistyles();

Reserve useUnistyles() for cases where you need runtime theme values (like the toggle above).

Debugging Re-renders

React Native DevTools includes a feature to highlight components when they re-render, helping you identify performance issues:

  1. Open React Native DevTools (press j in Metro terminal)
  2. Go to the React Components panel
  3. Click the View Settings (⚙︎) icon
  4. Enable "Highlight updates when components render"

Highlight re-renders in React Native DevTools

Components will flash with a colored border when they re-render. This makes it easy to spot unnecessary re-renders caused by useUnistyles() or other state changes.

[!TIP] Testing your setup: A good way to verify Unistyles is configured correctly is to toggle light/dark mode with highlighting enabled. If set up properly, only the theme toggle button should re-render — not the rest of your app. If you see the entire screen flash, you likely have useUnistyles() calls in components that should be using StyleSheet.create with dynamic functions instead.

See the React Native DevTools docs for more debugging features.

Extending the Theme

To add custom theme values alongside UDS tokens, merge your additions with the generated theme:

// src/lib/unistyles.ts
import { StyleSheet } from 'react-native-unistyles';
import { breakpoints, themes } from './unistyles.uds';

// Extend with your app-specific tokens
const extendedThemes = {
  light: {
    ...themes.light,
    // Add custom values
    custom: {
      headerHeight: 64,
      tabBarHeight: 80,
      cardShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
    },
  },
  dark: {
    ...themes.dark,
    custom: {
      headerHeight: 64,
      tabBarHeight: 80,
      cardShadow: '0 2px 8px rgba(0, 0, 0, 0.3)',
    },
  },
} as const;

StyleSheet.configure({
  themes: extendedThemes,
  breakpoints,
  settings: {
    adaptiveThemes: true,
  },
});

// Update type augmentation to include custom values
declare module 'react-native-unistyles' {
  export interface UnistylesBreakpoints extends typeof breakpoints {}
  export interface UnistylesThemes extends typeof extendedThemes {}
}

Now you can use both UDS tokens and your custom values in stylesheets:

const styles = StyleSheet.create((theme) => ({
  header: {
    height: theme.custom.headerHeight,
    backgroundColor: theme.colors.background.primary, // UDS token
  },
}));

Components

Available Components

| Component | Description | | ------------ | ----------------------------------------------- | | Avatar | User avatars with image, initials, or icon | | Badge | Status indicators and labels | | Box | Flexible container with layout props | | Button | Interactive button with variants and animations | | Checkbox | Selectable checkbox with label | | Chip | Compact elements for filters and selections | | HStack | Horizontal flex container | | Icon | Icon rendering (font or SVG) | | IconButton | Icon-only button | | IconSlot | Flexible icon slot for component composition | | Image | Image component with loading states | | Input | Text input with label and helper text | | Link | Inline text links with icons | | Pressable | Base pressable component | | Radio | Radio button with label | | Screen | Screen container with safe area handling | | Switch | Toggle switch with animations | | Text | Typography component with variants | | VStack | Vertical flex container |

Usage Examples

Button with Icons

<Button
  variant="primary"
  size="lg"
  startIcon="Add"
  onPress={handlePress}
>
  Create New
</Button>

<Button
  variant="secondary"
  loading
  disabled
>
  Saving...
</Button>

Form Controls

<VStack spacing="4">
  <Input
    label="Email"
    placeholder="Enter your email"
    helperText="We'll never share your email"
    startIcon="Mail"
  />

  <Checkbox checked={agreed} onValueChange={setAgreed} label="I agree to the terms" />

  <Switch isOn={notifications} onValueChange={setNotifications} label="Enable notifications" />
</VStack>

Avatar

<Avatar
  name="Jane Doe"
  src="https://example.com/avatar.jpg"
  size="lg"
/>

<Avatar
  name="John Smith"
  abbreviation="firstAndLast"  // Shows "JS"
/>

<Avatar showIcon /> // Shows person icon

Link with Icons

<Text variant="body1">
  Read our{' '}
  <Link textVariant="body1" variant="primary" endIcon="ExternalLink">
    Terms of Service
  </Link>
</Text>

Icons

Icon Rendering

Icons can be rendered using the font-based Icon component or as SVGs:

import { Icon } from '@yahoo/uds-mobile/Icon';

// Basic usage
<Icon name="Star" size="md" color="primary" />

// With variant
<Icon name="Heart" variant="fill" size="lg" />

// Custom color
<Icon name="Settings" dangerouslySetColor="#FF5733" />

Available Icons

The icon library includes the full UDS icon set. To see available icons:

import { iconNames, multicolorIconNames } from '@yahoo/uds-mobile/Icon';

console.log(iconNames); // All icon names
console.log(multicolorIconNames); // Multi-color icons

Animation Patterns

State-Driven Animations

Use useDerivedValue instead of useEffect + useSharedValue:

// ✅ Preferred pattern
const progress = useDerivedValue(() => withTiming(visible ? 1 : 0), [visible]);

// ❌ Avoid
const progress = useSharedValue(0);
useEffect(() => {
  progress.value = withTiming(visible ? 1 : 0);
}, [visible]);

Staggered Animations

const progress = useDerivedValue(
  () => withSpring(visible ? 1 : 0, BUTTON_SPRING_CONFIG),
  [visible],
);

const animatedStyle = useAnimatedStyle(() => ({
  width: interpolate(progress.value, [0, 1], [0, totalWidth]),
  opacity: interpolate(progress.value, [0.5, 1], [0, 1], 'clamp'), // Starts at 50%
  transform: [{ scale: interpolate(progress.value, [0.5, 1], [0.7, 1], 'clamp') }],
}));

Fonts

Font Handling

React Native doesn't support variable fonts, so all fonts are static (one file per weight). The package includes pre-converted fonts for:

  • Yahoo Product Sans
  • Inter
  • Roboto Mono
  • And other UDS-supported fonts

Font Loading

Fonts are automatically loaded via the expo-font plugin when configured in app.config.ts:

import { fonts } from '@yahoo/uds-mobile/fonts';

export default {
  plugins: [['expo-font', { fonts }]],
};

CLI

The uds-mobile CLI generates React Native theme files from UDS design tokens.

Commands

sync

Generates/updates theme files from UDS tokens.

npx uds-mobile sync [options]

Options:

| Option | Description | | ------------------- | -------------------------------------------------------- | | --id <config-id> | Fetch config by ID from UDS API | | [config] | Path to local config file (auto-detects uds.config.ts) | | --config <path> | Explicit path to config file | | --output <path> | Output file path (default: src/lib/unistyles.uds.ts) | | --prettier=<path> | Path to Prettier config (auto-detects if not specified) |

Examples:

# Fetch config from UDS API
npx uds-mobile sync --id abc123

# Use local config file
npx uds-mobile sync ./uds.config.ts

# Custom output location
npx uds-mobile sync --output ./src/theme.ts

Generated Output

The CLI generates a TypeScript file containing:

  • themes: Light and dark theme objects with all design tokens
  • breakpoints: Responsive breakpoint definitions
// AUTO-GENERATED FILE. DO NOT EDIT.
export const themes = {
  light: {
    /* ... */
  },
  dark: {
    /* ... */
  },
};

export const breakpoints = {
  /* ... */
};

Testing

Jest Setup

UDS Mobile ships Jest mocks for native dependencies that don't work in Jest/JSDOM, allowing real UDS components to be tested without native module errors. This approach ensures your tests validate actual component behavior.

Quick Start

Add the setup file to your Jest config:

// jest.config.js
module.exports = {
  preset: 'react-native',
  setupFilesAfterEnv: ['@yahoo/uds-mobile/jest'],
  transformIgnorePatterns: [
    'node_modules/(?!(@yahoo/uds-mobile|@yahoo/uds-icons|react-native|@react-native)/)',
  ],
};

Or import manually in your setup file:

// jest.setup.js
import '@yahoo/uds-mobile/jest';

What Gets Mocked

The setup automatically mocks these native dependencies:

| Package | What's Mocked | | ------------------------- | ----------------------------------------------------------------------------------- | | react-native-unistyles | useUnistyles(), StyleSheet.create(), UnistylesRuntime | | react-native-reanimated | Animated components, hooks (useSharedValue, useAnimatedStyle), timing functions | | react-native-svg | SvgXml, SVG shape components | | @yahoo/uds-icons | glyphMap, svgMap, ICON_SIZE_MAP |

Example Test

import { render, fireEvent } from '@testing-library/react-native';
import { Button } from '@yahoo/uds-mobile/Button';
import { Text } from '@yahoo/uds-mobile/Text';
import { VStack } from '@yahoo/uds-mobile/VStack';

test('renders button with text and handles press', () => {
  const onPress = jest.fn();

  const { getByRole, getByText } = render(
    <VStack>
      <Button variant="primary" onPress={onPress}>
        Save
      </Button>
    </VStack>,
  );

  expect(getByText('Save')).toBeTruthy();

  fireEvent.press(getByRole('button'));
  expect(onPress).toHaveBeenCalled();
});

Benefits

  • Real component testing: Tests validate actual component behavior, not stubs
  • No native module errors: Required native dependencies are properly mocked
  • Zero configuration: Just add the setup file and transformIgnorePatterns
  • Catches regressions: Tests break when component behavior changes

Manual Mock Access

If you need to customize mocks, individual modules are exported:

import { mocks } from '@yahoo/uds-mobile/jest';

// Override a specific mock
jest.mock('react-native-unistyles', () => ({
  ...mocks.unistyles,
  useUnistyles: () => ({
    theme: {
      /* custom theme */
    },
    rt: { themeName: 'dark' },
  }),
}));

Contributing

See CONTRIBUTING.md for the development workflow, architecture details, and internal documentation.

API Reference

Component Props

All components export their props types:

import type {
  ButtonProps,
  TextProps,
  AvatarProps,
  BadgeProps,
  CheckboxProps,
  ChipProps,
  IconProps,
  IconButtonProps,
  ImageProps,
  InputProps,
  LinkProps,
  RadioProps,
  SwitchProps,
  BoxProps,
  VStackProps,
  HStackProps,
  ScreenProps,
  PressableProps,
  IconSlotProps,
  IconSlotType,
  IconName,
} from '@yahoo/uds-mobile';

Exports

// Components (one import per component)
import { Avatar } from '@yahoo/uds-mobile/Avatar';
import { Badge } from '@yahoo/uds-mobile/Badge';
import { Box } from '@yahoo/uds-mobile/Box';
import { Button } from '@yahoo/uds-mobile/Button';
import { Checkbox } from '@yahoo/uds-mobile/Checkbox';
import { Chip } from '@yahoo/uds-mobile/Chip';
import { HStack } from '@yahoo/uds-mobile/HStack';
import { Icon, iconNames, multicolorIconNames } from '@yahoo/uds-mobile/Icon';
import { IconButton } from '@yahoo/uds-mobile/IconButton';
import { IconSlot } from '@yahoo/uds-mobile/IconSlot';
import { Image } from '@yahoo/uds-mobile/Image';
import { Input } from '@yahoo/uds-mobile/Input';
import { Link } from '@yahoo/uds-mobile/Link';
import { Pressable } from '@yahoo/uds-mobile/Pressable';
import { Radio } from '@yahoo/uds-mobile/Radio';
import { Screen } from '@yahoo/uds-mobile/Screen';
import { Switch } from '@yahoo/uds-mobile/Switch';
import { Text } from '@yahoo/uds-mobile/Text';
import { VStack } from '@yahoo/uds-mobile/VStack';

// Sub-exports
import { motion, BUTTON_SPRING_CONFIG, SCALE_EFFECTS } from '@yahoo/uds-mobile/motion';
import { fonts, fontAliasToPostscript } from '@yahoo/uds-mobile/fonts';