Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(icon-component): Creating icons with iconNodes #1997

Merged
merged 36 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
69f86e3
Add useIconComponent, lucide-react
ericfennis Jan 23, 2024
a1a9126
Add concept useIconComponent
ericfennis Jan 23, 2024
76ff2d5
add useIconComponents to packages
ericfennis Jan 28, 2024
8d15710
Merge branch 'main' of https://github.com/lucide-icons/lucide into us…
ericfennis Mar 8, 2024
736a6cd
Add icon component
ericfennis Mar 8, 2024
7aeba3b
Merge branch 'main' of https://github.com/lucide-icons/lucide into us…
ericfennis Mar 15, 2024
4b67599
Add icon component
ericfennis Mar 15, 2024
c56e29d
Add tests for react packages
ericfennis Mar 18, 2024
00de13c
Reset changes in icons
ericfennis Mar 18, 2024
941968d
Merge branch 'main' into use-icon-component
ericfennis Mar 18, 2024
b9e0864
Add types
ericfennis Mar 18, 2024
12188fa
Merge branch 'use-icon-component' of https://github.com/ericfennis/lu…
ericfennis Mar 18, 2024
40b30e0
Add support for Icon components in Lucide Vue Next
ericfennis Mar 22, 2024
57e8edc
update tests
ericfennis Mar 22, 2024
6a9bd80
Update tests
ericfennis Mar 22, 2024
34e647d
Enable Svelte component
ericfennis Mar 22, 2024
d153bea
Fix lucide-react-native tests
ericfennis Mar 22, 2024
4fbc764
Update Solid package
ericfennis Mar 22, 2024
7b83711
update snapshots
ericfennis Mar 22, 2024
2320393
Add docs
ericfennis Apr 1, 2024
adc4d47
add docs
ericfennis Apr 1, 2024
23710e4
Update tests
ericfennis Apr 1, 2024
292a619
Merge branch 'main' into use-icon-component
ericfennis Apr 1, 2024
78c5bd2
Formatting
ericfennis Apr 1, 2024
30ee113
Formatting
ericfennis Apr 1, 2024
4ae0d4b
Update package lock
ericfennis Apr 1, 2024
2a792b8
Remove `useIconComponent`
ericfennis Apr 5, 2024
c386c28
Merge branch 'main' of https://github.com/lucide-icons/lucide into us…
ericfennis Apr 5, 2024
a0f3b8a
Update guides
ericfennis Apr 5, 2024
02b284e
Update exports preact and solid package
ericfennis Apr 26, 2024
4a6d83d
Merge branch 'main' of https://github.com/lucide-icons/lucide into us…
ericfennis Apr 26, 2024
3492e6d
Formatting
ericfennis Apr 26, 2024
663002b
Merge branch 'main' into use-icon-component
ericfennis Apr 26, 2024
b7a8f1e
Format createIcons.ts
ericfennis Apr 26, 2024
1c5a06d
Add lucide lab repo link in docs
ericfennis Apr 26, 2024
0e9854e
Merge branch 'main' into use-icon-component
ericfennis Apr 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ pnpm-lock.yaml

# docs examples
docs/**/examples/
docs/.vitepress/.temp
docs/.vitepress/cache
docs/.vitepress/data
docs/.nitro

# lucide-angular
packages/lucide-angular/.angular/cache
Expand Down
17 changes: 17 additions & 0 deletions docs/guide/packages/lucide-angular.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,20 @@ import { icons } from 'lucide-angular';

LucideAngularModule.pick(icons)
```

## With Lucide lab or custom icons

[Lucide lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.
They can be used in the same way as the official icons.

```js
import { LucideAngularModule } from 'lucide-angular';
import { burger } from '@lucide/lab';

@NgModule({
imports: [
LucideAngularModule.pick({ burger })
]
})
export class AppModule { }
```
20 changes: 20 additions & 0 deletions docs/guide/packages/lucide-preact.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,26 @@ const App = () => {

> SVG attributes in Preact aren't transformed, so if you want to change for example the `stroke-linejoin` you need to pass it in kebabcase. Basically how the SVG spec want you to write it. See this topic in the [Preact documentation](https://preactjs.com/guide/v10/differences-to-react/#svg-inside-jsx).

## With Lucide lab or custom icons

[Lucide lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.

They can be used by using the `Icon` component.
All props like regular lucide icons can be passed to adjust the icon appearance.

### Using the `Icon` component

This creates a single icon based on the iconNode passed and renders a Lucide icon component.

```jsx
import { Icon } from 'lucide-preact';
import { burger } from '@lucide/lab';

const App = () => (
<Icon iconNode={burger} />
);
```

## One generic icon component

It is possible to create one generic icon component to load icons, but it is not recommended.
Expand Down
20 changes: 20 additions & 0 deletions docs/guide/packages/lucide-react-native.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@ const App = () => {
};
```

## With Lucide lab or custom icons

[Lucide lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.

They can be used by using the `Icon` component.
All props like regular lucide icons can be passed to adjust the icon appearance.

### Using the `Icon` component

This creates a single icon based on the iconNode passed and renders a Lucide icon component.

```jsx
import { Icon } from 'lucide-react-native';
import { burger } from '@lucide/lab';

const App = () => (
<Icon iconNode={burger} />
);
```

## One generic icon component

It is possible to create one generic icon component to load icons, but it is not recommended.
Expand Down
20 changes: 20 additions & 0 deletions docs/guide/packages/lucide-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@ const App = () => {
};
```

## With Lucide lab or custom icons

[Lucide lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.

They can be used by using the `Icon` component.
All props like regular lucide icons can be passed to adjust the icon appearance.

### Using the `Icon` component

This creates a single icon based on the iconNode passed and renders a Lucide icon component.

```jsx
import { Icon } from 'lucide-react';
import { burger } from '@lucide/lab';

const App = () => (
<Icon iconNode={burger} />
);
```

## One generic icon component

It is possible to create one generic icon component to load icons, but it is not recommended.
Expand Down
20 changes: 20 additions & 0 deletions docs/guide/packages/lucide-solid.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@ const App = () => {
};
```

## With Lucide lab or custom icons

[Lucide lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.

They can be used by using the `Icon` component.
All props like the regular Lucide icons can be passed to adjust the icon appearance.

### Using the `Icon` component

This creates a single icon based on the iconNode passed and renders a Lucide icon component.

```jsx
import { Icon } from 'lucide-solid';
import { burger, sausage } from '@lucide/lab';

const App = () => (
<Icon iconNode={sausage} color="red"/>
);
```

## One generic icon component

It is possible to create one generic icon component to load icons. It's not recommended.
Expand Down
21 changes: 21 additions & 0 deletions docs/guide/packages/lucide-svelte.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,27 @@ The package includes type definitions for all icons. This is useful if you want

For more details about typing the `svelte:component` directive, see the [Svelte documentation](https://svelte.dev/docs/typescript#types-componenttype).

## With Lucide lab or custom icons

[Lucide lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.

They can be used by using the `Icon` component.
All props like the regular Lucide icons can be passed to adjust the icon appearance.

### Using the `Icon` component

This creates a single icon based on the iconNode passed and renders a Lucide icon component.

```svelte
<script>
import { Icon } from 'lucide-svelte';
import { burger, sausage } from '@lucide/lab';
</script>

<Icon iconNode={burger} />
<Icon iconNode={sausage} color="red"/>
```

## One generic icon component

It is possible to create one generic icon component to load icons, but it is not recommended.
Expand Down
30 changes: 26 additions & 4 deletions docs/guide/packages/lucide-vue-next.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,16 @@ Each icon can be imported as a Vue component, which renders an inline SVG Elemen
You can pass additional props to adjust the icon.

```vue
<script setup>
import { Camera } from 'lucide-vue-next';
</script>

<template>
<Camera
color="red"
:size="32"
/>
</template>

<script setup>
import { Camera } from 'lucide-vue-next';
</script>
```

## Props
Expand All @@ -69,6 +69,28 @@ To customize the appearance of an icon, you can pass custom properties as props
</template>
```

## With Lucide lab or custom icons

[Lucide lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.

They can be used by using the `Icon` component.
All props like regular lucide icons can be passed to adjust the icon appearance.

### Using the `Icon` component

This creates a single icon based on the iconNode passed and renders a Lucide icon component.

```vue
<script setup>
import { Icon } from 'lucide-vue-next';
import { burger } from '@lucide/lab';
</script>

<template>
<Icon :iconNode={burger} />
</template>
```

## One generic icon component

It is possible to create one generic icon component to load icons, but it is not recommended.
Expand Down
15 changes: 15 additions & 0 deletions docs/guide/packages/lucide.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,18 @@ menuIcon.classList.add('my-icon-class');
const myApp = document.getElementById('app');
myApp.appendChild(menuIcon);
```

### With Lucide lab or custom icons

[Lucide lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.
They can be used in the same way as the official icons.

```js
import { burger } from '@lucide/lab';

createIcons({
icons: {
burger
}
});
```
50 changes: 50 additions & 0 deletions packages/lucide-preact/src/Icon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { h, toChildArray } from 'preact';
import defaultAttributes from './defaultAttributes';
import type { IconNode, LucideProps } from './types';

interface IconComponentProps extends LucideProps {
iconNode: IconNode;
}

/**
* Lucide icon component
*
* @component Icon
* @param {object} props
* @param {string} props.color - The color of the icon
* @param {number} props.size - The size of the icon
* @param {number} props.strokeWidth - The stroke width of the icon
* @param {boolean} props.absoluteStrokeWidth - Whether to use absolute stroke width
* @param {string} props.class - The class name of the icon
* @param {IconNode} props.children - The children of the icon
* @param {IconNode} props.iconNode - The icon node of the icon
*
* @returns {ForwardRefExoticComponent} LucideIcon
*/
const Icon = ({
color = 'currentColor',
size = 24,
strokeWidth = 2,
absoluteStrokeWidth,
children,
iconNode,
class: classes = '',
...rest
}: IconComponentProps) =>
h(
'svg',
{
...defaultAttributes,
width: String(size),
height: size,
stroke: color,
['stroke-width' as 'strokeWidth']: absoluteStrokeWidth
? (Number(strokeWidth) * 24) / Number(size)
: strokeWidth,
class: ['lucide', classes].join(' '),
...rest,
},
[...iconNode.map(([tag, attrs]) => h(tag, attrs)), ...toChildArray(children)],
);

export default Icon;
47 changes: 13 additions & 34 deletions packages/lucide-preact/src/createLucideIcon.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import { type FunctionComponent, h, type JSX, toChildArray } from 'preact';
import defaultAttributes from './defaultAttributes';
import { toKebabCase } from '@lucide/shared';

export type IconNode = [elementName: keyof JSX.IntrinsicElements, attrs: Record<string, string>][];

export interface LucideProps extends Partial<Omit<JSX.SVGAttributes, 'ref' | 'size'>> {
color?: string;
size?: string | number;
strokeWidth?: string | number;
absoluteStrokeWidth?: boolean;
}

export type LucideIcon = FunctionComponent<LucideProps>;
import { h, type JSX } from 'preact';
import { mergeClasses, toKebabCase } from '@lucide/shared';
import Icon from './Icon';
import type { IconNode, LucideIcon, LucideProps } from './types';

/**
* Create a Lucide icon component
Expand All @@ -20,29 +10,18 @@ export type LucideIcon = FunctionComponent<LucideProps>;
* @returns {FunctionComponent} LucideIcon
*/
const createLucideIcon = (iconName: string, iconNode: IconNode): LucideIcon => {
const Component = ({
color = 'currentColor',
size = 24,
strokeWidth = 2,
absoluteStrokeWidth,
children,
class: classes = '',
...rest
}: LucideProps) =>
const Component = ({ class: classes = '', children, ...props }: LucideProps) =>
h(
'svg',
Icon,
{
...defaultAttributes,
width: String(size),
height: size,
stroke: color,
['stroke-width' as 'strokeWidth']: absoluteStrokeWidth
? (Number(strokeWidth) * 24) / Number(size)
: strokeWidth,
class: ['lucide', `lucide-${toKebabCase(iconName)}`, classes].join(' '),
...rest,
...props,
iconNode,
class: mergeClasses<string | JSX.SignalLike<string | undefined>>(
`lucide-${toKebabCase(iconName)}`,
classes,
),
},
[...iconNode.map(([tag, attrs]) => h(tag, attrs)), ...toChildArray(children)],
children,
);

Component.displayName = `${iconName}`;
Expand Down
3 changes: 3 additions & 0 deletions packages/lucide-preact/src/lucide-preact.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export * from './icons';
export * as icons from './icons';
export * from './aliases';
export * from './types';

export { default as createLucideIcon } from './createLucideIcon';
export { default as Icon } from './Icon';
12 changes: 12 additions & 0 deletions packages/lucide-preact/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { type FunctionComponent, type JSX } from 'preact';

export type IconNode = [elementName: keyof JSX.IntrinsicElements, attrs: Record<string, string>][];

export interface LucideProps extends Partial<Omit<JSX.SVGAttributes, 'ref' | 'size'>> {
color?: string;
size?: string | number;
strokeWidth?: string | number;
absoluteStrokeWidth?: boolean;
}

export type LucideIcon = FunctionComponent<LucideProps>;
Loading
Loading