Claude
Skills
Sign in
Back

gluestack-ui-v4:components

Included with Lifetime
$97 forever

Component usage patterns for gluestack-ui v4 - covers component selection, props vs className, compound patterns, icons, and provider setup.

Design

What this skill does


# Gluestack UI v4 - Component Patterns

This sub-skill focuses on component usage, compound component patterns, icon handling, and provider setup for gluestack-ui v4.

## Rule 1: Gluestack Components Over React Native Primitives

Always use Gluestack components instead of direct React Native imports:

| React Native                         | Gluestack Equivalent                           |
| ------------------------------------ | ---------------------------------------------- |
| View from "react-native"             | Box from "@/components/ui/box"                 |
| Text from "react-native"             | Text from "@/components/ui/text"               |
| TouchableOpacity from "react-native" | Pressable from "@/components/ui/pressable"     |
| ScrollView from "react-native"       | ScrollView from "@/components/ui/scroll-view"  |
| Image from "react-native"            | Image from "@/components/ui/image"             |
| TextInput from "react-native"        | Input, InputField from "@/components/ui/input" |
| FlatList from "react-native"         | FlatList from "@/components/ui/flat-list"      |

### Correct Pattern

```tsx
import { Box } from "@/components/ui/box";
import { Text } from "@/components/ui/text";
import { Pressable } from "@/components/ui/pressable";

const Component = () => (
  <Box className="p-4">
    <Text className="text-foreground">Hello</Text>
    <Pressable onPress={handlePress}>
      <Text>Press Me</Text>
    </Pressable>
  </Box>
);
```

### Incorrect Pattern

```tsx
import { View, Text, TouchableOpacity } from "react-native";

const Component = () => (
  <View style={{ padding: 16 }}>
    <Text style={{ color: "#333" }}>Hello</Text>
    <TouchableOpacity onPress={handlePress}>
      <Text>Press Me</Text>
    </TouchableOpacity>
  </View>
);
```

### Exceptions

- Platform-specific code where RN primitives are explicitly required
- Deep integration with native modules
- Performance-critical paths where wrapper overhead matters (rare, must document)

## Rule 2: Use Component Props Over className Utilities

Always prefer component props over className utilities when a component provides built-in props. This ensures type safety, better maintainability, and consistent styling.

### Component Props vs className

Many Gluestack components provide props that map to common styling needs. Use these props instead of className utilities:

| Component | Use Prop Instead of className | Available Values |
|-----------|------------------------------|-----------------|
| `VStack` / `HStack` | `space` instead of `gap-*` | `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl` |
| `Button` | `variant` instead of `bg-*` classes | `default`, `destructive`, `outline`, `secondary`, `ghost`, `link` |
| `Button` | `size` instead of `px-* py-*` classes | `default`, `sm`, `lg`, `icon` |
| `Heading` | `size` instead of `text-*` classes | `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl`, `5xl` |
| `Text` | `size` instead of `text-*` classes | `2xs`, `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl`, `5xl`, `6xl` |
| `Heading` / `Text` | `bold` prop instead of `font-bold` | boolean |
| `Heading` / `Text` | `isTruncated` prop instead of `truncate` | boolean |
| `VStack` / `HStack` | `reversed` prop instead of `flex-*-reverse` | boolean |

### Correct Pattern: Using Component Props

```tsx
// ✅ CORRECT: Using space prop instead of gap className
<VStack space="lg">
  <Box>Item 1</Box>
  <Box>Item 2</Box>
</VStack>

// ✅ CORRECT: Using Button variant and size props
<Button variant="outline" size="lg">
  <ButtonText>Click Me</ButtonText>
</Button>

// ✅ CORRECT: Using Heading size prop
<Heading size="2xl" bold>
  Title
</Heading>

// ✅ CORRECT: Using Text size and bold props
<Text size="sm" bold>
  Important text
</Text>

// ✅ CORRECT: Using HStack space prop
<HStack space="md" className="items-center">
  <Text>Label</Text>
  <Button size="sm">
    <ButtonText>Action</ButtonText>
  </Button>
</HStack>
```

### Incorrect Pattern: Using className Instead of Props

```tsx
// ❌ INCORRECT: Using gap className instead of space prop
<VStack className="gap-4">
  <Box>Item 1</Box>
  <Box>Item 2</Box>
</VStack>

// ❌ INCORRECT: Using className for button styling instead of variant/size props
<Button className="bg-primary px-8 py-2">
  <ButtonText>Click Me</ButtonText>
</Button>

// ❌ INCORRECT: Using text size className instead of size prop
<Heading className="text-2xl font-bold">
  Title
</Heading>

// ❌ INCORRECT: Using className for spacing instead of space prop
<HStack className="gap-2 items-center">
  <Text>Label</Text>
  <Button size="sm">
    <ButtonText>Action</ButtonText>
  </Button>
</HStack>
```

### When to Use className vs Props

**Use Props When:**
- Component provides a built-in prop for the styling (size, variant, space, etc.)
- You want type safety and autocomplete
- The styling is part of the component's design system

**Use className When:**
- Component doesn't provide a prop for the specific styling needed
- You need custom styling not covered by props
- Combining multiple utilities that don't have prop equivalents
- Layout utilities (flex, items-center, justify-between, etc.)

### Combining Props and className

You can combine props with className for additional styling:

```tsx
// ✅ CORRECT: Using space prop + className for additional styling
<VStack space="lg" className="p-4 bg-card rounded-lg">
  <Heading size="xl">Title</Heading>
  <Text size="sm">Description</Text>
</VStack>

// ✅ CORRECT: Using variant prop + className for custom adjustments
<Button variant="outline" size="lg" className="w-full">
  <ButtonText>Full Width Button</ButtonText>
</Button>
```

### Space Prop Mapping

The `space` prop on VStack/HStack maps to standard spacing:

| space prop | Gap Value | Equivalent className |
|------------|-----------|---------------------|
| `xs` | 4px | `gap-1` |
| `sm` | 8px | `gap-2` |
| `md` | 12px | `gap-3` |
| `lg` | 16px | `gap-4` |
| `xl` | 20px | `gap-5` |
| `2xl` | 24px | `gap-6` |
| `3xl` | 28px | `gap-7` |
| `4xl` | 32px | `gap-8` |

### Benefits of Using Props

1. **Type Safety** - TypeScript will catch invalid prop values
2. **Autocomplete** - IDE provides suggestions for valid values
3. **Consistency** - Enforces design system values
4. **Maintainability** - Easier to refactor and update
5. **Documentation** - Props are self-documenting
6. **Performance** - Props are optimized by the component system

## Rule 6: Gluestack Compound Component Pattern

Use Gluestack's composable compound component pattern for complex components. This is **REQUIRED** for proper rendering, styling, and functionality. Compound components provide proper context sharing, styling inheritance, and accessibility.

### Critical Rule: InputIcon MUST Be Wrapped in InputSlot

**ALL InputIcon components MUST be wrapped in InputSlot**, regardless of whether they're on the left or right side of the input. This is required for proper styling, positioning, and interaction handling.

### Input Component Patterns

#### Correct: InputIcon Wrapped in InputSlot (Required)

```tsx
// ✅ CORRECT: Left icon wrapped in InputSlot
<Input>
  <InputSlot>
    <InputIcon as={MailIcon} className="text-muted-foreground" />
  </InputSlot>
  <InputField placeholder="Enter email" />
</Input>

// ✅ CORRECT: Right icon (interactive) wrapped in InputSlot
<Input>
  <InputField placeholder="Enter password" secureTextEntry={!showPassword} />
  <InputSlot onPress={() => setShowPassword(!showPassword)}>
    <InputIcon as={showPassword ? EyeOffIcon : EyeIcon} className="text-muted-foreground" />
  </InputSlot>
</Input>

// ✅ CORRECT: Both left and right icons wrapped in InputSlot
<Input>
  <InputSlot>
    <InputIcon as={SearchIcon} className="text-muted-foreground" />
  </InputSlot>
  <InputField placeholder="Search..." />
  <InputSlot onPress={handleClear}>
    <InputIcon as={XIcon} className="text-muted-foreground" />
  </InputSlot>
</Input>
```

#### Incorrect: InputIcon Used Directly (Will Brea

Related in Design