react-native-reusables
react-native-reusables copied to clipboard
[ FEATURE ] Automate Lucide Icon additions
Is your feature request related to a problem? Please describe.
To remove a bit of the leg work of adding a new icon it would nice if part of the CLI was essentially a helper that takes the Icon name and creates the necessary lib/icons/*.ts file with the wrapped export.
Describe the solution you'd like
Add a new icon command alongside add which takes Lucid icon names as an argument and creates the necessary .ts file.
Describe alternatives you've considered Currently using a script like this to automate the creation
#!/bin/bash
if [ -z "$1" ]; then
echo "Usage: addIcon.sh <iconName>"
exit 1
fi
iconName=$1
# Create the new icon file under `lib/icons`
iconPath="src/lib/icons/${iconName}.ts"
touch $iconPath
# Write the icon content
echo "import {${iconName}} from 'lucide-react-native';" >> $iconPath
echo "import {iconWithClassName} from './iconWithClassName';" >> $iconPath
echo "iconWithClassName(${iconName});" >> $iconPath
echo "export {${iconName}};" >> $iconPath
Additional context I've always been interested in creating a node based CLI script and would be happy to tackle this addition if that would be OK.
This would be great! I am also having some troubles with auto imports from the icon exports, have you had any issues with that?
Check this out https://github.com/mrzachnugent/react-native-reusables/issues/198, replace lucide with iconify and only one export needed. Iconify includes lucide and so much more https://icon-sets.iconify.design/
I am open to this. It will need to be another command than "add" since there are some conflicts between the components and the lucide-icon names.
another suggestion: instead of creating separate files for each icons, create a single icons.tsx and increment the icons there. For example:
import {
Home,
Library,
UserPlus,
Layers,
ListPlus,
} from 'lucide-react-native';
import { iconWithClassName } from './iconWithClassName';
iconWithClassName(Home);
iconWithClassName(Library);
iconWithClassName(UserPlus);
iconWithClassName(Layers);
iconWithClassName(ListPlus);
export {
Home,
Library,
UserPlus,
Layers,
ListPlus,
};
after that just import { Home, Layers} from '../../lib/icons/icons';
This way the codebase will remain neat.
@helix-77 That's how it was at first, the problem I faced was with the CLI when adding icons. It would need to parse the file to see if the icon is already there, add text in 3 places, and if the user manually changed something it could stop working so it was easier to add a file for each icon.
React-native-reusables is meant as a quick start for your projects and it is encouraged that you make any changes you need. So, by all means, modify your the icons in your codebase to look like your suggestion.
We can maybe utilise component.json here by adding an 'icons' field and then on each run we can just check that key and regenerate whole file without needing to parse it.
I am open to this. It will need to be another command than "add" since there are some conflicts between the components and the lucide-icon names.
sorry for falling off the deep end @mrzachnugent. I'm still interested in tackling this and I'll start working something up.
I have gone with a different approach and it's working fine to me
I create a component named lucide-icon.tsx that allows me to use any lucide icon like <LucideIcon name="Check" className="size-4 text-accent-foreground" />
Notice that the name prop does have type safety
import { icons } from 'lucide-react-native';
import { iconWithClassName } from './iconWithClassName';
const LucideIcon = ({
name,
size,
strokeWidth = 2,
className,
}: {
name: keyof typeof icons;
size?: number;
strokeWidth?: number;
className?: string;
}) => {
const Icon = icons[name];
iconWithClassName(Icon);
return <Icon size={size} strokeWidth={strokeWidth} className={className} />;
};
export { LucideIcon };
If using the generic approach, please take this warning into consideration: https://lucide.dev/guide/packages/lucide-react-native#one-generic-icon-component
I would also suggest rapping the LucideIcon with the iconWithClassName function. In the snippet above, the iconWithClassName function is called every time the component renders.
On another note, to fix allowing the icons to receive a class name, I've been thinking about adding a patch-package but haven't looked into it. That way, we could import directly from 'lucide-react-native' and we could get ride of the /icons folder.
What do you mean by
I would also suggest rapping the LucideIcon with the iconWithClassName function. In the snippet above, the iconWithClassName function is called every time the component renders.
Tried it and didn't worked. I couldn't find any other way to do it besides the one that I commented.
And when I read #341 found that it can be way harder than I tough. What do you suggets for now?
Fwiw, here's a turbo generator for adding these icons:
// turbo/generators/config.ts
import type { PlopTypes } from '@turbo/gen'
export default function generator(plop: PlopTypes.NodePlopAPI): void {
plop.setGenerator('icon', {
description: 'Create a new icon component from Lucide icons',
prompts: [
{
type: 'input',
name: 'name',
message: 'What is the name of your icon? (must match Lucide icon name)',
validate: (input: string) => {
if (input.length === 0) {
return 'Icon name is required'
}
return true
},
},
],
actions: [
{
type: 'add',
path: '{{ turbo.paths.root }}/packages/ui/src//lib/icons/{{pascalCase name}}.tsx',
templateFile: 'templates/icon.tsx.hbs',
},
{
type: 'append',
path: '{{ turbo.paths.root }}/packages/ui/src/primitives/lib/icons/index.ts',
pattern: /$/,
template: "export * from './{{pascalCase name}}'\n",
},
],
})
}
{{!-- turbo/generators/templates/icon.tsx.hbs --}}
import { {{pascalCase name}} } from 'lucide-react-native'
import { iconWithClassName } from './iconWithClassName'
iconWithClassName({{pascalCase name}})
export { {{pascalCase name}} }
Instead of automation, there is now a single Icon component : https://github.com/founded-labs/react-native-reusables/blob/main/packages/registry/src/new-york/components/ui/icon.tsx