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

@marktiderman/genesis-ui-native

v3.3.0

Published

Genesis React Native components (NativeWind v4-5). Part of the Genesis framework.

Readme

@marktiderman/genesis-ui-native

Genesis React Native components and screen layouts for Expo apps (NativeWind). Every component is listed in the component reference.

Optional native modules

Some components draw better with a native module your app may or may not have. This package never require()s one itself: you import what you installed and pass it once, near the root, and every component falls back to plain React Native for whatever you leave out. (GenesisNativeApp from @marktiderman/genesis-native takes the same object as its modules prop.)

import DateTimePicker from "@expo/ui/community/datetime-picker";
import { FlashList } from "@shopify/flash-list";
import * as GlassEffect from "expo-glass-effect";
import { Image } from "expo-image";
import { SymbolView } from "expo-symbols";
import * as Reanimated from "react-native-reanimated";
import { GenesisModulesProvider } from "@marktiderman/genesis-ui-native";
import { lucideIcons } from "@marktiderman/genesis-ui-native/icons/lucide";

<GenesisModulesProvider
  modules={{ list: FlashList, image: Image, reanimated: Reanimated, glass: GlassEffect,
             symbol: SymbolView, icons: lucideIcons, datePicker: DateTimePicker }}
>
  {app}
</GenesisModulesProvider>;

| modules. | Package (npx expo install …) | Used by | Without it | | --- | --- | --- | --- | | list | @shopify/flash-list v2 (New Architecture only) | NativeResourcePage, NotificationsPage (sections become one list with sticky headers) | FlatList / SectionList | | image | expo-image | NativeAvatar, NativeImage: memory and disk cache, placeholder (blurhash / thumbhash), recyclingKey (the URL by default) so recycled rows never flash the last picture, no cross-fade under Reduce Motion | React Native Image | | reanimated | react-native-reanimated 4 (import * as) | NativeToastProvider, NativeDrawer, NativeSkeleton; all of them stay still under Reduce Motion | React Native Animated | | glass | expo-glass-effect (import * as) | NativeGlassSurface: default toasts, the update banner, popovers and dropdown menus, as iOS 26 Liquid Glass | the solid surface | | symbol | expo-symbols | NativeIcon on iOS (SF Symbols), and the drill-in chevron of NativeListItem | icons | | icons | lucide-react-native 0.475+, through lucideIcons from /icons/lucide | NativeIcon on Android and web, and as the SF Symbol's fallback | an empty space of the icon's size, and a development warning | | datePicker | @expo/ui (@expo/ui/community/datetime-picker) | NativeDatePicker, NativeTimePicker: SwiftUI on iOS, a Jetpack Compose dialog on Android | @react-native-community/datetimepicker, else a read-only label |

Glass is drawn only on iOS when both isLiquidGlassAvailable() (built with the iOS 26 SDK, running iOS 26) and isGlassEffectAPIAvailable() (the API exists at run time) are true, and Reduce Transparency is off. Success and destructive toasts keep their solid color, which carries their meaning.

NativeIcon takes a semantic name ("settings", "bell", "trash": NATIVE_ICON_NAMES), never a library's own. It is decorative (hidden from screen readers) unless you give it a label.

Gesture handler. No component here needs react-native-gesture-handler except NativeSheet when it draws with @gorhom/bottom-sheet. If you use that, install react-native-gesture-handler as a direct dependency of your app (npx expo install react-native-gesture-handler) and wrap the root in its GestureHandlerRootView; don't rely on another package bringing it in. The drawer's swipe uses React Native's PanResponder.

Loading screens: NativeLoadingState and ScreenContainer loading

For a screen that is waiting (a redirect while the session loads, a first fetch), don't hand-roll <View><ActivityIndicator /></View>. NativeLoadingState is a centred spinner in the theme tint, read by screen readers as one "Loading" progress bar (or your label, which also shows under the spinner). By default it fills the screen on the background, inside the safe area; fullScreen={false} makes it a centred block for a screen body, a section or a list footer.

import { NativeLoadingState, ScreenContainer } from "@marktiderman/genesis-ui-native";

if (!session) return <NativeLoadingState label="Signing you in" />;

<ScreenContainer scroll loading={isLoading} loadingLabel="Loading your plan">{body}</ScreenContainer>;

ScreenContainer's loading puts the inline form in place of the body, keeping its safe area, background and status bar. InboxPage uses it for its first load and "Loading more" footer. Use NativeSkeleton for a placeholder shaped like the content, and NativeProgress for known progress. loading is for a screen's first load: the body is unmounted while it's on, so don't use it to cover a form the person is filling in (its state would be lost); show NativeLoadingState fullScreen={false} or a button's busy state instead. loadingLabel is shown and read by VoiceOver, so pass translated text; without it the screen reader hears accessibilityLabel ("Loading" by default) and nothing is shown.

genesis doctor (native pack) flags a raw ActivityIndicator from react-native and points here. A route whose only screen is a full-screen NativeLoadingState (a redirect or loading bridge, optionally with Stack.Screen options) counts as a screen for native-screen-layout; one that also renders other content, imports it, or uses fullScreen={false} still needs a layout.

Keyboard toolbar

KeyboardScrollProvider (from /layouts) takes an optional toolbar: react-native-keyboard-controller's KeyboardToolbar. With it, AuthScreen and SettingsSubPage show the previous / next / done bar above the keyboard and keep the focused field clear of it. It needs the scroll view (component) and the library's KeyboardProvider; GenesisNativeApp takes it as keyboardToolbar.

Sign-in: AuthScreen and Sign in with Apple

AuthScreen (from @marktiderman/genesis-ui-native/layouts) is a whole sign-in screen: branding, provider buttons, the email form and a footer, each a slot. In development on iOS it warns when it offers a third-party provider without Sign in with Apple, which App Store Review Guideline 4.8 requires.

appleProvider adds Apple in one line, drawn with Apple's own AppleAuthenticationButton (Apple requires its button; a look-alike is rejected). Pass expo-apple-authentication in; this package doesn't import it.

import * as AppleAuthentication from "expo-apple-authentication";
import { AuthScreen, appleProvider } from "@marktiderman/genesis-ui-native/layouts";

<AuthScreen
  branding={{ headline: "Welcome back" }}
  providers={[
    appleProvider({ apple: AppleAuthentication, onPress: onApple }),
    { id: "google", label: "Continue with Google", onPress: onGoogle },
  ]}
  form={{ onSubmit: signInWithEmail }}
/>;
  • appleProvider({ apple, onPress, type?, appearance?, cornerRadius?, height?, label? }): a provider with id "apple", or null off iOS or when apple is undefined. AuthScreen skips null entries, so the same list works on every platform. type is Apple's wording ("continue" by default, "sign-in", "sign-up"); appearance "auto" is black in light mode and white in dark. label follows type and is used only by the dev warning and a custom social slot: Apple's button draws and announces its own localized text. height defaults to 44, the recommended touch target (the HIG minimum for this button is 30pt).
  • AppleSignInButton: the same button on its own, for a screen you compose yourself. While an onPress promise is pending it ignores further taps (so a double tap can't open a second sheet) and reports itself busy and disabled to accessibility; disabled does the same and dims it.
  • googleProvider({ onPress, label?, icon?, disabled?, enabled? }): a provider with id "google" ("Continue with Google"), drawn as the row's outline button, or null when enabled is false. Pass Google's "G" mark as icon (Genesis ships no Google artwork). onPress is usually signInWithGoogle from @marktiderman/genesis-supabase/native.
  • SocialAuthProvider.render: any provider can draw its own button this way.
  • onPress is usually signInWithApple from @marktiderman/genesis-supabase/native, which returns the full name Apple shares on the first sign-in only; save it with supabase.auth.updateUser({ data: { full_name } }). See that package's README.

Deleting the account

SettingsPage's dangerousActions is where "Delete account" goes: pass an action whose onPress asks with Alert.alert (a destructive button) and then calls deleteMyAccount(supabase) from @marktiderman/genesis-supabase. The example and the SQL it needs are in that package's README.

Inbox and thread: InboxPage and ThreadPage

Two generic layouts for conversations (support tickets, direct messages, comment threads), in SettingsPage's iOS inset grouped style.

  • InboxPage: rows with an unread dot or count, a short time (9:41, Yesterday, a weekday, a date), a two-line preview and a status line; pull to refresh, onEndReached paging and an empty state with an optional action. Each row's swipeActions are always reachable as VoiceOver / TalkBack custom actions and on long press (a menu); for the swipe gesture itself, fill the swipeable slot with react-native-gesture-handler's ReanimatedSwipeable. Slots: row, swipeable, header, footer, empty.
  • ThreadPage: messages oldest first (mine trailing in the tint, theirs leading on surface), attachments, a read receipt under my newest message the other side has read (readAt), "load earlier", optimistic sending and failed messages with retry, and a composer. With KeyboardScrollProvider (the native shell's keyboardScroll) the messages and the composer scroll together above the keyboard; without it a KeyboardAvoidingView does. composer={null} makes it read-only with a closedNotice. Slots: message, attachment, readReceipt, composer, composerAccessory, header, earlier, empty.

getInboxPageStackOptions() and getThreadPageStackOptions() compose the header. @marktiderman/genesis-support/native feeds both for a person's support reports.

Part of the Genesis framework.