ExpoStartup

Chip

A versatile chip component for displaying filters, tags, or selections.

Chip

The Chip component is a compact UI element that can be used for displaying filters, tags, categories, or selection options. It supports multiple sizes, selected states, icons, and images, making it versatile for various UI needs.

Features

  • Selection State: Visual indication of selected/unselected states
  • Multiple Sizes: Six size options from extra small to extra-extra large
  • Icon Support: Can include icons from the Icon component
  • Image Support: Can include small images as visual indicators
  • Custom Content: Accepts custom React elements for the left content
  • Interactive: Optional press handlers and link navigation
  • Customizable: Control for styling and appearance
  • Dark Mode Support: Automatic light/dark mode styles

Import

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

Props

Core Props

PropTypeDefaultDescription
labelstringRequiredThe text displayed in the chip
isSelectedbooleanfalseWhether the chip appears in selected state
onPress() => voidFunction called when the chip is pressed
hrefstringIf provided, chip acts as a navigation link

Styling Props

PropTypeDefaultDescription
size'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl''md'The size of the chip
classNamestringAdditional Tailwind classes for the container
styleViewStyleReact Native style object for the container

Content Props

PropTypeDefaultDescription
iconIconNameIcon to display before the label
iconSizenumberBased on chip sizeCustom size for the icon
iconColorstringBased on selection stateCustom color for the icon
imageImageSourcePropTypeImage to display before the label
imageSizenumberBased on chip sizeCustom size for the image
leftContentReactNodeCustom content to display before the label

Sizes

The size prop affects padding, text size, and default icon/image sizes:

SizePaddingText SizeDefault Icon SizeDefault Image Size
'xs'px-1.5 py-0.5xs12px16px
'sm'px-2 py-0.5xs14px18px
'md'px-3 py-1sm16px20px
'lg'px-4 py-1.5base18px24px
'xl'px-5 py-2lg20px28px
'xxl'px-6 py-2.5xl24px32px

Usage Examples

Basic Chip

<Chip label="Category" />

Selected Chip

<Chip 
  label="Selected" 
  isSelected={true} 
/>

Interactive Chip

<Chip 
  label="Click Me" 
  onPress={() => console.log('Chip pressed')} 
/>
<Chip 
  label="View All" 
  href="/categories" 
/>

Chip with Icon

<Chip 
  label="Settings" 
  icon="settings" 
/>

Chip with Image

<Chip 
  label="Profile" 
  image={require('../assets/profile.png')} 
/>

Custom Sized Chip

<Chip 
  label="Extra Large" 
  size="xl" 
/>

Custom Styled Chip

<Chip 
  label="Custom" 
  className="my-2 mx-1" 
  style={{ elevation: 2 }} 
/>

Filter Selection Example

const [selectedFilters, setSelectedFilters] = useState([]);
 
const toggleFilter = (filter) => {
  if (selectedFilters.includes(filter)) {
    setSelectedFilters(selectedFilters.filter(f => f !== filter));
  } else {
    setSelectedFilters([...selectedFilters, filter]);
  }
};
 
// In your render:
<View className="flex-row flex-wrap">
  {filters.map(filter => (
    <View key={filter} className="m-1">
      <Chip
        label={filter}
        isSelected={selectedFilters.includes(filter)}
        onPress={() => toggleFilter(filter)}
      />
    </View>
  ))}
</View>

Tag List Example

<ScrollView horizontal showsHorizontalScrollIndicator={false}>
  <View className="flex-row p-2">
    {tags.map(tag => (
      <View key={tag.id} className="mr-2">
        <Chip
          label={tag.name}
          icon={tag.icon}
          size="sm"
          href={`/tags/${tag.id}`}
        />
      </View>
    ))}
  </View>
</ScrollView>

Best Practices

Visual Consistency

Maintain consistent size and styling for related chips:

// Good: Consistent size for filter chips
<View className="flex-row flex-wrap">
  <Chip label="All" size="sm" className="m-1" isSelected={filter === 'all'} />
  <Chip label="Recent" size="sm" className="m-1" isSelected={filter === 'recent'} />
  <Chip label="Popular" size="sm" className="m-1" isSelected={filter === 'popular'} />
</View>

Clear Selection States

Ensure selection states are visually distinct:

// The component automatically applies different styles for selected state
<View className="flex-row">
  <Chip label="Option A" isSelected={true} className="mr-2" />
  <Chip label="Option B" isSelected={false} />
</View>

Appropriate Content

Keep chip labels concise and use icons to enhance meaning:

// Good: Short, clear labels with relevant icons
<Chip label="Add" icon="plus" />
<Chip label="Remove" icon="trash" />
 
// Avoid: Long text that might get truncated
<Chip label="This is a very long label that might not fit properly" />

Implementation Details

The Chip component uses React Native's View, Text, TouchableOpacity, and optionally Image components for rendering. When the href prop is provided, it uses Expo Router's Link component for navigation.

For the left content, the component can render an icon (using the Icon component), an image, or custom content provided via the leftContent prop. The component automatically adjusts the size of icons and images based on the chip size, but these can be overridden with the iconSize and imageSize props.

The component supports both light and dark mode through Tailwind classes that apply different styles based on the active theme.

Notes

  • The isSelected prop changes the background color and text color
  • When both href and onPress are provided, href takes precedence
  • When both custom leftContent and icon/image are provided, leftContent takes precedence
  • The chip is automatically wrapped in a TouchableOpacity when either onPress or href is provided
  • If none of onPress or href is provided, the chip will not be interactive