appCN
← All components

Button

Base
new

Pressable with variants and a Reanimated press-scale. Accessible by default.

Preview

Scan with Expo Go to run it live

Install Expo Goon Android or iPhone, scan, and the entire appCN gallery loads — real native motion & gestures, not a web shim.

Open in Expo Go Play Store — coming soon
https://expo.dev/preview/update?message=v1.0.0+initial&updateRuntimeVersion=1.0.0&createdAt=2026-05-28T20%3A07%3A21.247Z&slug=exp&projectId=a2d02caa-be26-436a-acd6-f3007862ba0a&group=3ca7e750-9506-4146-8394-1a16c3a917a8

Install

npx @app-cn/cli@latest add button

Recommended. Configures NativeWind + Reanimated and registers @app-cn on first run.

Anatomy

A Reanimated wrapper around a React Native Pressable. The variant + size cva blocks own the visual surface; an animated transform on the wrapper drives the press-scale. Reach for it any time you'd reach for a native <Pressable>, and let the variants do the styling work.

The delight detail

Press-in snaps the button to 0.96 with a fast 100ms ease; release settles back over 140ms — so taps feel weighted, never twitchy, and you never see overshoot.

Props

NameTypeDefaultDescription
variant"default" | "secondary" | "outline" | "ghost" | "destructive""default"Visual style. Drives bg, border, and text color via cva blocks.
size"sm" | "default" | "lg" | "icon""default"Height + horizontal padding preset. `icon` is square 12×12.
childrenReact.ReactNodeString children are auto-wrapped in a styled <Text>. Pass a composition for icon + label.
classNamestringExtra NativeWind classes merged onto the Pressable surface.
textClassNamestringExtra NativeWind classes merged onto the auto-text (string children only).
disabledbooleanfalseDisables press handling and applies 50% opacity.
onPress(e: GestureResponderEvent) => voidForwarded to the underlying Pressable.

Examples

Basic

String children get auto-styled text.

<Button onPress={() => console.log("hi")}>Get started</Button>

Variants

All five variants at the default size.

<View className="gap-3">
  <Button>Primary</Button>
  <Button variant="secondary">Secondary</Button>
  <Button variant="outline">Outline</Button>
  <Button variant="ghost">Ghost</Button>
  <Button variant="destructive">Delete</Button>
</View>

Icon button

Use size="icon" with a non-string child to render just a glyph.

<Button size="icon" variant="outline" accessibilityLabel="Settings">
  <SettingsIcon />
</Button>

Accessibility

  • Defaults to `accessibilityRole="button"` — no need to set it yourself.
  • `disabled` is reflected in `accessibilityState`, so VoiceOver announces it correctly.
  • Icon-only buttons must pass `accessibilityLabel` since there is no visible text.
  • Minimum touch target is 36pt (size sm) — prefer `default` (48pt) or bigger for primary actions.