Deft
Ask AI

Search

Search skills, authors and topics

Appllama / appllama-skills

appllama-app-design-skill

Build native-feeling, benchmark-quality mobile app screens (Expo / React Native). Use when designing or implementing any mobile UI — screens, flows, onboarding, paywalls, tab bars, sheets, settings, empty states — or when polishing motion, navigation, typography, dark mode, or perceived performance. Enforces Apple HIG fidelity, semantic colors, native controls, anti-slop discipline, navigation semantics, purposeful Reanimated motion, a full-motion simulator-verified iteration loop, and a study-real-apps-first workflow.

Install

npx skills add https://github.com/Appllama/appllama-skills --skill appllama-app-design-skill

Native controls — use the platform's, wire them right

A native-feeling app is mostly assembled from controls the OS already ships. Rebuild a control only when the design genuinely diverges — and then match the platform's timing and haptics so it still reads as native.

Control selection table

NeediOSAndroidPackage
ToggleSwitchMaterial Switchreact-native Switch (renders native on both)
Single choice, 2–5 optionsSegmented controlTabs / segmented buttons@react-native-segmented-control/segmented-control
Value in a rangeSliderMaterial Slider@react-native-community/slider
Date / timeWheel or inline calendarMaterial pickers@react-native-community/datetimepicker (display="inline" for calendars on iOS)
Contextual actionsContext menu (long-press/tap)Popup menuzeego (native menus on both) — never a JS dropdown for item actions
Destructive confirmAction sheetBottom sheet / dialogActionSheetIOS via @expo/react-native-action-sheet
Bottom sheet contentDetented sheetBottom sheet@gorhom/bottom-sheet (see notes)
SearchNav-bar integrated searchSearchViewExpo Router headerSearchBarOptions
Pull to refreshUIRefreshControlSwipeRefreshLayoutRefreshControl on the ScrollView/list
HapticsUIImpactFeedbackGeneratorVibratorexpo-haptics
In-app browserSFSafariViewControllerCustom Tabsexpo-web-browser

Item-level actions (rename, share, delete) belong in a native context menu anchored to the element, with SF Symbols on iOS:

tsx
<ContextMenu.Root>  <ContextMenu.Trigger>{card}</ContextMenu.Trigger>  <ContextMenu.Content>    <ContextMenu.Item key="share" onSelect={share}>      <ContextMenu.ItemTitle>Share</ContextMenu.ItemTitle>      <ContextMenu.ItemIcon ios={{ name: 'square.and.arrow.up' }} />    </ContextMenu.Item>    <ContextMenu.Item key="delete" destructive onSelect={confirmDelete}>      <ContextMenu.ItemTitle>Delete</ContextMenu.ItemTitle>      <ContextMenu.ItemIcon ios={{ name: 'trash' }} />    </ContextMenu.Item>  </ContextMenu.Content></ContextMenu.Root>

Destructive items: destructive role + a confirm step (action sheet), never a bare tap-to-delete.

Bottom sheets

  • Detents should be content-derived (enableDynamicSizing) or the platform set (medium/large) — arbitrary 37%/63% detents feel arbitrary.
  • The sheet's drag must hand off to inner scroll correctly: use the library's provided BottomSheetScrollView/BottomSheetFlashList, never a plain ScrollView inside.
  • Backdrop: fade in with sheet position (interpolate on animatedIndex), tap-to-dismiss, and dim to the platform's standard (~40% black).
  • Keyboard: keyboardBlurBehavior="restore", and test with the keyboard up — half the bottom-sheet bugs in the wild are keyboard interactions.

Forms and inputs

  • Labels above fields, not placeholders-as-labels.
  • keyboardType, autoComplete, textContentType on every input — enables autofill and the right keyboard. textContentType="oneTimeCode" for OTPs.
  • Return-key chaining: returnKeyType="next" + focus the next field; final field submits.
  • Validate on blur or submit, never on keystroke; errors appear beneath the field in the platform's error color and stay until fixed.
  • Wrap forms in a keyboard-avoiding strategy you have actually tested (react-native-keyboard-controller is the current best answer).
  • Stack for drill-in, tabs for top-level destinations, modal for self-contained tasks. Do not put a back-navigable flow inside a modal deeper than 2 steps — use a stack inside the modal with its own header.
  • iOS: swipe-back must always work (don't block the interactive pop gesture).
  • Tab bars: 3–5 items, SF Symbols with the filled variant for the active tab, labels always on (icon-only tab bars fail recognition tests).
  • Deep links: every screen reachable by URL via Expo Router's file routes.

When you DO rebuild a control

Match the OS's numbers, not your instincts:

  • iOS switch: thumb travel ~22 pt in ~0.2 s with a slight squish; haptic on toggle.
  • Pressed states: opacity 0.4 for plain-text buttons, scale 0.97 + slight darken for filled buttons, spring back on release.
  • Selection cells: checkmark animates in with a short fade+scale, row flashes the selection color for ~150 ms.
  • Always add the platform haptic the real control would emit.