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

react-native-pixelflow

v0.6.0

Published

Professional React Native responsive design system — hybrid scaling, styled(), RTL, a11y prefs, Figma tokens, adaptive shells, and navigation bridges.

Readme

react-native-PixelFlow

Responsive React Native UI that stays simple.

Write normal StyleSheet numbers (or design tokens). PixelFlow scales them for phones, tablets, and foldables — without NativeWind or CSS-in-JS.


Start in 3 steps

1. Install

npm install react-native-pixelflow react-native-safe-area-context
# Expo:
npx expo install react-native-safe-area-context

2. Wrap your app (order matters)

import { SafeAreaProvider } from 'react-native-safe-area-context';
import { PixelFlowProvider, configure } from 'react-native-pixelflow';

// Match your Figma frame once (optional but recommended)
configure({ figma: 'iPhone 14' });

export default function App() {
  return (
    <SafeAreaProvider>
      <PixelFlowProvider followSystem>
        {/* your screens */}
      </PixelFlowProvider>
    </SafeAreaProvider>
  );
}

3. Build a screen

Option A — easiest (tokens + components):

import { Container, Box, FText, Button, Spacer } from 'react-native-pixelflow';

export function HomeScreen() {
  return (
    <Container>
      <Box p="md" bg="surface" radius="lg">
        <FText variant="h2">Welcome</FText>
        <FText color="fg.muted">Looks good on every phone size.</FText>
        <Spacer size={16} />
        <Button intent="primary" onPress={() => {}}>
          Get started
        </Button>
      </Box>
    </Container>
  );
}

Option B — paste Figma numbers into a StyleSheet:

import { usePixelSheet, FText } from 'react-native-pixelflow';

export function Card() {
  const styles = usePixelSheet(() => ({
    box: { padding: 16, borderRadius: 12 },
    title: { fontSize: 24, marginBottom: 8 },
  }));

  return (
    <>
      <FText style={styles.title}>Title</FText>
      {/* use styles.box on a View */}
    </>
  );
}

That’s enough for most apps. Everything below is optional.


What should I use?

| I want to… | Use this | |---|---| | Build a screen quickly | Container, Box, FText, Button, Card, Spacer | | Stack children with gap | Stack / HStack / VStack / AdaptiveStack | | Form / keyboard screen | KeyboardScreen, FormField | | Paste Figma px into styles | usePixelSheet(() => ({ … })) | | Match my Figma frame | configure({ figma: 'iPhone 14' }) | | Support iPad / large screens | Grid, SplitView, ContentWidth, useWindowClass, useListLayout | | React to parent width | useContainerSize / ContainerQuery | | Hide/show by breakpoint | Show / Hide | | Fluid type that clamps | fluid(14, 16, 22) | | Readable article width | useReadableWidth / maxCh | | Tabs vs drawer nav | useAdaptiveNav | | Fold / split-screen | useFoldState / useMultiWindow | | Common screen patterns | useRecipes() | | Tokenized styled components | styled(View, { p: 'md', bg: 'surface' }) | | App shells (phone/tablet/fold) | Shell.Phone / Shell.Tablet / Shell.Tabletop | | React Navigation colors | createNavigationTheme({ theme }) | | Figma Variables → theme | npx pixelflow tokens ./vars.json | | See live scale values in the app | {__DEV__ && <PixelFlowDebug />} | | Coming from size-matters | npx pixelflow migrate ./src or scale / ms aliases |


Everyday building blocks

Box & text (design tokens)

<Box p="md" px={{ compact: 'sm', medium: 'lg' }} bg="bg.subtle" radius="lg">
  <FText variant="h2" color="primary">Title</FText>
  <FText color="fg.muted">Subtitle</FText>
</Box>

Spacing: xs sm md lg xl xxl
Radius: none sm md lg xl full
Colors: primary, surface, text, … or semantic bg.subtle, fg.muted, border.default

You can still pass raw numbers: <Box p={16} />.

PixelSheet (auto-scale by property)

| Style key | Scales as | |---|---| | fontSize | font | | padding / margin / gap | spacing | | borderRadius | radius | | % / flex / opacity | unchanged |

Prefer usePixelSheet inside components so styles update on rotation.

Avoid module-level StyleSheet.create({ padding: rp(16) }) — that freezes the number at import time.

Button

<Button intent="primary" size="lg" fullWidth onPress={onSave}>
  Save
</Button>

intent: primary | secondary | danger | ghost
size: sm | md | lg

Stack, Card, AspectBox

import {
  AdaptiveStack,
  AspectBox,
  Card,
  FText,
  HStack,
  Stack,
  absoluteFill,
} from 'react-native-pixelflow';

<Stack gap="md">
  <Card p="md" elevation="md">
    <FText variant="h3">Profile</FText>
  </Card>
  <AdaptiveStack gap="sm" breakpoint="medium">
    <AspectBox ratio="16:9">{/* Image with style={absoluteFill} */}</AspectBox>
    <FText color="fg.muted">Caption</FText>
  </AdaptiveStack>
  <HStack gap="sm" justify="space-between">{/* … */}</HStack>
</Stack>

Keyboard + form fields

import { FormField, KeyboardScreen, FText } from 'react-native-pixelflow';
import { TextInput } from 'react-native';

<KeyboardScreen>
  <FormField label="Email" required helper="Work email" chrome error={errors.email}>
    <TextInput value={email} onChangeText={setEmail} />
  </FormField>
</KeyboardScreen>

Shadows, press styles, clamp

import { clamp, createPressStyle, rf, shadow } from 'react-native-pixelflow';

const card = [styles.box, shadow('md')];
const fontSize = clamp(rf(18), 14, 22);

<Pressable
  disabled={busy}
  style={createPressStyle(
    {
      base: { padding: 12, borderRadius: 8 },
      pressed: { opacity: 0.85 },
      disabled: { opacity: 0.4 },
    },
    busy,
  )}
/>

Recipes, insets, lists

import {
  useInsetStyle,
  useListLayout,
  useRecipes,
} from 'react-native-pixelflow';

const r = useRecipes();
const pad = useInsetStyle({ top: true, bottom: true, extra: 'md' });
const list = useListLayout({ minItemWidth: 160, gap: 12 });

<View style={[r.screenPadded, pad]}>
  <FlatList {...list.flatListProps} data={data} renderItem={…} />
</View>

Container queries, Show/Hide, fluid type

import {
  ContainerQuery,
  Hide,
  OrientationGate,
  Show,
  fluid,
  match,
  maxCh,
  rs,
  useAdaptiveNav,
  useImageSize,
  useMultiWindow,
  useReadableWidth,
} from 'react-native-pixelflow';

const columns = rs.match({ compact: 1, medium: 2, expanded: 3 });
const titleSize = fluid(18, 22, 28);
const { maxWidth } = useReadableWidth({ chars: 65 });
const img = useImageSize({ base: 120, max: 200 });
const nav = useAdaptiveNav();
const { forceCompact } = useMultiWindow();

<ContainerQuery>
  {(box) => (box.meets('medium') ? <RowLayout /> : <ColumnLayout />)}
</ContainerQuery>

<Show above="medium"><TabletChrome /></Show>
<Hide below="medium"><PhoneOnlyHint /></Hide>

<OrientationGate allow="portrait">
  <CheckoutForm />
</OrientationGate>

<View style={{ maxWidth: maxCh(65) }} />

Wire native fold posture when you have a hinge module:

import { setFoldState } from 'react-native-pixelflow';
setFoldState({ isFolded: true, posture: 'tabletop' });

styled(), shells, navigation, Figma tokens

import {
  Shell,
  createNavigationTheme,
  styled,
  useA11yPrefs,
  useEstimatedItemSize,
  useOverlayInsets,
  usePointer,
  useScaleContext,
  rpWith,
} from 'react-native-pixelflow';

const Panel = styled.View({ p: 'md', bg: 'surface', radius: 'lg', ps: 'md' });

<Shell.Tablet master={<List />} detail={<Detail />} />
<Shell.Tabletop top={<Player />} bottom={<Controls />} />

// NavigationContainer theme={createNavigationTheme({ theme })}
// npx pixelflow tokens ./figma-variables.json -o src/theme/figmaTheme.ts

const { estimatedItemSize } = useEstimatedItemSize({ base: 72 });
const overlay = useOverlayInsets({ extra: 8 });
const { canHover } = usePointer();
const { a11yTheme } = useA11yPrefs();
const ctx = useScaleContext(); // pass to Reanimated: rpWith(ctx, 16)

SSR / Expo Router web (avoid first-paint flash):

<PixelFlowProvider ssrWidth={390} ssrHeight={844} followSystem>
  <App />
</PixelFlowProvider>

Layout regression tests:

import { assertLayout, resetPixelFlow } from 'react-native-pixelflow/testing';

assertLayout({
  fixture: 'phone',
  expect: { widthClass: 'compact', rp16: 16 },
});

Tablets & larger screens (when you need them)

Scaling alone makes iPad UI “bigger phone.” For real tablet UX, change layout:

import {
  Grid,
  SplitView,
  ContentWidth,
  useWindowClass,
} from 'react-native-pixelflow';

const { widthClass, columns, meets } = useWindowClass();
// widthClass: compact → medium → expanded → large → extraLarge

<ContentWidth>
  <Grid minItemWidth={160} gap={12}>
    {items.map((item) => (
      <Card key={item.id} {...item} />
    ))}
  </Grid>
</ContentWidth>

<SplitView
  breakpoint="medium"
  master={<List />}
  detail={<Detail />}
/>

Try it fast


Coming from react-native-size-matters?

npx pixelflow migrate ./src

Or keep familiar names:

import { scale, moderateScale, s, ms } from 'react-native-pixelflow';

Advanced (optional)

Only reach for these when the basics aren’t enough.

configure({
  figma: 'iPhone 14',           // or { width: 390, height: 844 }
  density: 'comfortable',       // compact | comfortable | spacious
  maxFontSizeMultiplier: 1.3,
  applyAccessibilityFontScale: true,
});

listFigmaPresets() shows all named frames (iPhone 14, Pixel 7, iPad Pro 11, …).

| Function | Use for | |---|---| | rp / rm | padding / margin | | rf / rl / rls | font / line height / letter spacing | | rr / ri | radius / icon | | rw / rh | % of screen width / height | | rsw / rsh | % of safe width / height | | rs({ phone, tablet }) | per-device value | | design(16) | same as rp(16) from Figma |

<Box
  p={{ compact: 'sm', medium: 'md', expanded: 'lg' }}
  flexDirection={['column', 'row']}  // compact, medium, expanded
/>
import { createVariants, useMedia, useMotion, useA11yLayout } from 'react-native-pixelflow';

const chip = createVariants({
  base: { padding: 8, borderRadius: 8 },
  variants: {
    tone: { neutral: { opacity: 1 }, danger: { opacity: 0.9 } },
  },
});

const media = useMedia();
if (media.lg || media.matches({ minWidth: 840 })) { /* wide layout */ }

const motion = useMotion(); // durations become 0 if Reduce Motion is on
const { preferStack } = useA11yLayout();
import { customTheme, PixelFlowProvider } from 'react-native-pixelflow';

const brand = customTheme({
  base: 'light',
  colors: { primary: '#FF6B6B' },
});

<PixelFlowProvider theme={brand} density="comfortable">
  <App />
</PixelFlowProvider>

PixelFlow maps family names → strings (e.g. fonts.inter.bold).
It does not bundle font files.

npx expo install expo-font @expo-google-fonts/inter
import { useFonts, Inter_400Regular, Inter_700Bold } from '@expo-google-fonts/inter';
const [loaded] = useFonts({ Inter_400Regular, Inter_700Bold });

See src/fonts/fontRegistry.ts for the full family list.

import { mockDimensions, resetPixelFlow } from 'react-native-pixelflow/testing';

beforeEach(() => {
  resetPixelFlow();
  mockDimensions({ width: 390, height: 844 });
});
// ESLint — warn on raw padding/fontSize outside PixelSheet
plugins: { pixelflow: require('react-native-pixelflow/eslint-plugin') },
rules: { 'pixelflow/no-raw-spacing': 'warn' }

Most libs only do width / 375 scaling. PixelFlow blends width + height, damps tablets/foldables, and can change layout (grid / split) — not only enlarge padding.

Works with RN 0.70+, Hermes, Fabric, Expo. Pure JS/TS — no native modules.


Compatibility

  • React Native 0.70+
  • Expo (managed or bare)
  • TypeScript (strict, full typings)

License

MIT — see LICENSE

Changelog

CHANGELOG.md