eslint-plugin-react-native-design-tokens
v0.1.0
Published
ESLint plugin to enforce design token usage in React Native StyleSheet.create()
Maintainers
Readme
eslint-plugin-react-native-design-tokens
ESLint plugin to enforce design token usage in React Native StyleSheet.create().
Detects hardcoded values for font sizes, colors, spacing, and border radii, and encourages replacing them with design tokens from your design system.
Installation
npm install --save-dev eslint-plugin-react-native-design-tokens
# or
yarn add -D eslint-plugin-react-native-design-tokensUsage
ESLint 8 (legacy config) — .eslintrc.js
module.exports = {
plugins: ['react-native-design-tokens'],
rules: {
'react-native-design-tokens/no-hardcoded-font-size': 'warn',
'react-native-design-tokens/no-hardcoded-color': 'warn',
'react-native-design-tokens/no-hardcoded-spacing': 'warn',
'react-native-design-tokens/no-hardcoded-border-radius': 'warn',
},
};Or use the recommended preset:
module.exports = {
extends: ['plugin:react-native-design-tokens/recommended'],
};ESLint 9 (flat config) — eslint.config.js
const rnDesignTokens = require('eslint-plugin-react-native-design-tokens');
module.exports = [
rnDesignTokens.configs['flat/recommended'],
];Adding custom suggestions
Each rule accepts an optional suggestion string that is appended to the error message, allowing you to point developers to your project's specific tokens:
rules: {
'react-native-design-tokens/no-hardcoded-font-size': ['warn', {
suggestion: 'Use ...theme.text.bodyMedium from src/config/theme',
}],
'react-native-design-tokens/no-hardcoded-color': ['warn', {
suggestion: 'Use theme.color.* from src/config/theme',
}],
'react-native-design-tokens/no-hardcoded-spacing': ['warn', {
suggestion: 'Use theme.spacing() from src/config/theme',
}],
'react-native-design-tokens/no-hardcoded-border-radius': ['warn', {
suggestion: 'Use theme.radius() from src/config/theme',
}],
},Rules
| Rule | Description | Default severity |
|------|-------------|-----------------|
| no-hardcoded-font-size | Disallow hardcoded fontSize in StyleSheet.create() | warn |
| no-hardcoded-color | Disallow hardcoded color literals (hex / named) in StyleSheet.create() | warn |
| no-hardcoded-spacing | Disallow hardcoded margin/padding/gap values in StyleSheet.create() | warn |
| no-hardcoded-border-radius | Disallow hardcoded border-radius values in StyleSheet.create() | warn |
no-hardcoded-font-size
Detects numeric fontSize literals inside StyleSheet.create().
// ✅ Good
StyleSheet.create({ text: { ...tokens.typography.body } });
// ❌ Bad
StyleSheet.create({ text: { fontSize: 14 } });Options
| Option | Type | Description |
|--------|------|-------------|
| suggestion | string | Custom hint appended to the error message |
no-hardcoded-color
Detects hardcoded hex codes (#fff, #FFFFFF, #FFFFFF80) and CSS named colors (white, black, …) in color-related style properties.
Targeted properties: color, backgroundColor, borderColor, borderTopColor, borderRightColor, borderBottomColor, borderLeftColor, borderStartColor, borderEndColor, shadowColor, tintColor, overlayColor, placeholderTextColor, selectionColor, underlineColorAndroid, textDecorationColor, textShadowColor, outlineColor
// ✅ Good
StyleSheet.create({ box: { backgroundColor: tokens.color.surface } });
StyleSheet.create({ box: { color: 'transparent' } }); // allowed by default
// ❌ Bad
StyleSheet.create({ box: { backgroundColor: '#FFFFFF' } });
StyleSheet.create({ box: { color: 'white' } });Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| allowTransparent | boolean | true | Allow 'transparent' as a value |
| suggestion | string | — | Custom hint appended to the error message |
no-hardcoded-spacing
Detects hardcoded positive numeric values in margin, padding, and gap properties.
Targeted properties: margin, marginTop, marginRight, marginBottom, marginLeft, marginHorizontal, marginVertical, marginStart, marginEnd, padding, paddingTop, paddingRight, paddingBottom, paddingLeft, paddingHorizontal, paddingVertical, paddingStart, paddingEnd, gap, columnGap, rowGap
// ✅ Good
StyleSheet.create({ box: { padding: tokens.spacing.md } });
StyleSheet.create({ box: { margin: 0 } }); // 0 is allowed by default
StyleSheet.create({ box: { marginTop: -1 } }); // negatives are allowed by default
// ❌ Bad
StyleSheet.create({ box: { padding: 16 } });
StyleSheet.create({ box: { gap: 8 } });Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| allowedValues | number[] | null (0 and negatives) | Explicit list of allowed values. When set, overrides the default behaviour (0 + negatives) |
| suggestion | string | — | Custom hint appended to the error message |
no-hardcoded-border-radius
Detects hardcoded numeric values in border-radius properties.
Targeted properties: borderRadius, borderTopLeftRadius, borderTopRightRadius, borderBottomLeftRadius, borderBottomRightRadius, borderTopStartRadius, borderTopEndRadius, borderBottomStartRadius, borderBottomEndRadius
// ✅ Good
StyleSheet.create({ card: { borderRadius: tokens.radius.md } });
StyleSheet.create({ card: { borderRadius: 0 } }); // no radius — allowed by default
StyleSheet.create({ pill: { borderRadius: 999 } }); // full circle — allowed by default
// ❌ Bad
StyleSheet.create({ card: { borderRadius: 8 } });
StyleSheet.create({ card: { borderTopLeftRadius: 4 } });Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| allowedValues | number[] | [0, 999] | Values to allow without a token |
| suggestion | string | — | Custom hint appended to the error message |
License
MIT
