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

@vincent-huy-uit/react-native-responsive-ui

v1.1.7

Published

A responsive design library for React Native / Expo applications. Automatically scale design values across different screen sizes.

Readme

@vincent-huy-uit/react-native-responsive-ui

A zero-config responsive design library for React Native / Expo.
Build UIs that look perfect on phones, tablets, and iPads with minimal code.

📚 Documentation

View Full Documentation →


🎯 Problems We Solve

| ❌ Problem | ✅ Solution | |-----------|------------| | Wrapping every value with scaling functions is tedious | createScaledStyles() - auto-scales entire StyleSheet | | Manual size calculations for different screens | s(16) - scales any value automatically | | Duplicating code for breakpoints | responsive() - pick values per device | | Different layouts needed for phone vs tablet | ResponsiveSwitch - render different components | | Inconsistent spacing/fonts across app | Design tokens - space.md, font.body | | iPads scale too large with width-only scaling | Aspect-aware scaling - works on all devices by default |


📦 Installation

npm install @vincent-huy-uit/react-native-responsive-ui

🚀 The 3 Main Features

1️⃣ createScaledStyles() - Auto-Scale Entire StyleSheet ⭐

The easiest way! Drop-in replacement for StyleSheet.create() - scales everything automatically.

import { createScaledStyles } from '@vincent-huy-uit/react-native-responsive-ui';

// Just write normal values - everything scales automatically!
const styles = createScaledStyles({
  container: {
    padding: 16,           // ✅ Auto-scaled
    borderRadius: 12,      // ✅ Auto-scaled
    flex: 1,               // ✅ NOT scaled (it's a ratio)
    opacity: 0.9,          // ✅ NOT scaled (0-1 value)
  },
  title: {
    fontSize: 24,          // ✅ Auto-scaled
    fontWeight: '600',     // ✅ Preserved as-is
  },
  shadow: {
    shadowOffset: { width: 2, height: 4 },  // ✅ Nested values scaled too!
    shadowRadius: 8,       // ✅ Auto-scaled
    shadowOpacity: 0.2,    // ✅ NOT scaled
  },
});

Smart exclusions - these properties are NOT scaled:

  • flex, flexGrow, flexShrink (ratios)
  • opacity, shadowOpacity (0-1 values)
  • zIndex, elevation (indices)
  • aspectRatio, scale, fontWeight

1️⃣ s() - Scale Individual Values

Use when you need to scale a single value (e.g., inline styles, dynamic values)

import { s } from '@vincent-huy-uit/react-native-responsive-ui';

// For inline styles or dynamic values
<View style={{ padding: s(16), marginTop: s(isLarge ? 32 : 16) }} />

🎨 Design Tokens (Alternative to s())

Pre-defined scaled values for consistency:

import { space, font, radius } from '@vincent-huy-uit/react-native-responsive-ui';

const styles = StyleSheet.create({
  card: {
    padding: space.md,        // 16pt scaled
    fontSize: font.body,      // 16pt scaled
    borderRadius: radius.md,  // 8pt scaled
  },
});

| space | font | radius | |---------|--------|----------| | xs = 4 | caption = 12 | sm = 4 | | sm = 8 | body = 16 | md = 8 | | md = 16 | subtitle = 18 | lg = 16 | | lg = 24 | title = 24 | full = 9999 | | xl = 32 | headline = 32 | | | xxl = 48 | | |

Custom tokens? Override via Provider:

<ResponsiveProvider
  tokens={{
    space: { sm: 4, md: 12, lg: 20 },
    font: { body: 14, title: 22 },
  }}
>
  <App />
</ResponsiveProvider>

2️⃣ responsive() - Different Values Per Device

Use when you need different values for mobile vs tablet (e.g., grid columns, show/hide elements)

import { responsive, useDeviceType } from '@vincent-huy-uit/react-native-responsive-ui';

function ProductGrid() {
  // Pick different values per device
  const columns = responsive({ mobile: 2, tablet: 3, desktop: 4 });
  const showSidebar = responsive({ mobile: false, tablet: true });
  
  // Or get device type directly
  const device = useDeviceType(); // "mobile" | "tablet" | "desktop"
  
  return (
    <View style={{ flexDirection: device === 'mobile' ? 'column' : 'row' }}>
      {showSidebar && <Sidebar />}
      <Grid columns={columns} />
    </View>
  );
}

3️⃣ ResponsiveSwitch - Different Layouts Per Device

Use when mobile and tablet need completely different UIs (e.g., master-detail on tablet)

import { ResponsiveSwitch } from '@vincent-huy-uit/react-native-responsive-ui';

function InboxScreen() {
  return (
    <ResponsiveSwitch
      mobile={<MobileInbox />}      // Simple list
      tablet={<TabletInbox />}      // Master-detail split
    />
  );
}

// Mobile: Navigate to detail screen
const MobileInbox = () => (
  <EmailList onPress={(id) => navigation.navigate('EmailDetail', { id })} />
);

// Tablet: Side-by-side layout
const TabletInbox = () => (
  <View style={{ flexDirection: 'row' }}>
    <EmailList style={{ width: '35%' }} onPress={setSelected} />
    <EmailDetail style={{ width: '65%' }} email={selected} />
  </View>
);

📋 Quick Reference

Most Used (Learn These First!)

| Function | What It Does | Example | |----------|--------------|---------| | createScaledStyles() ⭐ | Auto-scale entire StyleSheet | Replace StyleSheet.create() | | s(value) | Scale a single value | padding: s(16) | | space.md | Scaled spacing token | gap: space.lg | | font.body | Scaled font token | fontSize: font.title | | responsive() | Different values per device | responsive({ mobile: 2, tablet: 4 }) | | useDeviceType() | Get current device type | "mobile" | "tablet" | "desktop" | | ResponsiveSwitch | Different components per device | <ResponsiveSwitch mobile={...} tablet={...} /> |

All Scaling Functions

| Function | Description | |----------|-------------| | s(value) | Universal scaling (default: aspect-aware) | | sv(value) | Scale based on height | | sm(value) | Moderate scaling (min of width/height) | | sa(value) | Aspect-aware scaling |

All Hooks

| Hook | Returns | |------|---------| | useDeviceType() | "mobile" | "tablet" | "desktop" | | useOrientation() | "portrait" | "landscape" | | useDimensions() | { width, height } | | useScaleFactor() | Current scale factor | | useScaledValue(n) | Scaled value (reactive) |

Utilities

| Function | Description | |----------|-------------| | getDeviceType() | Get device type (non-reactive) | | getOrientation() | Get orientation (non-reactive) | | createScaledStyles() | Auto-scale all numbers in StyleSheet |


💡 Best Practices

✅ Do This

// 1. Use createScaledStyles() for StyleSheets (easiest!)
const styles = createScaledStyles({
  container: { padding: 16, fontSize: 14 }  // Auto-scaled!
});

// 2. Use s() for inline/dynamic styles
<View style={{ padding: s(16) }} />

// 3. Use tokens for consistency
padding: space.md
fontSize: font.body

// 4. Use responsive() for conditional values
const columns = responsive({ mobile: 2, tablet: 4 });

// 5. Use ResponsiveSwitch only when layouts are completely different
<ResponsiveSwitch mobile={<List />} tablet={<Grid />} />

❌ Avoid This

// Don't hardcode sizes in StyleSheet.create()
const styles = StyleSheet.create({
  container: { padding: 16 }  // ❌ Won't scale!
});

// Don't create separate files for minor differences
// Instead, use responsive() in the same component

⚙️ Configuration (Optional)

Zero configuration needed! But you can customize:

Using Provider (Recommended)

import { ResponsiveProvider } from '@vincent-huy-uit/react-native-responsive-ui';

<ResponsiveProvider
  baseWidth={375}
  baseHeight={812}
  scalingStrategy="aspectAware"
  maxScaleFactor={2}
  breakpoints={{ tablet: 768, desktop: 1024 }}
  tokens={{
    space: { xs: 2, sm: 4, md: 12, lg: 20, xl: 28, xxl: 40 },
    font: { caption: 10, body: 14, subtitle: 16, title: 22, headline: 30 },
    radius: { sm: 2, md: 6, lg: 12 },
  }}
>
  <App />
</ResponsiveProvider>

Using configure() (Imperative)

import { configure, configureTokens } from '@vincent-huy-uit/react-native-responsive-ui';

// Configure scaling
configure({
  baseWidth: 375,
  baseHeight: 812,
  scalingStrategy: 'aspectAware',
  maxScaleFactor: 2,
  breakpoints: { tablet: 768, desktop: 1024 },
});

// Configure tokens (optional)
configureTokens({
  space: { md: 12, lg: 20 },
  font: { body: 14 },
});

Scaling Strategies

| Strategy | Best For | |----------|----------| | "aspectAware" | All devices (default) - auto-adjusts for iPads | | "width" | Phone-only apps | | "moderate" | iPad-first apps |


🔤 TypeScript

import type {
  DeviceType,        // "mobile" | "tablet" | "desktop"
  Orientation,       // "portrait" | "landscape"
  ScalingStrategy,   // "width" | "height" | "moderate" | "aspectAware"
  ResponsiveValues,  // { mobile: T; tablet?: T; desktop?: T }
} from '@vincent-huy-uit/react-native-responsive-ui';

📱 Real-World Examples

Dashboard with Stats

import { createScaledStyles, responsive } from '@vincent-huy-uit/react-native-responsive-ui';

function Dashboard() {
  const columns = responsive({ mobile: 2, tablet: 4 });
  
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Dashboard</Text>
      
      <View style={styles.statsGrid}>
        {stats.map(stat => (
          <View key={stat.id} style={[styles.statCard, { width: `${100/columns}%` }]}>
            <Text style={styles.statValue}>{stat.value}</Text>
            <Text style={styles.statLabel}>{stat.label}</Text>
          </View>
        ))}
      </View>
    </View>
  );
}

// All numeric values auto-scaled!
const styles = createScaledStyles({
  container: { padding: 24 },
  title: { fontSize: 32, fontWeight: 'bold' },
  statsGrid: { flexDirection: 'row', flexWrap: 'wrap', gap: 12 },
  statCard: { padding: 16, backgroundColor: '#1a1a2e', borderRadius: 12 },
  statValue: { fontSize: 24, fontWeight: 'bold' },
  statLabel: { fontSize: 12, color: '#888' },
});

Product Marketplace

import { createScaledStyles, responsive } from '@vincent-huy-uit/react-native-responsive-ui';

function Marketplace() {
  const columns = responsive({ mobile: 2, tablet: 3, desktop: 4 });
  
  return (
    <FlatList
      data={products}
      numColumns={columns}
      key={columns}
      contentContainerStyle={styles.list}
      renderItem={({ item }) => (
        <View style={[styles.card, { width: `${100/columns - 2}%` }]}>
          <Image source={item.image} style={styles.image} />
          <Text style={styles.name}>{item.name}</Text>
          <Text style={styles.price}>${item.price}</Text>
        </View>
      )}
    />
  );
}

// Clean code - no s() wrapping needed!
const styles = createScaledStyles({
  list: { padding: 16 },
  card: { margin: 4, backgroundColor: '#222', borderRadius: 16 },
  image: { width: '100%', height: 150, borderRadius: 16 },
  name: { fontSize: 16, padding: 8 },
  price: { fontSize: 18, color: '#4CAF50', paddingHorizontal: 8 },
});

Master-Detail Layout (Inbox)

import { createScaledStyles, ResponsiveSwitch } from '@vincent-huy-uit/react-native-responsive-ui';

function InboxScreen() {
  return (
    <ResponsiveSwitch
      mobile={<MobileInbox />}
      tablet={<TabletInbox />}
    />
  );
}

// Tablet: Side-by-side master-detail
function TabletInbox() {
  const [selected, setSelected] = useState(emails[0]);
  
  return (
    <View style={styles.splitView}>
      <View style={styles.masterPanel}>
        <EmailList emails={emails} onSelect={setSelected} selected={selected} />
      </View>
      <View style={styles.detailPanel}>
        <EmailDetail email={selected} />
      </View>
    </View>
  );
}

const styles = createScaledStyles({
  splitView: { flex: 1, flexDirection: 'row' },
  masterPanel: { width: '35%', borderRightWidth: 1, borderColor: '#333' },
  detailPanel: { width: '65%', padding: 24 },
});

📄 License

MIT