Create Component - Interactive Workflow
You are helping create a new component for gluestack-ui, a cross-platform React Native/Expo UI library. Follow this comprehensive workflow to ensure the component follows all established patterns and best practices.
CRITICAL REQUIREMENTS
- ALWAYS enter Plan Mode first using the EnterPlanMode tool
- NEVER skip user confirmations - there are 6 confirmation points
- ALWAYS analyze existing components before proposing patterns
- ALWAYS follow the compound component API pattern for multi-part components
- ALWAYS use AskUserQuestion to gather requirements and preferences
- ALWAYS discuss tradeoffs before making design decisions
- NEVER edit generated files in
apps/*/components/ui/- only editsrc/ - ALWAYS use latest color tokens from
src/components/ui/gluestack-ui-provider/config.ts - ALWAYS respect user's animation library preference - ask explicitly and use their choice
- ALWAYS use correct package imports - e.g.,
@gluestack-ui/core/bottomsheet/creatornot@gluestack-ui/bottomsheet - ALWAYS define exports properly - barrel exports in
packages/gluestack-core/src/[component]/index.tsxand package.json typesVersions - ALWAYS research similar components on the web to understand best practices and functionality patterns
- NEVER manually modify apps/ directory - changes propagate automatically through mappers
WORKFLOW: 8 PHASES
PHASE 1: ENTER PLAN MODE & DISCOVERY
Step 1.1: Enter Plan Mode
Use EnterPlanMode tool to enter planning mode. You will explore the codebase and design the component before implementation.
Step 1.2: Gather Initial Requirements
Use AskUserQuestion tool to gather basic information:
Initial Questions (Must Ask First):
questions:
- question: "What is the name of the component you want to create?"
header: "Component Name"
multiSelect: false
options:
- label: "Single-word component (e.g., dropdown, tooltip, badge)"
description: "Simple kebab-case name for basic components"
- label: "Multi-word component (e.g., bottom-sheet, file-upload, date-picker)"
description: "Compound kebab-case name for complex components"
- question: "What category does this component belong to?"
header: "Category"
multiSelect: false
options:
- label: "Overlays (Recommended for modals, sheets, tooltips)"
description: "Components that appear above other content (modals, sheets, popovers, tooltips)"
- label: "Data Display (Recommended for cards, lists, tables)"
description: "Components that display information (cards, badges, avatars, tables)"
- label: "Forms (Recommended for inputs, selects)"
description: "Form-related components (inputs, checkboxes, selects, switches)"
- label: "Layout (Recommended for containers, grids)"
description: "Structural components (containers, stacks, grids, dividers)"
- question: "What problem does this component solve?"
header: "Purpose"
multiSelect: false
options:
- label: "User interaction (buttons, inputs, controls)"
description: "Allows users to interact with the application"
- label: "Information display (cards, badges, alerts)"
description: "Shows information or status to users"
- label: "Navigation (menus, tabs, breadcrumbs)"
description: "Helps users navigate the application"
- label: "Feedback (toasts, alerts, progress)"
description: "Provides feedback about actions or states"
- question: "What animation library do you prefer for this component?"
header: "Animation"
multiSelect: false
options:
- label: "react-native-reanimated (Recommended)"
description: "Better performance, runs on UI thread, most components use this"
- label: "@legendapp/motion"
description: "Simple declarative animations, good for basic transitions"
- label: "No animations"
description: "Static component without animations"
After getting these answers, ask the user to describe in their own words:
- What is the specific problem this component addresses?
- What are the key features it must have?
- Any specific design references or inspirations?
Step 1.3: Research Similar Components
IMPORTANT: Research on the web first before designing!
Use WebSearch tool to research:
- Search for "[component-name] component best practices" (e.g., "bottom sheet component best practices")
- Search for "[component-name] accessibility patterns" (e.g., "bottom sheet accessibility")
- Search for "React Native [component-name] implementation"
- Look for inspiration from popular UI libraries:
- Material Design guidelines for this component
- iOS Human Interface Guidelines
- Chakra UI, Ant Design, Material-UI implementations
- React Native Paper, NativeBase implementations
Analyze the research to understand:
- Common features and patterns
- Accessibility best practices
- Animation patterns
- API design conventions
- Edge cases to handle
Present research findings to user:
## Research Findings: [ComponentName]
### Industry Best Practices:
- [Finding 1 with source]
- [Finding 2 with source]
- [Finding 3 with source]
### Common Features Found:
- [Feature 1 - seen in Library A, Library B]
- [Feature 2 - recommended by Material Design]
- [Feature 3 - iOS HIG standard]
### Accessibility Standards:
- [ARIA pattern to follow]
- [Keyboard interactions needed]
- [Screen reader considerations]
### Recommended Features for Our Component:
Based on research, we should include:
1. [Feature with justification]
2. [Feature with justification]
3. [Feature with justification]
Ask user:
- Do you agree with these recommendations?
- Any features you want to add/remove based on the research?
- Any concerns about complexity vs functionality?
Step 1.4: Analyze Existing Patterns
Read and understand these files to learn gluestack-ui patterns:
/Users/sanchitkumar/Downloads/new_folder/gluestack-ui/CONTRIBUTING.md- Complete contribution guidelines/Users/sanchitkumar/Downloads/new_folder/gluestack-ui/src/components/ui/accordion/index.tsx- Example compound component/Users/sanchitkumar/Downloads/new_folder/gluestack-ui/src/components/ui/button/index.tsx- Example with style context/Users/sanchitkumar/Downloads/new_folder/gluestack-ui/src/components/ui/alert-dialog/index.tsx- Example with animations/Users/sanchitkumar/Downloads/new_folder/gluestack-ui/packages/gluestack-core/src/accordion/creator/index.tsx- Example creator pattern- Color tokens:
/Users/sanchitkumar/Downloads/new_folder/gluestack-ui/src/components/ui/gluestack-ui-provider/config.ts- Latest color system
Use Glob/Grep to find more examples if needed.
Step 1.5: Gather Detailed Requirements
Use AskUserQuestion tool to ask additional questions:
Question 1: Component Type
questions:
- question: "What type of component is this?"
header: "Component Type"
multiSelect: false
options:
- label: "Simple component"
description: "Single element like Card, Badge - no sub-components"
- label: "Compound component (Recommended)"
description: "Multiple sub-components like Accordion, AlertDialog - follows gluestack pattern"
- label: "Form component"
description: "Input, Checkbox, Select - form interaction"
- label: "Overlay component"
description: "Modal, Popover, Tooltip - floating/overlay UI"
- label: "Layout component"
description: "Container, Grid, Stack - structural layout"
Question 2: Platform Requirements
questions:
- question: "Which platforms should this component support?"
header: "Platforms"
multiSelect: true
options:
- label: "iOS (Recommended)"
description: "Support iOS devices"
- label: "Android (Recommended)"
description: "Support Android devices"
- label: "Web (Recommended)"
description: "Support web browsers via React Native Web"
- label: "Web-specific implementation"
description: "Needs separate index.web.tsx file for web-only code"
Question 3: Accessibility Requirements
questions:
- question: "Does this component need ARIA support and accessibility features?"
header: "Accessibility"
multiSelect: true
options:
- label: "Keyboard navigation (Recommended)"
description: "Arrow keys, Tab, Enter, Escape support"
- label: "Screen reader support (Recommended)"
description: "ARIA labels, announcements, semantic markup"
- label: "Focus management"
description: "Focus trap, auto-focus, focus return"
- label: "ARIA patterns"
description: "Follow WAI-ARIA authoring practices"
If ARIA is needed, ask which pattern applies (dialog, menu, button, checkbox, etc.)
Question 4: Animation Details
Based on the animation library chosen earlier, ask specifics:
If react-native-reanimated was chosen:
questions:
- question: "What type of animations does this component need?"
header: "Animation Type"
multiSelect: true
options:
- label: "Entrance/exit animations (Recommended)"
description: "FadeIn, SlideIn, ZoomIn when mounting/unmounting"
- label: "Gesture-driven animations"
description: "Swipe, drag, pinch interactions"
- label: "Spring physics"
description: "Natural motion with spring animations"
- label: "Layout animations"
description: "Animate position and size changes"
If @legendapp/motion was chosen:
questions:
- question: "What type of animations does this component need?"
header: "Animation Type"
multiSelect: true
options:
- label: "Opacity transitions"
description: "Fade in/out effects"
- label: "Scale transitions"
description: "Zoom in/out effects"
- label: "Position transitions"
description: "Slide movements"
Question 5: Styling & Variants
Ask the user:
- What variants should this component support? (e.g., size: sm/md/lg, variant: default/outline/ghost)
- What should be the default variant?
- Does it need parent-child style context? (if compound component)
- Should it support custom theming?
IMPORTANT: Always use color tokens from src/components/ui/gluestack-ui-provider/config.ts for styling:
- Use semantic tokens like
bg-background,text-foreground,border-border - These tokens support both light and dark modes automatically
- Never hardcode color values like
#000000orrgb(0,0,0)
Question 6: Sub-components (if compound)
If it's a compound component, ask:
- List all sub-components needed (e.g., Dropdown, DropdownTrigger, DropdownContent, DropdownItem)
- How do they interact with each other?
- What state/context needs to be shared?
- What's the typical usage pattern?
Question 7: Dependencies
The animation library is already determined (user chose earlier). Ask about other dependencies:
questions:
- question: "Which additional external dependencies does this component need?"
header: "Dependencies"
multiSelect: true
options:
- label: "None (Recommended)"
description: "Use only React Native core primitives + chosen animation library"
- label: "react-native-svg"
description: "For custom icons or SVG elements"
- label: "@floating-ui/react-native"
description: "For positioning (popovers, tooltips, dropdowns)"
- label: "react-native-gesture-handler"
description: "For complex touch gestures"
- label: "Other (specify)"
description: "Other npm packages needed"
If "Other" is selected, ask the user to specify which packages and why.
IMPORTANT: Remember the user's animation library choice and NEVER substitute it with a different library during implementation!
PHASE 2: API DESIGN & CONFIRMATION
Step 2.1: Analyze Similar Components
Use Glob to find similar components:
Use Glob tool with pattern: "src/components/ui/**/index.tsx"
Read 2-3 similar components to understand:
- How they structure their API
- Naming conventions for props
- TypeScript interface patterns
- Sub-component naming
- Event handler naming (onOpenChange vs onChange vs onToggle)
Step 2.2: Design Component API
Based on requirements and similar component analysis, design the API:
For a compound component example:
// Component API
<ComponentName>
<ComponentTrigger>
<Button>Open</Button>
</ComponentTrigger>
<ComponentContent>
<ComponentItem>
<ComponentItemText>Item 1</ComponentItemText>
</ComponentItem>
</ComponentContent>
</ComponentName>
// Props interfaces
interface ComponentNameProps {
defaultOpen?: boolean;
onOpenChange?: (open: boolean) => void;
children: React.ReactNode;
}
interface ComponentContentProps {
placement?: 'top' | 'bottom' | 'left' | 'right';
className?: string;
children: React.ReactNode;
}
// ... other interfaces
For a simple component:
<ComponentName
size="md"
variant="default"
className="custom-class"
>
Content here
</ComponentName>
interface ComponentNameProps {
size?: 'sm' | 'md' | 'lg';
variant?: 'default' | 'outline' | 'ghost';
className?: string;
children?: React.ReactNode;
}
Step 2.3: Present API to User
Present the complete API design to the user and ask:
- Is this API intuitive and easy to use?
- Does it follow React Native conventions?
- Are the prop names clear and self-explanatory?
- Any missing props or features?
- Any naming conflicts with existing components?
- Would you prefer different sub-component names?
CHECKPOINT 1: Get user confirmation on API design before proceeding.
PHASE 3: TRADEOFFS & DESIGN DECISIONS
Step 3.1: Identify Design Decisions
Based on the component type and requirements, identify key decisions. Common decisions:
- State Management: Controlled vs Uncontrolled vs Both
- Positioning: Manual vs Auto-positioning library
- Trigger: Specific component vs Any child
- Animation Library: Animated API vs react-native-reanimated
- Accessibility: Basic vs Full WCAG compliance
- Flexibility: Simple API vs Highly configurable
Step 3.2: Present Tradeoffs
Create a tradeoffs table for each decision:
## Design Decisions & Tradeoffs
### Decision 1: State Management
| Aspect | Option A: Controlled Only | Option B: Both Controlled & Uncontrolled | Recommendation |
|--------|---------------------------|------------------------------------------|----------------|
| **API Complexity** | Simple - requires value & onChange | More complex - supports both patterns | Option B |
| **Flexibility** | Developer must manage state | Works with or without state management | Option B |
| **Common Use Case** | Best for complex forms | Best for both simple and complex cases | Option B |
| **Bundle Size** | Smaller (~1KB less) | Slightly larger | Option B |
| **Pattern Match** | Alert uses controlled only | Accordion, Select use both | Option B ✅ |
**Recommendation:** Option B - Support both patterns like most gluestack components
### Decision 2: Animation
| Aspect | Option A: Animated API | Option B: react-native-reanimated | Recommendation |
|--------|------------------------|----------------------------------|----------------|
| **Performance** | Good for simple animations | Excellent - runs on UI thread | Option B |
| **Cross-platform** | Works but different APIs | Consistent API web+native | Option B |
| **Bundle Size** | No extra dependency | Adds ~50KB | Option B |
| **Developer Experience** | More complex API | Simpler, declarative API | Option B |
| **Pattern Match** | Button uses Animated | AlertDialog, Drawer use reanimated | Option B ✅ |
**Recommendation:** Option B - Use react-native-reanimated for consistency
### Decision 3: [Add more decisions as needed]
Step 3.3: Discuss with User
Present the tradeoffs and ask:
- Do you agree with the recommendations?
- Any preferences different from recommendations?
- Any concerns about bundle size, performance, or complexity?
- Should we prioritize API simplicity over flexibility?
CHECKPOINT 2: Get user confirmation on design decisions before proceeding.
PHASE 4: PATTERN MATCHING & CONSISTENCY
Step 4.1: Pattern Analysis
Use Glob and Grep to analyze patterns:
# Find similar components
Glob: "src/components/ui/**/index.tsx"
# Check naming conventions
Grep: "export const.*= React.forwardRef" in src/components/ui/
# Check prop patterns
Grep: "size.*=.*'sm'" in src/components/ui/
# Check style patterns
Grep: "tva\\({" in src/components/ui/**/styles.tsx
# Check TypeScript patterns
Grep: "interface.*Props" in src/components/ui/
Step 4.2: Create Pattern Report
Generate a report showing:
## Pattern Analysis Report
### ✅ Similar Components Found
- **Popover**: Uses @floating-ui/react-native for positioning
- **Menu**: Uses compound pattern with MenuItem
- **Select**: Uses similar dropdown behavior
- **AlertDialog**: Uses withStyleContext for parent-child styling
### ✅ Naming Conventions
- Folders: kebab-case (e.g., `alert-dialog`, `file-upload`)
- Components: PascalCase (e.g., `AlertDialog`, `FileUpload`)
- Props: camelCase (e.g., `isOpen`, `onOpenChange`)
- Variants: lowercase (e.g., `size='sm'`, not `size='SM'`)
### ✅ Prop Patterns
- Size prop: `'sm' | 'md' | 'lg'` (consistent across all components)
- Variant prop: `'default' | 'outline' | 'ghost' | 'destructive'`
- Boolean props: Prefix with `is` (e.g., `isOpen`, `isDisabled`)
- Event handlers: Prefix with `on` (e.g., `onChange`, `onOpenChange`)
### ✅ Style Patterns
- All use `tva()` from gluestack-utils
- Styles defined in separate `styles.tsx` file
- Parent variants passed via `withStyleContext` and `useStyleContext`
- Base styles + variants structure
### ✅ TypeScript Patterns
- All use React.forwardRef with generic types
- Props extend base component props
- Variants typed with VariantProps<typeof styleFunction>
- All exports are named exports
### ✅ File Structure Pattern
component-name/ ├── index.tsx # Main component ├── index.web.tsx # Web-specific (if needed) ├── styles.tsx # Tailwind styles ├── dependencies.json # NPM dependencies ├── docs/ │ └── index.mdx └── examples/ └── basic/ ├── meta.json └── template.handlebars
### 📋 Pattern Recommendations for Your Component
Based on analysis, your component should:
1. Use kebab-case for folder: `your-component-name`
2. Use PascalCase for components: `YourComponentName`
3. Follow size prop pattern: `'sm' | 'md' | 'lg'`
4. Use `isOpen` and `onOpenChange` for open state (not `open` and `onToggle`)
5. Define styles in separate `styles.tsx` using `tva()`
6. Use `withStyleContext` if compound component
7. Export all sub-components as named exports
Step 4.3: Confirm Pattern Matching
Ask the user:
- Do these patterns make sense?
- Should we follow all the recommendations?
- Any patterns you'd like to deviate from? (and why)
CHECKPOINT 3: Get user confirmation on pattern matching before proceeding.
PHASE 5: IMPLEMENTATION PLAN & CONFIRMATION
Step 5.1: Create Complete Implementation Plan
Generate detailed plan:
## Implementation Plan: [ComponentName]
### 📁 File Structure
**CRITICAL: Follow this EXACT structure as per CONTRIBUTING.md:**
src/components/ui// ├── index.tsx # Main component file (copy-pasteable) ├── index.web.tsx # Web-specific (if needed) ├── styles.tsx # Tailwind styles with tva() (optional) ├── dependencies.json # NPM dependencies (if needed) ├── examples/ # Usage examples │ ├── basic/ # Basic example (REQUIRED) │ │ ├── meta.json # Example metadata with reactLive imports │ │ └── template.handlebars # Handlebars template (no imports) │ ├── customized-component/ # Customized variant │ │ ├── meta.json │ │ └── template.handlebars │ └── [other-examples]/ # Additional examples (3-5 total recommended) │ ├── meta.json │ └── template.handlebars └── docs/ # Main documentation └── index.mdx # Component documentation page
packages/gluestack-core/src// ├── creator/ │ └── index.tsx # create[ComponentName] factory ├── aria/ │ └── index.tsx # use[ComponentName] hook (if needed) └── index.tsx # Barrel export
**Note:** Use `<component-name>` in kebab-case (e.g., `bottom-sheet`, `alert-dialog`)
### 🔧 Core Package Implementation
**CRITICAL: Proper Exports Configuration**
When creating a new component in gluestack-core, you MUST configure exports properly:
1. **Barrel Export:** Create `packages/gluestack-core/src/[component-name]/index.tsx`:
```typescript
export * from './creator';
export * from './creator/types'; // if types exist
export * from './aria'; // if aria exists
- Update Main Index: Add to
packages/gluestack-core/src/index.tsx:
export * from './[component-name]';
Package.json Updates: The barrel exports for deep imports (e.g.,
@gluestack-ui/core/[component]/creator) are auto-generated byscripts/generate-barrel-exports.jsduring build. The script:- Scans
src/for component directories - Creates barrel files in the component root directory (e.g.,
bottomsheet/creator.ts) - These files export from
lib/esm/[component]/[subdir]
- Scans
TypesVersions: For TypeScript to find the deep imports, typesVersions in package.json will be updated in the next package release
File: packages/gluestack-core/src/[component-name]/creator/index.tsx
export function create[ComponentName]<
RootProps,
// ... other generic types
>({
Root,
// ... other components
}: {
Root: React.ComponentType<RootProps>;
// ... other components
}) {
const [ComponentName] = [ComponentName]Main(Root) as any;
[ComponentName].SubComponent = [ComponentName]SubComponent(SubComponent);
// ... more sub-components
return [ComponentName] as I[ComponentName]ComponentType<...>;
}
File: packages/gluestack-core/src/[component-name]/aria/index.tsx (if needed)
export function use[ComponentName]({
// ... props
}: Use[ComponentName]Props) {
// ARIA logic using react-aria hooks
return {
// ... return values
};
}
🎨 UI Component Implementation
CRITICAL: Use Correct Import Paths
Always import from the deep path, not the component name directly:
- ✅ CORRECT:
import { create[ComponentName] } from '@gluestack-ui/core/[component-name]/creator'; - ❌ WRONG:
import { create[ComponentName] } from '@gluestack-ui/[component-name]';
CRITICAL: Use User's Animation Library Choice
Use the animation library the user specified during requirements gathering:
- If user chose react-native-reanimated: Use
Animatedfromreact-native-reanimated - If user chose @legendapp/motion: Use motion components from
@legendapp/motion - If user chose No animations: Don't import any animation library
CRITICAL: Use Latest Color Tokens
Always use semantic color tokens from the gluestack-ui theme system:
- Use tokens like:
bg-background,bg-card,text-foreground,border-border,bg-primary,bg-secondary - These are defined in
src/components/ui/gluestack-ui-provider/config.ts - They automatically support light/dark mode
- Never use hardcoded colors like
bg-white,text-black,#000000
File: src/components/ui/[component-name]/index.tsx
'use client';
import React from 'react';
import { View, Text, Pressable } from 'react-native';
// CORRECT import path - use deep import from core package
import { create[ComponentName] } from '@gluestack-ui/core/[component-name]/creator';
import { tva, withStyleContext, useStyleContext, type VariantProps } from '@gluestack-ui/utils/nativewind-utils';
import { [componentName]Style, [subComponent]Style } from './styles';
// Import animation library based on user's choice
// Example with react-native-reanimated:
import Animated, { FadeIn, SlideInUp } from 'react-native-reanimated';
// OR with @legendapp/motion:
// import { Motion } from '@legendapp/motion';
// Create context-aware root
const Root = withStyleContext(View, '[COMPONENT_NAME]');
// Create compound component
const UI[ComponentName] = create[ComponentName]({
Root: Root,
// ... other components
});
// Main component with variants
const [ComponentName] = React.forwardRef<
React.ComponentRef<typeof View>,
React.ComponentProps<typeof View> & VariantProps<typeof [componentName]Style>
>(({ className, size = 'md', variant = 'default', ...props }, ref) => {
return (
<UI[ComponentName]
ref={ref}
className={[componentName]Style({ size, variant, class: className })}
context={{ size, variant }}
{...props}
/>
);
});
[ComponentName].displayName = '[ComponentName]';
// Sub-components
const [SubComponent] = React.forwardRef<
React.ComponentRef<typeof View>,
React.ComponentProps<typeof View>
>(({ className, ...props }, ref) => {
const { size, variant } = useStyleContext('[COMPONENT_NAME]');
return (
<UI[ComponentName].[SubComponent]
ref={ref}
className={[subComponent]Style({
parentVariants: { size, variant },
class: className
})}
{...props}
/>
);
});
[SubComponent].displayName = '[SubComponent]';
// Exports
export { [ComponentName], [SubComponent], /* ... other exports */ };
File: src/components/ui/[component-name]/styles.tsx
import { tva } from '@gluestack-ui/utils/nativewind-utils';
// CRITICAL: Always use semantic color tokens from config.ts
// Available tokens: --background, --foreground, --card, --primary, --secondary,
// --muted, --accent, --destructive, --border, --input, --ring, --popover
// Use as: bg-background, text-foreground, border-border, bg-card, bg-primary, etc.
export const [componentName]Style = tva({
base: 'flex-col rounded-md',
variants: {
size: {
sm: 'p-2 gap-2',
md: 'p-4 gap-4',
lg: 'p-6 gap-6',
},
variant: {
// Use semantic tokens - these work in light AND dark mode automatically
default: 'bg-background border border-border',
outline: 'bg-transparent border border-border',
ghost: 'bg-transparent',
card: 'bg-card border border-border',
},
},
defaultVariants: {
size: 'md',
variant: 'default',
},
});
export const [subComponent]Style = tva({
base: 'flex-row items-center',
parentVariants: {
size: {
sm: 'gap-1',
md: 'gap-2',
lg: 'gap-3',
},
},
});
File: src/components/ui/[component-name]/dependencies.json (if needed)
{
"dependencies": {
"@floating-ui/react-native": "^0.10.0",
"react-native-reanimated": "^3.0.0"
}
}
📝 Documentation
File: src/components/ui/[component-name]/docs/index.mdx
- Installation section (CLI + Manual)
- Basic usage example
- API reference table
- Props documentation
- Accessibility notes
- Best practices
🎯 Examples
CRITICAL: Follow exact format and structure from existing components!
Create 3-5 comprehensive examples demonstrating different use cases:
- basic/ - REQUIRED - Simple, default usage
- customized-component/ - Customized styling with variants
- controlled/ - Controlled state management (if applicable)
- with-[feature]/ - Specific features (e.g., with-icons, with-image)
- [real-world-scenario]/ - Practical use case (e.g., delete-post, invite-friends)
Example Structure Checklist:
Each example MUST have:
- ✅
meta.jsonwith proper structure:title: Short, descriptive titledescription: Clear explanation of what the example demonstratesargTypes: Interactive controls (optional, only if example needs them)reactLive: REQUIRED - ALL components used must be listed here
- ✅
template.handlebarswith proper format:- Start with single space +
function Example() - NO imports (they're in reactLive)
- NO export statements
- Use Handlebars variables for argTypes:
{{size}},{{variant}} - Can use React hooks (useState, useEffect, etc.)
- Start with single space +
Analyze Existing Examples:
Before creating examples, read similar components to understand patterns:
# Look at accordion examples
src/components/ui/accordion/examples/*/meta.json
src/components/ui/accordion/examples/*/template.handlebars
# Look at button examples
src/components/ui/button/examples/*/meta.json
src/components/ui/button/examples/*/template.handlebars
# Look at modal examples for overlay patterns
src/components/ui/modal/examples/*/meta.json
src/components/ui/modal/examples/*/template.handlebars
Common Example Patterns:
- Stateful examples: Use
React.useStatefor interactive demos - Render props: Show function-as-child patterns like
{({ isExpanded }) => ...} - Variants: Demonstrate different size/variant combinations
- Icons: Show icon integration with
as={IconName}pattern - Composition: Show how to compose with other components (Button, Text, Icon)
- Real scenarios: Show practical use cases users will implement
🔗 Exports & Configuration
Export from
src/components/ui/index.tsx:export * from './[component-name]';Update
src/sidebar.jsonfor docs navigationUpdate
packages/gluestack-ui/src/dependencies.ts(if dependencies needed)
✨ Features Checklist
- Keyboard navigation (Arrow keys, Enter, Escape)
- Screen reader support (ARIA labels)
- Focus management
- Controlled & uncontrolled modes
- Animation support (entrance/exit)
- TypeScript types
- Cross-platform (iOS, Android, Web)
- Dark mode support
- Responsive design
- Parent-child style context
📦 Dependencies
- react-native-reanimated: For animations
- @floating-ui/react-native: For positioning (if overlay)
- [Add others if needed]
🎯 Sub-components
- [ComponentName] (Root) - Main container, context provider
- [SubComponent1] - Description
- [SubComponent2] - Description [... list all sub-components]
🔍 Testing Plan
- Test in kitchen-sink app (iOS, Android, Web)
- Test in website app (documentation)
- Test all variants (size, variant combinations)
- Test keyboard navigation
- Test screen reader
- Test animations
- Test edge cases
**Step 5.2: Present Plan to User**
Show the complete plan and ask:
- Does this implementation plan look complete?
- Any changes or additions needed?
- Any concerns about the approach?
- Ready to proceed with implementation?
**CHECKPOINT 4: Get user confirmation on implementation plan. Use ExitPlanMode to exit plan mode and get approval.**
---
### PHASE 6: IMPLEMENTATION
**IMPORTANT: Only proceed if user approved the plan in Phase 5.**
**Step 6.1: Setup Local Package Development**
**CRITICAL: Never Manually Edit apps/ Directory**
The `apps/` directory contains generated code that is automatically synced from `src/components/ui/`:
- `apps/kitchen-sink/components/ui/` - Auto-generated via mapper
- `apps/website/components/ui/` - Auto-generated via mapper
- `apps/starter-kit-expo/components/ui/` - Auto-generated via mapper (NativeWind v5)
- `apps/starter-kit-expo-uniwind/components/ui/` - Auto-generated via mapper (UniWind)
- `apps/starter-kit-next/components/ui/` - Auto-generated via mapper (NativeWind v4)
- `apps/starter-kit-monorepo/components/ui/` - Auto-generated via mapper (NativeWind v4)
**ONLY edit files in `src/components/ui/[component-name]/`** and changes will propagate automatically when you run `yarn sync`.
```bash
# Link packages for development
yarn link:create
# Link to apps
yarn link:apps
Step 6.2: Implement Core Package
- Create directory structure:
mkdir -p packages/gluestack-core/src/[component-name]/creator
mkdir -p packages/gluestack-core/src/[component-name]/aria # only if ARIA hook needed
- Implement creator function (follow pattern from accordion/creator/index.tsx)
- Implement ARIA hook if needed (follow pattern from accordion/aria/index.tsx)
- CRITICAL: Create barrel export
packages/gluestack-core/src/[component-name]/index.tsx:
export * from './creator';
export * from './creator/types'; // if types exist
export * from './aria'; // if aria exists
- CRITICAL: Update main index
packages/gluestack-core/src/index.tsx:
export * from './[component-name]';
- The
generate-barrel-exports.jsscript will auto-create deep import files during build
Step 6.3: Implement UI Component
CRITICAL REMINDERS for this step:
- ✅ Import from
@gluestack-ui/core/[component-name]/creator(deep import) - ✅ Use the animation library the USER CHOSE (don't substitute!)
- ✅ Use semantic color tokens:
bg-background,text-foreground,border-border, etc. - ✅ Only edit
src/components/ui/- NEVER touchapps/directories
- Create directory:
mkdir -p src/components/ui/[component-name]/docs
mkdir -p src/components/ui/[component-name]/examples/basic
Create
src/components/ui/[component-name]/index.tsxwith compound component:- Import creator using deep path:
@gluestack-ui/core/[component-name]/creator - Import utils from:
@gluestack-ui/utils/nativewind-utils - Use user's chosen animation library (react-native-reanimated or @legendapp/motion)
- Use semantic color tokens in className props
- Import creator using deep path:
Create
src/components/ui/[component-name]/styles.tsxwith tva() styles:- Import tva from:
@gluestack-ui/utils/nativewind-utils - Use only semantic color tokens (bg-background, text-foreground, etc.)
- Support both light and dark modes automatically
- Import tva from:
Create
src/components/ui/[component-name]/dependencies.jsonif external deps neededCreate web-specific
src/components/ui/[component-name]/index.web.tsxif needed
Step 6.4: Create Examples
CRITICAL: Follow exact format used by existing components!
Step 6.4.1: Analyze Existing Examples First
Before creating any examples, read and analyze similar existing components:
- Find similar components:
# Use Glob to find all examples
Glob: "src/components/ui/*/examples/*/meta.json"
Glob: "src/components/ui/*/examples/*/template.handlebars"
Read 3-5 relevant examples from similar components:
- If creating overlay component: Read modal, popover, actionsheet examples
- If creating form component: Read input, checkbox, select examples
- If creating layout component: Read accordion, tabs, card examples
Understand the patterns:
- How do they structure meta.json?
- What components are listed in reactLive?
- How do they format template.handlebars?
- Do they use argTypes? Which ones?
- How do they handle state in examples?
- What Handlebars variables do they use?
Present findings to user:
## Example Pattern Analysis
Based on analyzing [ComponentX], [ComponentY], [ComponentZ]:
### meta.json patterns found:
- All include title, description
- reactLive lists every component used including icons
- argTypes only used when interactive controls needed
- Common argTypes: size (sm/md/lg), variant (default/outline)
### template.handlebars patterns found:
- All start with single space + function Example()
- State management with React.useState
- Handlebars variables: {{size}}, {{variant}}
- Common structure: [pattern description]
### Recommended approach for our component:
1. [Recommendation based on patterns]
2. [Recommendation based on patterns]
Step 6.4.2: Create Examples
For each example (basic, customized, etc.):
- Create example directory:
mkdir -p src/components/ui/[component-name]/examples/basic
mkdir -p src/components/ui/[component-name]/examples/customized-component
# Add more as needed
- Create
meta.jsonfollowing this EXACT format:
{
"title": "Basic Example",
"description": "A basic usage example showing the default behavior of [ComponentName]",
"argTypes": {
"size": {
"control": {
"type": "select"
},
"options": ["sm", "md", "lg"],
"defaultValue": "md"
}
},
"reactLive": {
"[ComponentName]": "@/components/ui/[component-name]",
"[SubComponent1]": "@/components/ui/[component-name]",
"[SubComponent2]": "@/components/ui/[component-name]",
"Button": "@/components/ui/button",
"ButtonText": "@/components/ui/button",
"Text": "@/components/ui/text"
}
}
Notes on meta.json:
title: Short, descriptive titledescription: Clear explanation of what the example demonstratesargTypes: (optional) Interactive controls - only include if example has controllable propsreactLive: REQUIRED - Maps ALL component names used in template to their import paths- Use
@/components/ui/[component-name]format - Include all sub-components from the same component
- Include any external components used (Button, Text, Icon, etc.)
- Use
- Create
template.handlebarsfollowing this EXACT format:
function Example() {
const [isOpen, setIsOpen] = React.useState(false);
return (
<[ComponentName] size="{{size}}">
<[SubComponent1]>
<Text>Content here</Text>
</[SubComponent1]
<[SubComponent2]>
More content
</[SubComponent2]>
</[ComponentName]>
);
}
CRITICAL rules for template.handlebars:
- ✅ Start with a SINGLE SPACE then
function Example() - ✅ NO imports - they come from
reactLivein meta.json - ✅ Use Handlebars variables for argTypes:
{{size}},{{variant}}, etc. - ✅ Return JSX directly (can wrap in
<>...</>if multiple root elements) - ✅ Use React hooks (useState, useEffect, etc.) - React is available globally
- ❌ NO
importstatements - ❌ NO
export default - ❌ NO script tags
Example of a complete working example:
examples/basic/meta.json:
{
"title": "Basic",
"description": "A simple example showing the component in its default state",
"argTypes": {},
"reactLive": {
"Accordion": "@/components/ui/accordion",
"AccordionItem": "@/components/ui/accordion",
"AccordionHeader": "@/components/ui/accordion",
"AccordionTrigger": "@/components/ui/accordion",
"AccordionTitleText": "@/components/ui/accordion",
"AccordionContent": "@/components/ui/accordion",
"AccordionContentText": "@/components/ui/accordion",
"AccordionIcon": "@/components/ui/accordion",
"AddIcon": "@/components/ui/icon",
"RemoveIcon": "@/components/ui/icon"
}
}
examples/basic/template.handlebars:
function Example() {
return (
<Accordion className="w-[90%] m-5">
<AccordionItem value="item-1">
<AccordionHeader>
<AccordionTrigger>
{({ isExpanded }) => (
<>
<AccordionTitleText>
How do I get started?
</AccordionTitleText>
{isExpanded ? (
<AccordionIcon as={RemoveIcon} />
) : (
<AccordionIcon as={AddIcon} />
)}
</>
)}
</AccordionTrigger>
</AccordionHeader>
<AccordionContent>
<AccordionContentText>
To get started, follow our quick start guide.
</AccordionContentText>
</Acco
…(truncated)