Agent skill
rn-button-component
Ensures buttons use the unified Button component with proper state management, icon support, and glass effect integration. Apply when creating or modifying buttons in the app.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/rn-button-component
SKILL.md
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 textonPress: () => 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 statesuccessText?: string | React.ReactNode- Text shown during success stateerrorText?: string | React.ReactNode- Text shown during error stateicon?: { name, size?, position? }- Icon configurationsuccessIcon?: { 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 functionstyle?: 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 optionalloadingText'success': Shows success icon with optionalsuccessText'error': Shows error message witherrorText
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
GlassViewwith liquid glass effect - Other platforms: Falls back to regular
Viewwith background color - Automatic: No configuration needed, handled internally
The glass effect respects:
variantprop for tint colorbuttonStatefor disabled/loading tint- Interactive glass effect enabled automatically
Styling
Default Styles
borderRadius: 25- Fully rounded cornerspaddingVertical: 14paddingHorizontal: 24minHeight: 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
loadingTextwhen using loading state for better UX - Use
setButtonStatefor complex state management scenarios - Use
reset={true}for temporary success states (e.g., form submissions) - Provide
errorTextwhen handling error states - Use icons sparingly - only when they add clarity
- Choose appropriate variants - use
destructiveonly 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 NativePressable
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?