rn-button-component

Guide for using the unified Button component with state management, icon support, and glass effect integration.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "rn-button-component" with this command: npx skills add jchaselubitz/drill-app/jchaselubitz-drill-app-rn-button-component

Button Component

Guide for using the unified Button component with state management, icon support, and glass effect integration.

Overview

  • Location: @/components/Button

  • Features: State management, icon support, loading states, success/error states, glass effect on iOS

  • Design: Rounded corners (borderRadius: 25), glass effect on iOS when available

Basic Usage

import { Button } from '@/components/Button';

<Button text="Click Me" onPress={() => console.log('Pressed')} />

Props

Required Props

  • text: string | React.ReactNode

  • Button label text

  • onPress: () => void

  • Press handler function

Optional Props

  • variant?: 'primary' | 'secondary' | 'destructive'

  • Button style variant (default: 'primary' )

  • buttonState?: ButtonState

  • Current button state (default: 'default' )

  • loadingText?: string | React.ReactNode

  • Text shown during loading state

  • successText?: string | React.ReactNode

  • Text shown during success state

  • errorText?: string | React.ReactNode

  • Text shown during error state

  • icon?: { name, size?, position? }

  • Icon configuration

  • successIcon?: { name, size? }

  • Icon shown in success state (default: 'checkmark' )

  • reset?: boolean

  • Auto-reset from success to default after 2 seconds (default: false )

  • setButtonState?: (state: ButtonState) => void

  • External state control function

  • style?: StyleProp<ViewStyle>

  • Additional styles

Button States

export type ButtonState = 'default' | 'disabled' | 'loading' | 'success' | 'error';

State Behavior

  • 'default' : Normal interactive state

  • 'disabled' : Button is disabled and non-interactive

  • 'loading' : Shows loading spinner with optional loadingText

  • 'success' : Shows success icon with optional successText

  • 'error' : Shows error message with errorText

Common Patterns

Basic Button

<Button text="Save" onPress={handleSave} />

Button with Variant

<Button text="Cancel" onPress={handleCancel} variant="secondary" /> <Button text="Delete" onPress={handleDelete} variant="destructive" />

Loading State

const [isSaving, setIsSaving] = useState(false);

<Button text="Save" onPress={handleSave} buttonState={isSaving ? 'loading' : 'default'} loadingText="Saving..." />

Disabled State

<Button text="Submit" onPress={handleSubmit} buttonState={!isValid ? 'disabled' : 'default'} />

Button with Icon

<Button text="Create Lesson" onPress={handleCreate} icon={{ name: 'add', size: 24, position: 'left' }} variant="secondary" />

Success State with Auto-Reset

const [buttonState, setButtonState] = useState<ButtonState>('default');

const handleSave = async () => { setButtonState('loading'); try { await saveData(); setButtonState('success'); } catch (error) { setButtonState('error'); } };

<Button text="Save" onPress={handleSave} buttonState={buttonState} setButtonState={setButtonState} loadingText="Saving..." successText="Saved!" errorText="Failed to save" reset={true} // Auto-resets to 'default' after 2 seconds />

Combined Loading and Disabled

<Button text="Save Lesson" onPress={handleSave} buttonState={isSaving ? 'loading' : isLoading ? 'disabled' : 'default'} loadingText="Saving..." />

Icon Configuration

Icon Props

icon?: { name: keyof typeof Ionicons.glyphMap; // Required: Ionicons icon name size?: number; // Optional: Icon size (default: 24) position?: 'left' | 'right'; // Optional: Icon position (default: 'left') }

Examples

// Left icon (default) <Button text="Add Item" icon={{ name: 'add', position: 'left' }} onPress={handleAdd} />

// Right icon <Button text="Next" icon={{ name: 'arrow-forward', position: 'right' }} onPress={handleNext} />

// Custom size <Button text="Settings" icon={{ name: 'settings', size: 20 }} onPress={handleSettings} />

State Management

Internal State (Default)

The button manages its own state internally when setButtonState is not provided:

<Button text="Click Me" onPress={handleClick} buttonState="loading" // State is managed internally />

External State Control

Provide setButtonState to control state externally:

const [state, setState] = useState<ButtonState>('default');

<Button text="Submit" onPress={handleSubmit} buttonState={state} setButtonState={setState} loadingText="Submitting..." />

Auto-Reset Pattern

When reset={true} and button reaches 'success' state, it automatically resets to 'default' after 2 seconds:

const [state, setState] = useState<ButtonState>('default');

<Button text="Save" onPress={async () => { setState('loading'); await save(); setState('success'); }} buttonState={state} setButtonState={setState} reset={true} successText="Saved!" />

Glass Effect

The button automatically uses glass effect on iOS when available:

  • iOS 26+: Uses GlassView with liquid glass effect

  • Other platforms: Falls back to regular View with background color

  • Automatic: No configuration needed, handled internally

The glass effect respects:

  • variant prop for tint color

  • buttonState for disabled/loading tint

  • Interactive glass effect enabled automatically

Styling

Default Styles

  • borderRadius: 25

  • Fully rounded corners

  • paddingVertical: 14

  • paddingHorizontal: 24

  • minHeight: 48

Custom Styles

<Button text="Custom Button" onPress={handlePress} style={{ marginTop: 16, width: '100%' }} />

Complete Examples

Form Submit Button

const [isSubmitting, setIsSubmitting] = useState(false); const [submitState, setSubmitState] = useState<ButtonState>('default');

const handleSubmit = async () => { setIsSubmitting(true); setSubmitState('loading');

try { await submitForm(); setSubmitState('success'); } catch (error) { setSubmitState('error'); } finally { setIsSubmitting(false); } };

<Button text="Submit Form" onPress={handleSubmit} buttonState={submitState} setButtonState={setSubmitState} loadingText="Submitting..." successText="Submitted!" errorText="Submission failed" reset={true} disabled={!isFormValid} />

Action Button with Icon

<Button text="Create Lesson" onPress={openModal} icon={{ name: 'add', size: 24, position: 'left' }} variant="secondary" />

Conditional Loading

<Button text="Translate" onPress={handleTranslate} buttonState={isTranslating ? 'loading' : 'default'} loadingText="Translating..." variant="secondary" />

Best Practices

  • Always provide loadingText when using loading state for better UX

  • Use setButtonState for complex state management scenarios

  • Use reset={true} for temporary success states (e.g., form submissions)

  • Provide errorText when handling error states

  • Use icons sparingly - only when they add clarity

  • Choose appropriate variants - use destructive only for destructive actions

TypeScript

import { Button, ButtonState } from '@/components/Button';

const [state, setState] = useState<ButtonState>('default');

References

  • Component location: components/Button.tsx

  • Uses: expo-glass-effect , @expo/vector-icons , React Native Pressable

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

expo-router

No summary provided by upstream source.

Repository SourceNeeds Review
General

watermelondb

No summary provided by upstream source.

Repository SourceNeeds Review
General

expo-audio

No summary provided by upstream source.

Repository SourceNeeds Review
General

expo-glass-effect

No summary provided by upstream source.

Repository SourceNeeds Review