Button
Live preview
Hero actions and variant row — styled with RNUI semantic tokens.
Upgrade to Pro
Unlock offline mode, shared workspaces, and priority support for your team.
Start free trialLearn more
Variants
PrimaryOutlineGhostDelete
Button
Section titled “Button”The Button component wraps usePressable from the headless layer. All animation runs on the UI thread via Reanimated 3.
import { Button } from '@truongdq01/ui';
<Button label="Save changes" variant="solid" onPress={handleSave} />;| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Button text (optional for icon-only) |
variant | "solid" | "outline" | "ghost" | "destructive" | "solid" | Visual style |
size | "sm" | "md" | "lg" | "md" | Height and padding preset |
onPress | () => void | — | Press callback |
onLongPress | () => void | — | Long press callback |
loading | boolean | false | Show spinner, disable press |
disabled | boolean | false | Disable interaction and dim |
leadingIcon | ReactNode | — | Slot before label (or center if no label) |
trailingIcon | ReactNode | — | Slot after label |
feedbackMode | "scale" | "scaleSubtle" | "opacity" | "none" | "scale" | Press animation |
fullWidth | boolean | false | Fill container width |
accessibilityLabel | string | label | Override a11y label |
accessibilityHint | string | — | Screen reader hint |
Variants
Section titled “Variants”<Button label="Primary" variant="solid" onPress={() => {}} /><Button label="Secondary" variant="outline" onPress={() => {}} /><Button label="Tertiary" variant="ghost" onPress={() => {}} /><Button label="Delete" variant="destructive" onPress={() => {}} />Buttons come in three standardized heights:
- Small: 36px
- Medium: 44px
- Large: 52px
Default corner radius is radius.lg (12px) — rounded, not pill-shaped. Solid and accent variants use soft elevation; outline and ghost stay flat.
<Button label="Small" size="sm" onPress={() => {}} /><Button label="Medium" size="md" onPress={() => {}} /> {/* default */}<Button label="Large" size="lg" onPress={() => {}} />Loading state
Section titled “Loading state”<Button label="Saving…" loading={isSaving} onPress={save} />With icons
Section titled “With icons”The library uses a standardized icon styling system. Icons passed to leadingIcon or trailingIcon will automatically receive the correct size and color based on the button’s variant and size.
import { Plus, Send, Mail } from "lucide-react-native";
// Leading icon<Button label="Add item" leadingIcon={<Plus />} />
// Trailing icon<Button label="Send" variant="outline" trailingIcon={<Send />} />
// Icon only<Button leadingIcon={<Mail />} onPress={() => {}} />Headless usage
Section titled “Headless usage”import { usePressable } from '@truongdq01/headless';import Animated from 'react-native-reanimated';import { GestureDetector } from 'react-native-gesture-handler';
function MyButton({ label, onPress }) { const { tokens } = useTheme(); const { gesture, animatedStyle, accessibilityProps } = usePressable({ onPress, feedbackMode: 'scale', accessibilityLabel: label, });
return ( <GestureDetector gesture={gesture}> <Animated.View style={[myStyle, animatedStyle]} {...accessibilityProps}> <Text>{label}</Text> </Animated.View> </GestureDetector> );}