Skip to main content
While Eva Icons work great with UI Kitten, you may want to use other icon libraries like Material Icons, FontAwesome, or Feather Icons. This guide shows you how to integrate any icon package with UI Kitten.

Icon Adapter Pattern

UI Kitten uses an adapter pattern to support any icon library. You create an icon pack object that UI Kitten can use to render icons by name.

Adapter Structure

An icon pack consists of:
export const CustomIconsPack = {
  name: 'custom',  // Unique identifier
  icons: {         // Icon mapping
    'icon-name': IconProvider('icon-name'),
    // ...
  },
};
The IconProvider returns an object with a toReactElement method that renders the icon.

Vector Icons Integration

Let’s integrate react-native-vector-icons, a popular icon library.

Installation

Install the package:
npm install react-native-vector-icons
Follow the official installation guide to complete platform-specific setup.

Create Feather Icons Adapter

Create a feather-icons.js file:
import React from 'react';
import { StyleSheet } from 'react-native';
import Icon from 'react-native-vector-icons/Feather';

export const FeatherIconsPack = {
  name: 'feather',
  icons: createIconsMap(),
};

function createIconsMap() {
  return new Proxy({}, {
    get(target, name) {
      return IconProvider(name);
    },
  });
}

const IconProvider = (name) => ({
  toReactElement: (props) => FeatherIcon({ name, ...props }),
});

function FeatherIcon({ name, style }) {
  const { height, tintColor, ...iconStyle } = StyleSheet.flatten(style);
  return (
    <Icon name={name} size={height} color={tintColor} style={iconStyle} />
  );
}
The Proxy object dynamically creates icon providers for any requested icon name, eliminating the need to manually map every icon.

Register Custom Icons

Register your custom icon pack:
import React from 'react';
import * as eva from '@eva-design/eva';
import { ApplicationProvider, IconRegistry, Layout, Text } from '@ui-kitten/components';
import { FeatherIconsPack } from './feather-icons';

const HomeScreen = () => (
  <Layout style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
    <Text category='h1'>HOME</Text>
  </Layout>
);

export default () => (
  <>
    <IconRegistry icons={FeatherIconsPack} />
    <ApplicationProvider {...eva} theme={eva.light}>
      <HomeScreen />
    </ApplicationProvider>
  </>
);

Usage

Use Feather Icons with UI Kitten components:
import React from 'react';
import { Button, Icon } from '@ui-kitten/components';

const FacebookIcon = (props) => (
  <Icon {...props} name='facebook' />
);

export const LoginButton = () => (
  <Button accessoryLeft={FacebookIcon}>
    Login with Facebook
  </Button>
);

Multiple Icon Packs

Register multiple icon packages to use different icon libraries in your app.

Create Material Icons Adapter

Create a material-icons.js file:
import React from 'react';
import { StyleSheet } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';

export const MaterialIconsPack = {
  name: 'material',
  icons: createIconsMap(),
};

function createIconsMap() {
  return new Proxy({}, {
    get(target, name) {
      return IconProvider(name);
    },
  });
}

const IconProvider = (name) => ({
  toReactElement: (props) => MaterialIcon({ name, ...props }),
});

function MaterialIcon({ name, style }) {
  const { height, tintColor, ...iconStyle } = StyleSheet.flatten(style);
  return (
    <Icon name={name} size={height} color={tintColor} style={iconStyle} />
  );
}

Register Multiple Packs

Pass an array of icon packs to IconRegistry:
import React from 'react';
import * as eva from '@eva-design/eva';
import { ApplicationProvider, IconRegistry, Layout, Text } from '@ui-kitten/components';
import { EvaIconsPack } from '@ui-kitten/eva-icons';
import { FeatherIconsPack } from './feather-icons';
import { MaterialIconsPack } from './material-icons';

const HomeScreen = () => (
  <Layout style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
    <Text category='h1'>HOME</Text>
  </Layout>
);

export default () => (
  <>
    <IconRegistry icons={[EvaIconsPack, FeatherIconsPack, MaterialIconsPack]} />
    <ApplicationProvider {...eva} theme={eva.light}>
      <HomeScreen />
    </ApplicationProvider>
  </>
);

Select Icon Pack

Use the pack prop to choose which icon library to use:
import React from 'react';
import { Button, Icon } from '@ui-kitten/components';

// Eva Icons (default)
const HeartIcon = (props) => (
  <Icon {...props} name='heart-outline' />
);

// Material Icons
const HomeIcon = (props) => (
  <Icon {...props} name='home' pack='material' />
);

// Feather Icons
const SearchIcon = (props) => (
  <Icon {...props} name='search' pack='feather' />
);

export const MultiPackButtons = () => (
  <>
    <Button accessoryLeft={HeartIcon}>Eva</Button>
    <Button accessoryLeft={HomeIcon}>Material</Button>
    <Button accessoryLeft={SearchIcon}>Feather</Button>
  </>
);
If you don’t specify a pack prop, UI Kitten uses the first registered icon pack.

Asset Icons

You can also create an icon pack from image assets.

Create Asset Icons Pack

Create an asset-icons.js file:
import React from 'react';
import { Image } from 'react-native';

const IconProvider = (source) => ({
  toReactElement: ({ animation, ...props }) => (
    <Image {...props} source={source} />
  ),
});

export const AssetIconsPack = {
  name: 'assets',
  icons: {
    'github': IconProvider(require('../assets/images/github.png')),
    'gitlab': IconProvider(require('../assets/images/gitlab.png')),
    'bitbucket': IconProvider(require('../assets/images/bitbucket.png')),
    'color-palette': IconProvider(require('../assets/images/color-palette.png')),
  },
};

Register Asset Icons

import React from 'react';
import * as eva from '@eva-design/eva';
import { ApplicationProvider, IconRegistry } from '@ui-kitten/components';
import { EvaIconsPack } from '@ui-kitten/eva-icons';
import { AssetIconsPack } from './asset-icons';

export default () => (
  <>
    <IconRegistry icons={[EvaIconsPack, AssetIconsPack]} />
    <ApplicationProvider {...eva} theme={eva.light}>
      {/* Your app */}
    </ApplicationProvider>
  </>
);

Use Asset Icons

import React from 'react';
import { Button, Icon } from '@ui-kitten/components';

const GithubIcon = (props) => (
  <Icon {...props} name='github' pack='assets' />
);

export const GithubButton = () => (
  <Button accessoryLeft={GithubIcon}>
    View on GitHub
  </Button>
);

FontAwesome Integration

Integrate FontAwesome icons with UI Kitten:
import React from 'react';
import { StyleSheet } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome5';

export const FontAwesomeIconsPack = {
  name: 'font-awesome',
  icons: createIconsMap(),
};

function createIconsMap() {
  return new Proxy({}, {
    get(target, name) {
      return IconProvider(name);
    },
  });
}

const IconProvider = (name) => ({
  toReactElement: (props) => FontAwesomeIcon({ name, ...props }),
});

function FontAwesomeIcon({ name, style }) {
  const { height, tintColor, ...iconStyle } = StyleSheet.flatten(style);
  return (
    <Icon
      name={name}
      size={height}
      color={tintColor}
      style={iconStyle}
      solid  // Use solid variant by default
    />
  );
}

Custom SVG Icons

Integrate custom SVG icons using react-native-svg:
import React from 'react';
import { Svg, Path } from 'react-native-svg';

// Define your custom SVG icons
const CustomIcon = ({ width, height, fill }) => (
  <Svg width={width} height={height} viewBox="0 0 24 24">
    <Path
      fill={fill}
      d="M12 2L2 7v10c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V7l-10-5z"
    />
  </Svg>
);

const IconProvider = (Component) => ({
  toReactElement: ({ style, ...props }) => {
    const { height, tintColor } = StyleSheet.flatten(style);
    return (
      <Component
        {...props}
        width={height}
        height={height}
        fill={tintColor}
      />
    );
  },
});

export const CustomSvgIconsPack = {
  name: 'custom-svg',
  icons: {
    'shield': IconProvider(CustomIcon),
    // Add more custom icons
  },
};

Icon Pack Best Practices

Use a Proxy object instead of manually mapping every icon when working with large icon libraries like Material Icons (1000+ icons).
Ensure your icon adapter respects the height property from the style prop to maintain consistent sizing across all icon packs.
Extract tintColor from the style prop and pass it as the color property to ensure icons can be themed properly.
Consider adding fallback icons or error handling for missing icon names:
function FeatherIcon({ name, style }) {
  const { height, tintColor, ...iconStyle } = StyleSheet.flatten(style);
  
  // Check if icon exists
  const iconExists = Icon.hasIcon(name);
  
  return (
    <Icon
      name={iconExists ? name : 'alert-circle'}
      size={height}
      color={tintColor}
      style={iconStyle}
    />
  );
}
Keep a list of available icons in your asset icon packs to help developers know what’s available.

TypeScript Support

Add type safety for your custom icon packs:
import { IconPack } from '@ui-kitten/components';

type FeatherIconNames = 'facebook' | 'twitter' | 'instagram' | 'github';

export const FeatherIconsPack: IconPack<FeatherIconNames> = {
  name: 'feather',
  icons: createIconsMap(),
};

// Usage with type checking
const MyIcon = (props) => (
  <Icon<FeatherIconNames> {...props} name='facebook' pack='feather' />
);

Troubleshooting

  • Verify the icon library is properly installed and linked
  • Check that the icon name exists in the library
  • Ensure IconRegistry is placed before ApplicationProvider
  • Confirm the pack prop matches the registered pack name
Make sure your adapter extracts tintColor from the style prop and passes it to the underlying icon component:
const { height, tintColor } = StyleSheet.flatten(style);
return <Icon size={height} color={tintColor} />;
Extract the height property from the style and use it for both width and height to maintain aspect ratio:
const { height } = StyleSheet.flatten(style);
return <Icon width={height} height={height} />;
  • Use the Proxy pattern instead of creating individual icon providers
  • Memoize icon components with React.memo()
  • Consider lazy loading icon packs for large applications

Example: Complete Setup

Here’s a complete example with multiple icon packs:
// App.tsx
import React from 'react';
import * as eva from '@eva-design/eva';
import { ApplicationProvider, IconRegistry } from '@ui-kitten/components';
import { EvaIconsPack } from '@ui-kitten/eva-icons';
import { FeatherIconsPack } from './icon-packs/feather-icons';
import { MaterialIconsPack } from './icon-packs/material-icons';
import { AssetIconsPack } from './icon-packs/asset-icons';
import { AppNavigator } from './navigation';

export default () => (
  <>
    <IconRegistry icons={[
      EvaIconsPack,
      FeatherIconsPack,
      MaterialIconsPack,
      AssetIconsPack,
    ]} />
    <ApplicationProvider {...eva} theme={eva.light}>
      <AppNavigator />
    </ApplicationProvider>
  </>
);

Next Steps

Configure Navigation

Set up navigation with custom icon-based tab bars

Theming

Learn how icons adapt to your app’s theme

Build docs developers (and LLMs) love