react-native-football-formation
v1.0.11
Published
A highly customizable React Native component for displaying football/soccer team formations with player positions and match statistics
Maintainers
Keywords
Readme
React Native Football Formation
A highly customizable React Native component for displaying football/soccer team formations with player positions, stats, and match information.
Demo
Why This Package?
Building football/soccer formation displays from scratch is time-consuming and complex. This package provides:
- Production-Ready: Built for real-world sports apps, fantasy football platforms, and tactical analysis tools
- Zero Dependencies: Lightweight with no external dependencies beyond React Native core
- Battle-Tested: Supports all 24 major tactical formations used in professional football
- Developer-Friendly: Extensive TypeScript support, comprehensive documentation, and intuitive API
- Fully Customizable: Every visual aspect can be themed or completely overridden
Perfect for sports apps, match analysis tools, fantasy football platforms, coaching applications, and tactical planning software.
Features
✅ 24 Supported Formations - All major tactical formations (4-3-3, 4-2-3-1, 3-5-2, etc.) ✅ Player Statistics - Goals, assists, cards, substitutions, own goals ✅ Highly Customizable - Theme system for colors, fonts, spacing ✅ RTL Support - Built-in support for right-to-left languages ✅ TypeScript - Full type safety and IntelliSense ✅ Expo & Bare RN - Compatible with both Expo and bare React Native projects ✅ Asset Override - Use your own field backgrounds and icons ✅ Component Override - Custom rendering for player cards and footer ✅ Responsive - Adapts to different screen sizes
Installation
npm install react-native-football-formationor
yarn add react-native-football-formationQuick Start
import { FormationField } from 'react-native-football-formation';
function App() {
const lineup = {
players: [/* player data */],
formationUsed: '433',
};
return <FormationField lineup={lineup} />;
}Basic Usage
Simple Example
import React from 'react';
import { FormationField } from 'react-native-football-formation';
export default function FormationScreen() {
const teamLineup = {
players: [
{
playerId: '1',
matchName: 'De Gea',
shirtNumber: 1,
rating: '7.5',
position: 'Goalkeeper',
formationPlace: '1',
stats: [],
},
// ... 10 more players
],
formationUsed: '433',
};
return (
<FormationField
lineup={teamLineup}
getPlayerPhotoUrl={(playerId) =>
`https://example.com/players/${playerId}.png`
}
/>
);
}Complete Player Object Example
Here's a complete player object showing all available fields and stats:
const teamLineup = {
players: [
// Example 1: Player with all stats
{
playerId: "5il4uc7d941ndwjl0qu97y7dh",
matchName: "Marcelo Grohe",
shirtNumber: 43,
rating: "7.2",
position: "Goalkeeper",
positionSide: "Centre",
formationPlace: "1",
stats: [
{ type: "totalSubOff", value: "1" },
{ type: "goals", value: 1 },
{ type: "yellowCard", value: "1" },
{ type: "redCard", value: "1" },
{ type: "goalAssist", value: "0" },
{ type: "ownGoals", value: "1" }
]
},
// Example 2: Player with stats array containing null values
{
playerId: "abc123",
matchName: "Lionel Messi",
shirtNumber: 10,
rating: "9.5",
position: "Forward",
positionSide: "Right",
formationPlace: "10",
stats: [
{ type: "goals", value: 2 },
null,
{ type: "goalAssist", value: "1" },
null,
{ type: "yellowCard", value: "0" }
]
},
// ... 9 more players with formationPlace "2" to "9", "11"
],
formationUsed: "433" // or "4-3-3"
};
<FormationField
lineup={teamLineup}
getPlayerPhotoUrl={(playerId) =>
`https://example.com/players/${playerId}.png`
}
/>Note: The stats array can contain both PlayerStats objects and null values. Null values are safely ignored.
With Custom Theme
<FormationField
lineup={teamLineup}
theme={{
colors: {
primary: '#FF0000',
playerName: '#FFFFFF',
success: '#00FF00',
warning: '#FFAA00',
},
typography: {
fontFamily: 'MyCustomFont-Regular',
fontFamilyBold: 'MyCustomFont-Bold',
},
}}
/>With Player Interaction
<FormationField
lineup={teamLineup}
onPlayerPress={(player) => {
console.log('Player tapped:', player.matchName);
// Navigate to player details or show modal
}}
/>With Custom Assets
<FormationField
lineup={teamLineup}
fieldImage={require('./assets/custom-field.png')}
footballIcon={require('./assets/custom-goal-icon.png')}
playerPlaceholder={require('./assets/custom-placeholder.png')}
/>API Reference
FormationField Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| lineup | TeamLineup | required | Team lineup data with players and formation |
| width | number | screenWidth + 10 | Field width |
| height | number | 395 | Field height |
| theme | Partial<FormationTheme> | defaultTheme | Theme customization |
| fieldImage | ImageSourcePropType | default field | Background field image |
| playerPlaceholder | ImageSourcePropType | default avatar | Placeholder for missing player photos |
| footballIcon | ImageSourcePropType | default icon | Icon for goals |
| kickerIcon | ImageSourcePropType | default icon | Icon for assists |
| renewalIcon | ImageSourcePropType | default icon | Icon for substitutions |
| ownGoalIcon | ImageSourcePropType | default icon | Icon for own goals |
| logoImage | ImageSourcePropType | undefined | Optional logo to display |
| renderPlayerCard | (player, width, height) => ReactNode | undefined | Custom player card renderer |
| renderFooter | (formation) => ReactNode | undefined | Custom footer renderer |
| onPlayerPress | (player) => void | undefined | Player tap callback |
| showLogo | boolean | false | Show/hide logo |
| showFormation | boolean | true | Show/hide formation badge |
| showRating | boolean | false | Show/hide player ratings |
| containerStyle | ViewStyle | undefined | Container style override |
| playerCardStyle | ViewStyle | undefined | Player card style override |
| playerNameStyle | TextStyle | undefined | Player name text style override |
| getPlayerPhotoUrl | (playerId: string) => string | undefined | Function to generate player photo URLs |
TeamLineup Type
interface TeamLineup {
players: Player[];
formationUsed: string; // e.g., "433", "4231", "352"
}
interface Player {
rating: string;
playerId: string;
position: string;
matchName: string;
shirtNumber: number;
formationPlace?: string; // "1" to "11"
stats: (PlayerStats | null)[]; // Array can contain PlayerStats objects or null values
}
interface PlayerStats {
type: 'goals' | 'yellowCard' | 'redCard' | 'goalAssist' | 'totalSubOff' | 'ownGoals';
value: string | number;
}FormationTheme Type
interface FormationTheme {
colors: {
primary: string;
blue: string;
white: string;
text: string;
playerName: string;
border: string;
warning: string;
success: string;
error: string;
newError: string;
formationBadge: string;
};
spacing: {
playerCardWidth: number;
playerCardHeight: number;
playerImageSize: number;
jerseyNumberSize: number;
iconSize: number;
badgeMinWidth: number;
badgeHeight: number;
};
typography: {
playerNameSize: number;
formationSize: number;
jerseyNumberSize: number;
goalCountSize: number;
fontFamily?: string;
fontFamilyBold?: string;
};
borderRadius: {
playerImage: number;
badge: number;
card: number;
};
}Supported Formations
The component supports 24 different tactical formations:
4-Back Formations
4-4-2- Classic 4-4-24-3-3- 4-3-34-2-3-1- 4-2-3-1 (most common modern formation)4-1-2-1-2- 4-1-2-1-2 Diamond4-5-1- 4-5-14-4-1-1- 4-4-1-14-1-4-1- 4-1-4-14-3-2-1- 4-3-2-1 Christmas Tree4-2-2-2- 4-2-2-24-1-3-2- 4-1-3-24-2-4-0- 4-2-4-0 False 94-3-1-2- 4-3-1-2
5-Back Formations
5-3-2- 5-3-25-4-1- 5-4-1
3-Back Formations
3-5-2- 3-5-23-4-3- 3-4-33-5-1-1- 3-5-1-13-4-2-1- 3-4-2-13-4-1-2- 3-4-1-23-1-4-2- 3-1-4-23-4-3d- 3-4-3 Diamond3-2-4-1- 3-2-4-13-3-3-1- 3-3-3-1
Advanced Usage
Custom Player Card Renderer
<FormationField
lineup={teamLineup}
renderPlayerCard={(player, fieldWidth, fieldHeight) => (
<CustomPlayerCard
player={player}
width={fieldWidth}
height={fieldHeight}
onPress={() => navigateToPlayerDetails(player)}
/>
)}
/>Custom Footer
<FormationField
lineup={teamLineup}
renderFooter={(formation) => (
<View style={styles.customFooter}>
<Text>Formation: {formation}</Text>
<Text>Tactical Analysis</Text>
</View>
)}
/>Full Customization Example
<FormationField
lineup={teamLineup}
width={400}
height={500}
theme={{
colors: {
primary: '#0066CC',
success: '#28A745',
warning: '#FFC107',
error: '#DC3545',
text: '#000000',
white: '#FFFFFF',
formationBadge: '#2C3E50',
},
typography: {
fontFamily: 'Roboto-Regular',
fontFamilyBold: 'Roboto-Bold',
playerNameSize: 14,
formationSize: 16,
},
spacing: {
playerCardWidth: 80,
playerCardHeight: 60,
playerImageSize: 50,
},
}}
fieldImage={require('./assets/grass-field.png')}
onPlayerPress={(player) => console.log(player)}
showFormation={true}
showLogo={false}
getPlayerPhotoUrl={(playerId) =>
`https://cdn.example.com/players/${playerId}.png`
}
/>Player Statistics
The component automatically displays player statistics when available. The stats array can contain PlayerStats objects or null values.
Supported Stat Types
| Stat Type | Display | Description |
|-----------|---------|-------------|
| goals | ⚽ Football icon + count | Number of goals scored |
| goalAssist | 👟 Kicker icon | Number of assists provided |
| yellowCard | 🟨 Yellow card | Yellow card received |
| redCard | 🟥 Red card | Red card received |
| totalSubOff | 🔄 Substitution icon | Player was substituted off |
| ownGoals | ⚽🔴 Own goal icon + count | Number of own goals |
Example Player Stats
The stats array can contain both stat objects and null values:
{
playerId: '1',
matchName: 'Cristiano Ronaldo',
shirtNumber: 7,
formationPlace: '9',
stats: [
{ type: 'goals', value: 1 }, // Scored 1 goal
{ type: 'yellowCard', value: '1' }, // Received yellow card
{ type: 'goalAssist', value: '0' }, // No assists (won't display)
{ type: 'redCard', value: '1' }, // Received red card
{ type: 'totalSubOff', value: '1' }, // Was substituted
{ type: 'ownGoals', value: '1' }, // Scored own goal
null, // Null values are safely handled
]
}Note:
- Values can be either
stringornumbertypes - Stats with a value of
'0'or0won't be displayed - The
statsarray safely handlesnullentries - If
statsis empty or all values arenull, no stats will be displayed
Utilities
The package exports utility functions for advanced use cases:
import {
transformLineupByFormationPlace,
hasStat,
getStatValue,
FORMATION_COORDINATES_BY_PLACE,
} from 'react-native-football-formation';
// Transform raw lineup data
const positionedPlayers = transformLineupByFormationPlace(
teamLineup,
'4-3-3',
(playerId) => `https://example.com/${playerId}.png`
);
// Check if player has a stat
const hasGoals = hasStat(player.stats, 'goals');
// Get stat value
const goalCount = getStatValue(player.stats, 'goals');
// Access formation coordinates
const coords = FORMATION_COORDINATES_BY_PLACE['4-3-3']['1']; // GK positionTypeScript Support
The package is written in TypeScript and includes full type definitions. Import types for better development experience:
import type {
TeamLineup,
Player,
PlayerStats,
PlayerStatType,
LineupFormationPlayer,
FormationTheme,
FormationFieldProps,
} from 'react-native-football-formation';Troubleshooting
Images not loading
Make sure you've provided either:
- Player photo URLs via the
photofield in player data, OR - A
getPlayerPhotoUrlfunction prop
<FormationField
lineup={teamLineup}
getPlayerPhotoUrl={(playerId) =>
`https://your-cdn.com/players/${playerId}.png`
}
/>Formation not displaying correctly
Ensure the formationUsed field matches one of the supported formations (without dashes):
- ✅
"433"or"4-3-3" - ❌
"4-3-3-1"(not supported)
The component automatically handles both formats ("433" and "4-3-3").
Players in wrong positions
Check that each player has a valid formationPlace field from "1" to "11":
- Position 1 is always the goalkeeper
- Positions 2-11 depend on the formation
Examples
See the /examples directory for complete working examples:
- basic/ - Simple formation display
- custom-styling/ - Custom theme and styling
- custom-assets/ - Custom images and icons
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support & Community
- GitHub Issues - Report bugs or request features
- GitHub Discussions - Ask questions and share ideas
- Changelog - See what's new in each release
If you find this package helpful, please consider giving it a star on GitHub!
License
MIT © Arbab Rafiq
Author
Arbab Rafiq
- GitHub: @arbab-io
- Package: react-native-football-formation
Acknowledgments
- Inspired by modern football tactical analysis tools
- Built for the React Native community
- Thanks to all contributors
Made with ⚽ for football fans and developers
