Compare commits

..
105 Commits
Author SHA1 Message Date
Rodrigo Rodrigues 4b02cfdc8b feat(icons): added cctv-off icon (#4162)
* Added icons/cctv-off.svg

* Added icons/cctv-off.json
2026-03-23 14:43:40 +01:00
Antonin Kadrmas 59cf8104ef Update ICON_GUIDELINES link in CONTRIBUTING.md (#4187)
The old link for the guidelines link to the 404 page change the link to the working [link](https://lucide.dev/contribute/icon-design-guide).
2026-03-23 09:49:03 +01:00
Lukas Kalbertodt f9406068fb Fix formatting of <svg> element in two icons that were inconsistent (#4166)
These two icons were the only ones that didn't start with exactly

<svg
  xmlns="http://www.w3.org/2000/svg"
  width="24"
  height="24"
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
>

So I brought them in line.
2026-03-20 16:28:00 +01:00
d51c26ea9a fix(lucide-fonts): correct icon mappings in index.html and unicode.html (#4160)
Fixes lucide-icons/lucide#4154

The font mapping files were incorrectly mapping icon names to unicode values.
For example, message-circle-check was incorrectly pointing to database-search.

This was introduced in version 0.576 by commit efa1f252 which moved the
endCodePoint calculation inside the Promise.all callback, causing race
conditions where multiple icons could receive the same codepoint.

The fix moves endCodePoint calculation outside the Promise.all block
so it's calculated once before processing all icons, ensuring each icon
gets a unique codepoint.

Co-authored-by: Clawdbot <bot@clawdbot.com>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-03-20 15:43:27 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 6c00c2e74a chore(deps-dev): bump h3 from 1.15.4 to 1.15.6 (#4163)
Bumps [h3](https://github.com/h3js/h3) from 1.15.4 to 1.15.6.
- [Release notes](https://github.com/h3js/h3/releases)
- [Changelog](https://github.com/h3js/h3/blob/v1.15.6/CHANGELOG.md)
- [Commits](https://github.com/h3js/h3/compare/v1.15.4...v1.15.6)

---
updated-dependencies:
- dependency-name: h3
  dependency-version: 1.15.6
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-19 16:24:45 +01:00
Jakob Guddas 4af2f7e78b Updated icons/gpu.svg (#4147) 2026-03-14 20:58:03 +01:00
Jakob Guddas f8ee8d7287 docs: add rule about consistent use of shapes (#3975) 2026-03-14 20:55:52 +01:00
Sorin Hadjiu f910edc007 docs(site): add strapi lucide icons package (#4112) 2026-03-14 20:49:14 +01:00
Bhav Beri 4d44278d3e docs(svelte): clarify Svelte 4 vs Svelte 5 Lucide packages (#4107)
* Clarify package usage for Svelte 4 and 5

@lucide/svelte is specified for Svelte 5, with a note for Svelte 4 users to use lucide-svelte instead.

* Add message in lucide-svelte README as well

* Update the docs installation page to match the svelte docs page
2026-03-12 13:36:55 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> e2d1445f5b chore(deps): bump simple-git from 3.30.0 to 3.32.3 (#4133)
Bumps [simple-git](https://github.com/steveukx/git-js/tree/HEAD/simple-git) from 3.30.0 to 3.32.3.
- [Release notes](https://github.com/steveukx/git-js/releases)
- [Changelog](https://github.com/steveukx/git-js/blob/main/simple-git/CHANGELOG.md)
- [Commits](https://github.com/steveukx/git-js/commits/simple-git@3.32.3/simple-git)

---
updated-dependencies:
- dependency-name: simple-git
  dependency-version: 3.32.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-12 13:36:20 +01:00
Jakob Guddas a6136d3e47 fix(icons): changed school icon (#4124)
* Updated icons/school.svg

* Updated icons/school.json

* Updated icons/school.svg

* Updated icons/school.svg

* Updated icons/school.json

* Updated icons/school.json
2026-03-11 08:38:45 +01:00
Eric Fennis 785b2c6376 fix(redirects): Fixes icon alias redirects on site (#4122)
* Fix redirect issues

* turn off vercel output

* Revert "turn off vercel output"

This reverts commit 8cac049e24.

* Fix matching paths
2026-03-06 10:45:21 +01:00
Eric Fennis ed6ba4bf0c Merge branch 'main' of https://github.com/lucide-icons/lucide 2026-03-06 09:15:50 +01:00
Bhav Beri 5e460ce606 Fixes https://github.com/lucide-icons/lucide-lab/issues/6 (#4101) 2026-03-06 09:12:49 +01:00
Curtis Lowderandgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 0a2312d260 chore(icons): Add 'crypto' tag to bitcoin.json (#4120)
* Add 'crypto' tag to bitcoin.json

* Apply suggestion from @github-actions[bot]

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-05 18:41:45 +01:00
Eric Fennis e6c7d7d495 docs(api): Update nitro to latest version (#4102)
* update nitro

* try this?

* Try this

* update vercel output

* Add await

* Fix endpoints

* Adjust 404 catch all

* Fix output

* Adjust react in api

* Fix types

* Remove @resvg/resvg-wasm

* Format code

* Fix failing check

* Apply feedback

* Format code
2026-03-05 14:03:27 +01:00
Eric Fennis e8e800f98d ci(build-font): Fix env var GH actions 2026-03-04 10:39:55 +01:00
KISHORE KUMAR Sandgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 0ea8780434 feat(icons): added ellipse icon (#3749)
* Added icons/ellipse.svg

* Added icons/ellipse.json

* Updated icons/ellipse.json

* Update icons/ellipse.json

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-04 10:23:48 +01:00
Bhav Beri d88dca3732 Fix gitignore to correctly ignore the releaseMetadata folder of docs (#4100) 2026-03-04 10:22:12 +01:00
Eric Fennis efa1f25251 fix(font-build): Fix code points allocations 2026-03-04 10:17:52 +01:00
Eric Fennis 4201f70d7b ci(build-font): Use Vercel blob storage for font codepoints allocations 2026-03-02 08:30:29 +01:00
Eric Fennis d54247b637 ci: Update concurrency group name 2026-03-02 07:33:09 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> f6c0d0603a chore(deps): bump rollup from 4.53.3 to 4.59.0 (#4106)
Bumps [rollup](https://github.com/rollup/rollup) from 4.53.3 to 4.59.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.53.3...v4.59.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-version: 4.59.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-02 07:22:10 +01:00
6ee46b39a8 feat(icons): added fishing-rod icon (#3839)
* Added icons/fishing-rod.svg

* Added icons/fishing-rod.json

* Update fishing-rod.svg

upd: thanks to @karsa-mistmere & @jguddas

* Update icons/fishing-rod.json

++ contributors

Co-authored-by: Jakob Guddas <github@jguddas.de>

* Update fishing-rod.svg

 arc properly placed

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-02-27 16:32:47 +01:00
Eric FennisandCopilot de6ddfe381 fix(lucide-font, lucide-static): Fixing stable code points (#3894)
* Refactor font building

* Add lucide-font to gitignore

* Adjust workflow

* update lockfile

* Fixing code points build

* Adds next solution after build

* adds addLigatures to config

* Make code point consistent

* Format code

* Add todo

* Add comment in ci file

* Update tools/build-font/src/allocateCodepoints.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update tools/build-font/src/outlineSVGs.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-27 16:29:52 +01:00
Jamie LawandKarsa fdcaa659e4 Updated icons/cuboid.svg (#4098)
Co-authored-by: Karsa <contact@karsa.org>
2026-02-26 11:02:02 +01:00
Karsa 1e3018fea6 fix(icons): updated cuboid icon tags and categories (#4095)
* Updated icons/cuboid.svg

* Updated icons/cuboid.json

* Updated icons/cuboid.json
2026-02-26 11:00:48 +01:00
Karsa cf1c2ef2e4 fix(icons): changed receipt icon (#4075)
* Updated icons/receipt.svg

* Updated icons/receipt-cent.svg

* Updated icons/receipt-cent.json

* Updated icons/receipt-euro.svg

* Updated icons/receipt-euro.json

* Updated icons/receipt-indian-rupee.svg

* Updated icons/receipt-indian-rupee.json

* Updated icons/receipt-japanese-yen.svg

* Updated icons/receipt-japanese-yen.json

* Updated icons/receipt-pound-sterling.svg

* Updated icons/receipt-pound-sterling.json

* Updated icons/receipt-russian-ruble.svg

* Updated icons/receipt-russian-ruble.json

* Updated icons/receipt-swiss-franc.svg

* Updated icons/receipt-swiss-franc.json

* Updated icons/receipt-turkish-lira.svg

* Updated icons/receipt-turkish-lira.json
2026-02-24 09:06:42 +01:00
Karsa 89bb4f356c fix(icons): fixes guideline violations in package-* icons. (#4074)
* Updated icons/package-plus.svg

* Updated icons/package-x.svg

* Updated icons/package-check.svg

* Updated icons/package-minus.svg

* Updated icons/package-search.svg
2026-02-23 10:05:53 +01:00
1a8a7567eb Added zodiac signs (#712)
* Added zodiac signs

* Update cancer.svg

* Update capricorn.svg

* Update icons/gemini.svg

Co-authored-by: Jakob Guddas <github@jguddas.de>

* Update leo.svg

* Update libra.svg

* Update ophiuchus.svg

* Update pisces.svg

* Update scorpio.svg

* Update virgo.svg

* Update Aquarius SVG paths for new design

* Update scorpio.svg

* fix(icons/aquarius): fix off-grid paths introduced in https://github.com/lucide-icons/lucide/pull/712/changes/186e4d6e960d2593d71cc5b55f5a1870524ec478

* feat(icons): add zodiac prefix & add metadata json to zodiac icons

---------

Co-authored-by: Karsa <karsa@karsa.org>
Co-authored-by: Jakob Guddas <github@jguddas.de>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-02-23 09:47:51 +01:00
Karsa bca7e9cf43 fix(github/workflows): reformat ci.yml with prettier 2026-02-23 09:45:56 +01:00
Eric Fennis 80923a08b3 ci(ci.yml): Adds workflow_dispatch option to trigger manual release 2026-02-19 13:16:14 +01:00
Jakob Guddas 10f6d5f8c6 fix(icons): renamed flip-* to square-centerline-dashed-* (#3945)
* fix(icons): renamed flip-* to square-split-dashed-*

* Rename square-split-dashed-horizontal.json to square-centerline-dashed-horizontal.json

* Add square-centerline-dashed-vertical.json file

* Rename square-split-dashed-horizontal.svg to square-centerline-dashed-horizontal.svg

* Rename square-split-dashed-vertical.svg to square-centerline-dashed-vertical.svg

* Apply suggestion from @jguddas

* Apply suggestion from @jguddas

* Apply suggestion from @jguddas

* Apply suggestion from @jguddas
2026-02-19 12:13:36 +01:00
Ethan Hazel e77a037d9a feat(icons): added square-arrow-right-exit and square-arrow-right-enter icons (#3958)
* add(icons): added square-arrow-in and square-arrow-out icons

* fix(icons): renamed square-arrow-in/out to have left/right in name

* fix(icons): updated square-arrow-exit-right and square-arrow-enter-left

* fix(square-arrow-enter-right, square-arrow-exit-right): Renamed icons & edited metadata
2026-02-19 12:12:34 +01:00
Jakob GuddasandKarsa 3f53744316 Updated icons/file-pen-line.svg (#3970)
Co-authored-by: Karsa <contact@karsa.org>
2026-02-19 12:11:30 +01:00
DuckAfire 09574d820e fix(icons): remove execution permission of SVG files (#4053) 2026-02-19 12:10:31 +01:00
edwloef aeef1017fe feat(icons): added metronome icon (#4063) 2026-02-19 10:12:32 +01:00
Eric Fennis 267f22dced fix(lucide): Fix ESM Module output path in build (#4084)
* Fix module output path

* Format code
2026-02-19 10:11:52 +01:00
Karsa 391b0f6fc6 feat(icons): added message-square-check icon (#4076)
* Added icons/message-square-check.svg

* Added icons/message-square-check.json
2026-02-17 23:16:53 +01:00
849d10eda4 feat(icons): added mouse-right icon (#2787)
* Added icons/mouse-right.svg

* Added icons/mouse-right.json

* Update icons/mouse-right.svg

Co-authored-by: Karsa <contact@karsa.org>

---------

Co-authored-by: Karsa <contact@karsa.org>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-02-17 13:35:39 +01:00
2b9cacc5ae feat(icons): added mouse-left icon (#2788)
* Added icons/mouse-left.svg

* Added icons/mouse-left.json

* Update icons/mouse-left.svg

Co-authored-by: Karsa <contact@karsa.org>

---------

Co-authored-by: Karsa <contact@karsa.org>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-02-17 13:35:29 +01:00
Jakob Guddasgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Eric FennisKarsa
cc9c5d2731 feat(icons): added x-line-top icon (#2838)
* Added icons/x-bar.svg

* Added icons/x-bar.json

* Rename x-bar.svg to x-line-top.svg

* Add x-line-top.json icon file

* Update icons/x-line-top.json

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Karsa <contact@karsa.org>
2026-02-17 13:35:19 +01:00
Jakob Guddas 019d3b9792 fix(icons): flipped coins icon (#3158)
* Updated icons/coins.svg

* Updated icons/coins.json

* Updated icons/coins.svg
2026-02-17 13:23:31 +01:00
Jamie Law feca9eaab5 fix(icons): changed rocking-chair icon (#3445)
* Updated icons/rocking-chair.svg

* Updated icons/rocking-chair.json
2026-02-17 12:51:52 +01:00
Henry WilkinsonandEric Fennis 88b972059f feat(icons): added message-circle-check icon (#3770)
* Added icons/message-circle-check.svg

* Added icons/message-circle-check.json

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-02-17 12:32:36 +01:00
KarsaandKarsa 9d86a86a99 feat(icons): added shelving-unit icon (#3041)
* [github] Added issue template forms

* [github] yaml => yml

* Syntax fixes

* Further syntax fixes

* Sort issue templates

* Update 02_bug_report.yml

* Added icons/shelf.svg

* Added icons/shelf.json

* Update shelf.json

* Update shelf.json

* Update and rename shelf.json to shelving-unit.json

* Rename shelf.svg to shelving-unit.svg

---------

Co-authored-by: Karsa <karsa@karsa.org>
2026-02-17 12:11:12 +01:00
Adam LindqvistandKarsa 727e29183f fix(icons): rearange circle-icons path and circle order (#3746)
* Rearrange svg element order

* Rearrange svg element order

* Revert package.json update

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-02-17 10:56:57 +01:00
603df50ddd feat(icons): added towel-rack icon (#3350)
* Added icons/towel-rack.svg

* Added icons/towel-rack.json

* Updated icons/towel-rack.svg

* Updated icons/towel-rack.svg

* Updated icons/towel-rack.svg

* Updated icons/towel-rack.json

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Karsa <contact@karsa.org>
2026-02-17 10:25:44 +01:00
Muhammad Aqib BashirandKarsa c79a0ecbda feat(icons): add mirror-round and mirror-rectangular (#3832)
* feat(icon): add mirror-round icon

* feat(icon): add mirror-rectangular icon

* Update icons/mirror-rectangular.json: remove part of name from tages

Co-authored-by: Karsa <contact@karsa.org>

* Update icons/mirror-round.json: remove part of name from tags

Co-authored-by: Karsa <contact@karsa.org>

* Update icons/mirror-round.json: add vanity and makeup tags

Co-authored-by: Karsa <contact@karsa.org>

* fix(size): increase to make it a bit larger from `14 x 18` to `16 x 20`

Co-authored-by: Karsa <contact@karsa.org>

* Apply suggestion from @karsa-mistmere

Co-authored-by: Karsa <contact@karsa.org>

* Update mirror-round.json

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-02-17 09:44:18 +01:00
SpleefiesandKarsa 8939deb430 fix(icons): changed clipboard-pen icon (#4006)
* Updated icons/clipboard-pen.svg

* Updated icons/clipboard-pen.json

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-02-17 09:44:06 +01:00
Karsa 54abe52318 fix(icons): fix linting issues in git-merge-conflict.json 2026-02-17 09:22:57 +01:00
137034105a feat(icons): Add git-merge-conflict icon (#3008)
* Add icons/git-merge-conflict-icon

* updated git-merge-conflict.svg and git-merge-conflict.json

* added more contributors to git-merge-conflict.json

---------

Co-authored-by: timmy471 <timilehin.ayantunji@etranzact.com>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-02-17 08:45:50 +01:00
Owen FosterandJakob Guddas 9d9fb2c30b fix(icons): adjusted clapperboard so slash is no longer protruding (#3764)
* Adjusted second slash on clapperboard icon so it no longer protrudes.

* Update icons/clapperboard.svg

* Modify SVG paths in clapperboard icon

* Add 'torfmuer' to contributors in clapperboard.json

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>
2026-02-17 08:34:00 +01:00
Nathan De PachtereandEric Fennis caa50f5543 feat(icons): added line-dot-right-horizontal icon (#3742)
* Added icons/last-commit.svg

* Added icons/last-commit.json

* Rename to line-dot-right-horizontal

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-02-17 08:19:51 +01:00
Jakob Guddas b5fc65eed5 fix(icons): changed gift icon (#3977)
* Updated icons/gift.svg

* Updated icons/gift.svg

* Updated icons/gift.svg

* Updated icons/gift.svg

* Updated icons/gift.json
2026-02-17 07:56:09 +01:00
Jamie Law 153c35f5dd chore(tags): added tags to info (#4047)
* Update tags for `info` icon

* Add extra tags from Chat GPT
2026-02-17 07:54:41 +01:00
Timofey Kochetovgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>KarsaEric Fennis
07744ea48f feat(icons): added globe-off icon (#4051)
* Added icons/globe-off.svg

* Added icons/globe-off.json

* Apply suggestion from @github-actions[bot]

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Update icons/globe-off.svg

Co-authored-by: Karsa <contact@karsa.org>

* Update globe-off.json

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Karsa <contact@karsa.org>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-02-17 07:34:06 +01:00
Jakob Guddas 0846e2c6ef fix(icons): changed rocket icon (#4067)
* Updated icons/rocket.svg

* Updated icons/rocket.json
2026-02-17 07:30:29 +01:00
Jakob Guddasgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Eric Fennis
dea4936a72 fix(icons): changed forklift icon (#4069)
* Updated icons/forklift.svg

* Updated icons/forklift.json

* Apply suggestion from @github-actions[bot]

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-17 07:29:19 +01:00
Muhammad Aqib BashirandEric Fennis b76860a2b8 feat(icons): add lens-concave and lens-convex (#3831)
* feat(icons): add lens-convex icon

* feat(icon): add lens-concave icon

* fix(icon): replace approximate curve segments with 14-unit

* fix(icon): undo changes of making convex icon into concave

* fix(lens-concave): round path values from 13.9 to 14 to improve icon math

* Add 'shapes' category to lens-convex.json

* Add 'shapes' category to lens-concave.json

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-02-17 07:25:57 +01:00
Karsa de9b2d39b7 feat(icons): adds user-key and user-round-key, updates other -key icons to match (#4044)
* Updated icons/file-key.svg

* Updated icons/book-key.svg

* Updated icons/folder-key.svg

* Updated icons/rotate-ccw-key.svg

* Added icons/user-round-key.svg

* Added icons/user-round-key.json

* Added icons/user-key.svg

* Added icons/user-key.json

* Update user-key.json

* Update user-round-key.json
2026-02-13 12:28:24 +01:00
Jakob Guddas 08488f4809 fix(icons): changed cloud-alert and cloud-check icon (#3976)
* Updated icons/cloud-alert.svg

* Updated icons/cloud-alert.json

* Updated icons/cloud-check.svg
2026-02-13 12:24:21 +01:00
Jakob Guddas 3574e224e0 fix(icons): changed file-cog icon (#3965)
* Updated icons/file-cog.svg

* Updated icons/file-cog.json

* Updated icons/file-cog.svg

* Updated icons/file-cog.svg
2026-02-13 12:12:31 +01:00
Jakob Guddas 9a8e023754 fix(icons): changed git-branch icon (#3938)
* Updated icons/git-branch.svg

* Updated icons/git-branch.json
2026-02-10 08:23:39 +01:00
Jakob GuddasandEric Fennis 88fd3dadcb fix(icons): changed hard-drive icon (#3622)
* Updated icons/hard-drive.svg

* Updated icons/hard-drive.svg

* Updated icons/hard-drive.json

* Add keywords for storage and hardware in hard-drive.json

Added new keywords related to storage and hardware.

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-02-03 08:28:23 +01:00
Jakob Guddas bc446a83b2 fix(icons): changed bandage icon (#3967)
* Updated icons/bandage.svg

* Updated icons/bandage.json
2026-02-03 08:24:10 +01:00
Jakob Guddas 39fa345658 fix(icons): changed bell-dot icon (#3973)
* Updated icons/bell-dot.svg

* Updated icons/bell-dot.json
2026-02-03 08:23:15 +01:00
Jakob Guddas fb31e5f616 fix(icons): changed bug-off icon (#3972)
* Updated icons/bug-off.svg

* Updated icons/bug-off.json
2026-02-03 08:21:35 +01:00
Jakob Guddas dcd95a3b90 fix(icons): changed user-lock icon (#3971)
* Updated icons/user-lock.svg

* Updated icons/user-lock.json
2026-02-03 08:18:47 +01:00
SpleefiesandJakob Guddas a1a729555b feat(icons): added database-search icon (#4003)
* Added icons/database-search.svg

* Added icons/database-search.json

* Refactor SVG paths in database-search icon

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>
2026-02-02 21:30:51 +01:00
Eric Fennis a28631e2a4 chore(docs): Improve SEO icon detail pages (#4040)
* improve-seo-website

* Add some description texts
2026-01-29 16:19:32 +01:00
Eric Fennis cbaaf4e21e fix(@lucide/svelte): Fix build in (#4026)
* Fix build

* Adds extra typechecking

* Format code
2026-01-23 14:06:15 +01:00
lt25106 e9e060a851 feat(icons): added printer-x icon (#3941)
* Added icons/printer-cross.svg

* Added icons/printer-cross.json

* Add error-related tags to printer-cross.json

Added new tags for error handling.

* Rename printer-cross.json to printer-x.json

* Update and rename printer-cross.svg to printer-x.svg
2026-01-23 11:43:01 +01:00
Epifânio Francisco 0371baabcb fix(site): hide native search input clear "X" icon (#3933)
* fix(site): hide native search input clear "X" icon

Hide the browser's default clear "X" icon for search inputs to prevent duplicate icons when using the custom clear button. This resolves issue #3925

* style(site): adjust clear button position in input component for mobile

* fix(site): adjust clear button position for Mac in search input
2026-01-23 07:51:00 +01:00
Karsa 67c0485457 feat(scripts): added helper script to automatically update OpenCollective backers in all readmes (#4014)
feat(docs): upgraded backers as per the recurring contributions in the last 3 months
2026-01-22 11:27:39 +01:00
drago1520 c47876e5a6 Suggest anchoring to a specific lucide version when using cnd (#3727)
My whole app crashed because the newest version had a critical bug. I want to help other people avoid my mistake by anchoring to a specific version that worked for them
2026-01-22 09:07:52 +01:00
dependabot[bot]dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Eric Fennis
96859ba947 chore(deps): bump lodash-es from 4.17.21 to 4.17.23 (#4019)
Bumps [lodash-es](https://github.com/lodash/lodash) from 4.17.21 to 4.17.23.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.21...4.17.23)

---
updated-dependencies:
- dependency-name: lodash-es
  dependency-version: 4.17.23
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-01-22 09:06:37 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 7dfa7d9fc6 chore(deps): bump lodash from 4.17.21 to 4.17.23 (#4020)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.21 to 4.17.23.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.21...4.17.23)

---
updated-dependencies:
- dependency-name: lodash
  dependency-version: 4.17.23
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-22 08:58:17 +01:00
b6ed43d48c feat(packages): Added aria-hidden fallback for decorative icons to all packages (#3604)
* Add aria hidden to lucide package

* Add aria-hidden to astro package

* Add tests for shared package

* Fix test for props

* add aria prop to lucide-solid

* Add aria-hidden to lucide-vue-next

* Add aria-hidden prop to angular package

* Fix builds

* Add notice about aria-label in docs

* Format code

* Update packages/svelte/tests/Icon.spec.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/lucide-svelte/tests/Icon.spec.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/shared/src/utils/hasA11yProp.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Adjusted docs

* Fix import

* update tests

* test(shared): fix hasA11yProp unit test

* fix(packages/lucide-angular): fix hasA11yProp import path (non-relative import path will not get properly resolved by ng-packagr)

* Format code

* Adjust aria props to root element

* Format code

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Karsa <contact@karsa.org>
2026-01-20 15:55:02 +01:00
Alexander Wondwossen 9b10d1d9bb Update LICENSE (#4009) 2026-01-20 08:13:05 +01:00
Jakob Guddas 442ddbc43c fix: resolved spelling mistake in gh issue close command (#4000) 2026-01-19 13:08:57 +01:00
Jakob Guddas ce5cab371f fix(icons): changed cloudy icon (#3966)
* Updated icons/cloudy.svg

* Updated icons/cloudy.json

* Updated icons/cloudy.svg
2026-01-15 14:48:23 +01:00
Jakob Guddas 69239462bb fix(icons): changed message-square-dashed icon (#3959)
* Updated icons/message-square-dashed.svg

* Updated icons/message-square-dashed.json

* Updated icons/message-square-dashed.svg
2026-01-15 14:35:18 +01:00
Jakob Guddasgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>KarsaEric Fennis
f8e04958d8 fix(icons): changed bookmark icon (#2906)
* Updated icons/bookmark.svg

* Updated icons/bookmark.json

* Updated icons/bookmark.svg

* Updated icons/bookmark.svg

* Update icons/bookmark.json

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Updated icons/bookmark-check.svg

* Updated icons/bookmark-check.json

* Updated icons/bookmark-minus.svg

* Updated icons/bookmark-minus.json

* Updated icons/bookmark-plus.svg

* Updated icons/bookmark-plus.json

* Updated icons/bookmark-x.svg

* Updated icons/bookmark-x.json

---------

Co-authored-by: Karsa <contact@karsa.org>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-15 14:15:40 +01:00
Karsa e466a104ff fix(icons): changed waypoints icon (#3990)
* Updated icons/waypoints.svg

* Updated icons/waypoints.json
2026-01-15 13:30:47 +01:00
Muhammad Aqib BashirandKarsa 516917c527 feat(icon): add globe-x icon with metadata (#3827)
* feat(icon): add globe-x icon with metadata

* style(icon): redesign icon to make X mark 5 by 5

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-01-12 10:34:21 +01:00
dependabot[bot]dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Eric Fennis
3cec234405 chore(deps-dev): bump preact from 10.27.2 to 10.27.3 (#3955)
Bumps [preact](https://github.com/preactjs/preact) from 10.27.2 to 10.27.3.
- [Release notes](https://github.com/preactjs/preact/releases)
- [Commits](https://github.com/preactjs/preact/compare/10.27.2...10.27.3)

---
updated-dependencies:
- dependency-name: preact
  dependency-version: 10.27.3
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-01-10 17:34:30 +01:00
a258509bbb docs(site): added lucide-web-components third-party package (#3948)
* Add Lucide Web Components implementation

* restore lucide-rails

* Update docs/.vitepress/data/packageData.thirdParty.json

Co-authored-by: Karsa <contact@karsa.org>

---------

Co-authored-by: midesweb <miguel@escuela.it>
Co-authored-by: Karsa <contact@karsa.org>
2026-01-10 17:34:16 +01:00
Jakob Guddas 10918eba1f Updated icons/cloud-off.svg (#3942) 2026-01-10 12:38:15 +01:00
Jakob Guddas 5f4f58cba8 fix(icons): changed lasso icon (#3961)
* Updated icons/lasso.svg

* Updated icons/lasso.json

* Updated icons/lasso.svg
2026-01-10 12:37:19 +01:00
Jakob Guddas 511d7fabf7 Updated icons/monitor-off.svg (#3962) 2026-01-10 12:36:16 +01:00
Jakob Guddas 77a67819e4 Updated icons/tickets-plane.svg (#3928) 2026-01-08 12:54:13 +01:00
Jakob Guddas edc588125f Updated icons/star-off.svg (#3952) 2026-01-07 09:20:42 +01:00
taimar 0c4ac91ba5 fix(site): unify and improve the styling of input fields (#3919)
* Unify and improve the styling of input fields

* InputSearch: use ellipsis character, remove redundant space
2026-01-02 08:48:03 +01:00
taimar 450acd617d Add missing titles and unify title template (#3920) 2026-01-02 08:46:32 +01:00
Karsa d391bda369 feat: add Android to brand stopwords (#3895) 2025-12-22 07:54:08 +01:00
David Castilla Ortiz 69bf052ee5 Enable ligatures in font build configuration (#3876) 2025-12-18 12:17:28 +01:00
Karsa 6b4075b89b feat(icons): added toolbox icon (#3871)
* Added icons/toolbox.svg

* Added icons/toolbox.json
2025-12-18 11:44:47 +01:00
Jacek TomaszewskiandEric Fennis 7a68e10b12 fix(lucide-react-native): remove icons namespace export to enable tree-shaking (#3868)
* fix(lucide-react-native): remove icons namespace export to enable tree-shaking

The `export * as icons from './icons'` statement defeats tree-shaking
because bundlers cannot determine which exports from the namespace are
actually used at build time. This causes all 1600+ icons to be included
in the final bundle even when only a few are imported.

This change removes the namespace re-export while keeping all individual
icon exports available via `export * from './icons'`.

BREAKING CHANGE: The `icons` namespace export is no longer available.
Users should import icons directly: `import { Activity } from 'lucide-react-native'`
instead of `import { icons } from 'lucide-react-native'; icons.Activity`.

* Add icons entry file to improve treeshaking

* Format code

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2025-12-18 11:44:26 +01:00
Jakob Guddas a4531a9985 fix(react-native-web): only add className prop to parent Icon component (#3892) 2025-12-18 11:43:31 +01:00
taimar 3edcd9e0c3 fix and unify color-picker font-size (#3889) 2025-12-15 14:59:14 +01:00
Jakob Guddas 0b8f99326c fix(icons): changed paint-bucket icon (#3880)
* Updated icons/paint-bucket.svg

* Updated icons/paint-bucket.svg

* Updated icons/paint-bucket.svg

* Updated icons/paint-bucket.svg

* Updated icons/paint-bucket.json

* Updated icons/paint-bucket.json
2025-12-12 13:27:37 +01:00
Alexandru Portangithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Jakob Guddas
7abb61630e feat(icons): added stone icon (#3850)
* Added icons/stone.svg

* Added icons/stone.json

* Update icons/stone.json

Added suggested tags

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Update stone.svg

Updated based on suggested changes

* Update icons/stone.json

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jakob Guddas <github@jguddas.de>
2025-12-12 09:26:54 +01:00
Eric FennisandKarsa 3b0d158ea1 fix(site): Small adjustments color picker and add clear button search bar (#3851)
* Small adjustments

* Format code

* format code

* Remove default value

* format code

* update yml file

* Format code

* Update docs/.vitepress/theme/components/base/Input.vue

Co-authored-by: Karsa <contact@karsa.org>

* Add extra check if null or undefined

---------

Co-authored-by: Karsa <contact@karsa.org>
2025-12-12 09:25:39 +01:00
124572c83b feat(icons): added cannabis-off icon (#3748)
* Added icons/cannabis-off.svg

* Added icons/cannabis-off.json

* fix: applied optimization by jguddas

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Karsa <contact@karsa.org>
2025-12-11 09:15:49 +01:00
378 changed files with 5754 additions and 2530 deletions
+18 -2
View File
@@ -7,17 +7,26 @@ on:
paths:
- icons/**/*.svg
workflow_dispatch:
inputs:
version:
description: Version
required: true
permissions:
id-token: write # Required for OIDC
contents: write
# This is added to make sure we wait until last release is done, this is needed for the font-build process
concurrency:
group: continuous-integration
jobs:
create-release:
if: github.repository == 'lucide-icons/lucide' && startsWith(github.event.head_commit.message, 'feat(icons)')
if: github.repository == 'lucide-icons/lucide' && startsWith(github.event.head_commit.message, 'feat(icons)') && github.event_name != 'workflow_dispatch'
runs-on: ubuntu-latest
outputs:
VERSION: ${{ steps.new-version.outputs.NEW_VERSION }}
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
@@ -69,3 +78,10 @@ jobs:
secrets: inherit
with:
version: ${{ needs.create-release.outputs.VERSION }}
dispatch-release:
if: github.event_name == 'workflow_dispatch'
uses: './.github/workflows/release.yml'
secrets: inherit
with:
version: ${{ inputs.version }}
@@ -28,7 +28,7 @@ jobs:
{ [ -n "$ICON_NAME_SECTION" ] && echo "$ICON_NAME_SECTION" | grep -iqE "$SAFE_KEY|$SAFE_VALUE"; }; then
gh issue close ${{ github.event.issue.number }} \
--reason "not_planned" \
--reason "not planned" \
--comment "It looks like this request is about **${VALUE}**, which is a brand logo.
Lucide **does not accept** brand logos, and we do not plan to add them in the future. This is due to a combination of **legal restrictions**, **design consistency concerns**, and **practical maintenance reasons**.
-3
View File
@@ -20,9 +20,6 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Outline svg Icons
run: pnpm build:outline-icons
- name: Create font in ./lucide-font
run: pnpm build:font
+16
View File
@@ -41,3 +41,19 @@ jobs:
- name: Test
run: pnpm --filter @lucide/svelte test
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v6
with:
cache: 'pnpm'
node-version-file: 'package.json'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Test
run: pnpm --filter @lucide/svelte typecheck
+6 -10
View File
@@ -12,16 +12,13 @@ on:
description: Version
type: string
workflow_dispatch:
inputs:
version:
description: Version
required: true
permissions:
id-token: write # Required for OIDC
contents: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
pre-release:
if: github.repository == 'lucide-icons/lucide' && contains('["ericfennis", "karsa-mistmere", "jguddas"]', github.actor)
@@ -135,11 +132,10 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Outline svg Icons
run: pnpm build:outline-icons
- name: Create font in ./lucide-font
run: pnpm build:font
run: pnpm build:font --saveCodePoints
env:
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }}
- name: 'Upload to Artifacts'
uses: actions/upload-artifact@v4
+4 -1
View File
@@ -14,12 +14,15 @@ coverage
stats
*.log
outlined
lucide-font
packages/**/src/icons/*.js
packages/**/src/icons/*.ts
packages/**/src/icons/*.tsx
packages/**/src/aliases/*.ts
packages/**/src/aliases.ts
!packages/**/src/aliases/index.ts
packages/**/src/utils/*.ts
!packages/shared/src/utils/*.ts
packages/**/src/dynamicIconImports.ts
packages/**/DynamicIcon.d.ts
packages/**/dynamicIconImports.js
@@ -40,7 +43,7 @@ docs/.vitepress/.temp
docs/.vitepress/data/iconNodes
docs/.vitepress/data/iconMetaData.ts
docs/.vitepress/data/releaseMetaData.json
docs/.vitepress/data/releaseMetaData
docs/.vitepress/data/releaseMetadata
docs/.vitepress/data/categoriesData.json
docs/.vitepress/data/iconDetails
docs/.vitepress/data/relatedIcons.json
+1 -1
View File
@@ -25,7 +25,7 @@ Guidelines for pull requests:
Please make sure you follow the icon guidelines, that should be followed to keep quality and consistency when making icons for Lucide.
Read it here: [ICON_GUIDELINES](https://lucide.dev/docs/icon-design-guide).
Read it here: [ICON_GUIDELINES](https://lucide.dev/contribute/icon-design-guide).
#### Lucide Studio
+2 -2
View File
@@ -1,6 +1,6 @@
ISC License
Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2023 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2025.
Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2026 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2026.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -18,7 +18,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
The MIT License (MIT) (for portions derived from Feather)
Copyright (c) 2013-2023 Cole Bemis
Copyright (c) 2013-2026 Cole Bemis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+11 -2
View File
@@ -88,7 +88,16 @@ Thank you to all the people who contributed to Lucide!
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="docs/public/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
[//]: <> (Open Collective backers)
### Awesome backers 🍺
<a href="https://github.com/pdfme/pdfme"><img src="docs/public/sponsors/pdfme.svg" width="180" alt="pdfme sponsor badge" /></a>
<a href="https://www.fina.money/"><img src="docs/public/sponsors/fina-money.png" width="180" alt="Fina Money sponsor badge" /></a>
<a href="https://github.com/pdfme/pdfme"><img src="docs/public/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
<a href="https://www.paxhistoria.co/"><img src="docs/public/sponsors/paxhistoria.svg?" width="180" alt="Pax Historia – An alternate history sandbox game" /></a>
### Backers ☕
<a href="https://www.fina.money/"><img src="docs/public/sponsors/fina-money.png" width="180" alt="Fina Money – Modular Finance Tracker" /></a>
### Other contributors 💸
You can find all our past and non-recurring financial contributors at [our Open Collective page](https://opencollective.com/lucide-icons).
+1
View File
@@ -2,6 +2,7 @@
"adobe": "Adobe",
"airplay": "AirPlay",
"amazon": "Amazon",
"android": "Android",
"angular": "Angular",
"aws": "AWS",
"azure": "Azure",
@@ -1,3 +1,4 @@
import { eventHandler, setResponseHeader } from 'h3';
import iconMetaData from '../../data/iconMetaData';
export default eventHandler((event) => {
+1
View File
@@ -1,3 +1,4 @@
import { eventHandler, setResponseHeader } from 'h3';
import iconNodes from '../../data/iconNodes/index.ts';
import { IconNodeWithKeys } from '../../theme/types';
import iconMetaData from '../../data/iconMetaData';
@@ -1,6 +1,6 @@
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
import { createElement } from 'react';
import React from 'react';
import SvgPreview from '../../lib/SvgPreview/index.tsx';
import iconNodes from '../../data/iconNodes';
import createLucideIcon from 'lucide-react/src/createLucideIcon';
@@ -34,36 +34,29 @@ export default eventHandler((event) => {
const iconNode = iconNodes[backdropName];
const LucideIcon = createLucideIcon(backdropName, iconNode);
const svg = renderToStaticMarkup(createElement(LucideIcon));
const svg = renderToStaticMarkup(<LucideIcon />);
const backdropString = svg.replaceAll('\n', '').replace(/<svg[^>]*>|<\/svg>/g, '');
children.push(
createElement(Backdrop, {
backdropString,
src: src.replace(/<svg[^>]*>|<\/svg>/g, ''),
color: '#777',
}),
<Backdrop
backdropString={backdropString}
src={src.replace(/<svg[^>]*>|<\/svg>/g, '')}
color="#777"
/>,
);
}
const svg = Buffer.from(
// We can't use jsx here, is not supported here by nitro.
renderToString(
createElement(
SvgPreview,
{
src: src.replace(/<svg[^>]*>|<\/svg>/g, ''),
height,
width,
showGrid: true,
},
children,
),
),
).toString('utf8');
defaultContentType(event, 'image/svg+xml');
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
return svg;
return renderToString(
<SvgPreview
src={src.replace(/<svg[^>]*>|<\/svg>/g, '')}
showGrid
height={height}
width={width}
>
{children}
</SvgPreview>,
);
});
@@ -1,6 +1,6 @@
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
import { createElement } from 'react';
import React from 'react';
import Diff from '../../../lib/SvgPreview/Diff.tsx';
import iconNodes from '../../../data/iconNodes';
import createLucideIcon from 'lucide-react/src/createLucideIcon';
@@ -26,21 +26,26 @@ export default eventHandler((event) => {
const children = [];
const Icon = createLucideIcon(name, iconNodes[name]);
const oldSrc = iconNodes[name]
? renderToStaticMarkup(createElement(createLucideIcon(name, iconNodes[name])))
? renderToStaticMarkup(<Icon />)
.replaceAll('\n', '')
.replace(/<svg[^>]*>|<\/svg>/g, '')
: '';
const svg = Buffer.from(
// We can't use jsx here, is not supported here by nitro.
renderToString(
createElement(Diff, { oldSrc, newSrc, showGrid: true, height, width }, children),
),
).toString('utf8');
defaultContentType(event, 'image/svg+xml');
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
return svg;
return renderToString(
<Diff
oldSrc={oldSrc}
newSrc={newSrc}
showGrid
height={height}
width={width}
>
{children}
</Diff>,
);
});
@@ -1,17 +1,12 @@
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { Resvg, initWasm } from '@resvg/resvg-wasm';
import iconNodes from '../../../data/iconNodes';
import wasm from './loadWasm';
import { createElement } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import createLucideIcon from 'lucide-react/src/createLucideIcon';
var initializedResvg = initWasm(wasm);
import sharp from 'sharp';
export default eventHandler(async (event) => {
const { params = {} } = event.context;
await initializedResvg;
const imageSize = 96;
const name = params.data.split('/').at(-3);
const iconSizeString = params.data.split('/').at(-2);
@@ -45,9 +40,7 @@ export default eventHandler(async (event) => {
)
.replace(/<\/svg>/, '</g></svg>');
const resvg = new Resvg(svg, { background: '#000' });
const pngData = resvg.render();
const pngBuffer = Buffer.from(pngData.asPng());
const pngBuffer = await sharp(Buffer.from(svg)).png().toBuffer();
defaultContentType(event, 'image/svg+xml');
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
@@ -67,7 +60,7 @@ export default eventHandler(async (event) => {
<image
width="${imageSize}"
height="${prevSvg ? imageSize * 2 : imageSize}"
href="data:image/png;base64,${pngBuffer.toString('base64')}"
href="data:image/png;base64,${pngBuffer.toString('base64')}"
image-rendering="pixelated"
/>
</mask>
@@ -1,16 +0,0 @@
import fs from 'fs';
import module from 'node:module';
/* WASM_IMPORT */
let wasm;
if (process.env.NODE_ENV === 'development') {
const require = module.createRequire(import.meta.url);
wasm = fs.readFileSync(require.resolve('@resvg/resvg-wasm/index_bg.wasm'));
} else {
// @ts-ignore
wasm = resvg_wasm;
}
export default wasm;
@@ -1,44 +0,0 @@
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { renderToString } from 'react-dom/server';
import { createElement } from 'react';
import SvgPreview from '../../../lib/SvgPreview/index.tsx';
import createLucideIcon, { IconNode } from 'lucide-react/src/createLucideIcon';
import { parseSync } from 'svgson';
export default eventHandler((event) => {
const { params } = event.context;
const [strokeWidth, svgData] = params.data.split('/');
const data = svgData.slice(0, -4);
const src = Buffer.from(data, 'base64').toString('utf8');
const Icon = createLucideIcon(
'icon',
parseSync(src.includes('<svg') ? src : `<svg>${src}</svg>`).children.map(
({ name, attributes }) => [name, attributes],
) as IconNode,
);
const svg = Buffer.from(
// We can't use jsx here, is not supported here by nitro.
renderToString(createElement(Icon, { strokeWidth }))
.replace(/fill\="none"/, 'fill="#fff"')
.replace(
/>/,
`><style>
@media screen and (prefers-color-scheme: light) {
svg { fill: transparent !important; }
}
@media screen and (prefers-color-scheme: dark) {
svg { stroke: #fff; fill: transparent !important; }
}
</style>`,
),
).toString('utf8');
defaultContentType(event, 'image/svg+xml');
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
return svg;
});
@@ -0,0 +1,37 @@
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { renderToString } from 'react-dom/server';
import React from 'react';
import Icon from 'lucide-react/src/Icon';
import type { IconNode } from 'lucide-react/src/types';
import { parseSync } from 'svgson';
export default eventHandler((event) => {
const { params } = event.context;
const [strokeWidth, svgData] = params.data.split('/');
const data = svgData.slice(0, -4);
const src = Buffer.from(data, 'base64').toString('utf8');
const iconNode = parseSync(src.includes('<svg') ? src : `<svg>${src}</svg>`).children.map(
({ name, attributes }) => [name, attributes],
) as IconNode;
defaultContentType(event, 'image/svg+xml');
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
return renderToString(
<Icon
iconNode={iconNode}
strokeWidth={strokeWidth}
>
<style>
{`@media screen and (prefers-color-scheme: light) {
svg { fill: transparent !important; }
}
@media screen and (prefers-color-scheme: dark) {
svg { stroke: #fff; fill: transparent !important; }
}`}
</style>
</Icon>,
);
});
@@ -1,6 +1,6 @@
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { renderToString } from 'react-dom/server';
import { createElement } from 'react';
import React from 'react';
import Diff from '../../../lib/SvgPreview/Diff.tsx';
export default eventHandler((event) => {
@@ -41,15 +41,18 @@ export default eventHandler((event) => {
return '';
}
const svg = Buffer.from(
// We can't use jsx here, is not supported here by nitro.
renderToString(
createElement(Diff, { oldSrc, newSrc, showGrid: true, height, width }, children),
),
).toString('utf8');
defaultContentType(event, 'image/svg+xml');
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
return svg;
return renderToString(
<Diff
oldSrc={oldSrc}
newSrc={newSrc}
showGrid
height={height}
width={width}
>
{children}
</Diff>,
);
});
@@ -22,6 +22,7 @@ export default eventHandler((event) => {
const height = getQuery(event).height || undefined;
const color = getQuery(event).color || undefined;
const strokeWidth = getQuery(event).strokeWidth || undefined;
const background = getQuery(event).background || undefined;
const LucideIcon = createLucideIcon(params.iconName, iconNode);
@@ -32,6 +33,7 @@ export default eventHandler((event) => {
height,
color: color ? `#${color}` : undefined,
strokeWidth,
style: background ? { background } : undefined,
}),
),
).toString('utf8');
+1
View File
@@ -1,3 +1,4 @@
import { eventHandler, setResponseHeader } from 'h3';
import iconMetaData from '../../data/iconMetaData';
export default eventHandler((event) => {
-3
View File
@@ -1,3 +0,0 @@
export default eventHandler(() => {
return { nitro: 'Is Awesome! asda' };
});
+31 -1
View File
@@ -1,6 +1,7 @@
import { fileURLToPath, URL } from 'node:url';
import { defineConfig } from 'vitepress';
import sidebar from './sidebar';
import getStructuredData from './getStructuredData';
const title = 'Lucide';
const socialTitle = 'Lucide Icons';
@@ -9,6 +10,7 @@ const description = 'Beautiful & consistent icon toolkit made by the community.'
// https://vitepress.dev/reference/site-config
export default defineConfig({
title,
titleTemplate: ':title \u2013 Lucide',
description,
cleanUrls: true,
outDir: '.vercel/output/static',
@@ -150,8 +152,36 @@ export default defineConfig({
},
],
],
async transformPageData(pageData) {
if (
pageData.relativePath.startsWith('icons/') &&
!pageData.relativePath.startsWith('icons/lab/') &&
pageData.params?.name
) {
const iconName = pageData.params.name;
pageData.title = `${iconName} icon details`;
const taggedAs = pageData.params?.tags?.length
? `Tagged as: ${pageData.params.tags.join(', ')}.`
: '';
const categorizedIn = pageData.params?.category?.length
? `Categorized in: ${pageData.params.category.join(', ')}.`
: '';
pageData.description =
`Details and related icons for ${iconName} icon. ${taggedAs} ${categorizedIn}`.trim();
const structuredData = await getStructuredData(iconName, pageData);
pageData.frontmatter.head ??= [];
pageData.frontmatter.head.push([
'script',
{ type: 'application/ld+json' },
JSON.stringify(structuredData),
]);
}
},
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
logo: {
light: '/logo.light.svg',
dark: '/logo.dark.svg',
@@ -171,5 +171,43 @@
],
"source": "https://github.com/heyvito/lucide-rails",
"documentation": "https://github.com/heyvito/lucide-rails/blob/master/README.md"
},
{
"name": "lucide-web-components",
"description": "Implementation of Lucide icons in Web Components custom elements.",
"icon": "/framework-logos/web-components.svg",
"shields": [
{
"alt": "Latest Stable Version",
"src": "https://img.shields.io/npm/v/@dile/iconlib",
"href": "https://dile-components.com/icons/lucide-icons/"
},
{
"alt": "Total Downloads",
"src": "https://img.shields.io/npm/dt/@dile/iconlib",
"href": "https://dile-components.com/icons/lucide-icons/"
}
],
"source": "https://github.com/Polydile/dile-components",
"documentation": "https://github.com/Polydile/dile-components/blob/master/packages/iconlib/README.md"
},
{
"name": "strapi-lucide-icons",
"description": "Lucide icon picker custom field for Strapi.",
"icon": "/framework-logos/strapi.svg",
"shields": [
{
"alt": "Latest Stable Version",
"src": "https://img.shields.io/npm/v/strapi-lucide-icons",
"href": "https://www.npmjs.com/package/strapi-lucide-icons"
},
{
"alt": "Total Downloads",
"src": "https://img.shields.io/npm/dw/strapi-lucide-icons",
"href": "https://www.npmjs.com/package/strapi-lucide-icons"
}
],
"source": "https://github.com/shx08/strapi-lucide-icons",
"documentation": "https://github.com/shx08/strapi-lucide-icons/blob/main/README.md"
}
]
+46
View File
@@ -0,0 +1,46 @@
import { PageData } from 'vitepress';
export default async function getStructuredData(iconName: string, pageData: PageData) {
const url = `https://lucide.dev/icons/${iconName}`;
return {
'@context': 'https://schema.org',
'@type': 'WebPage',
'@id': url,
name: pageData.title,
description: pageData.description,
url,
inLanguage: 'en',
isPartOf: {
'@type': 'WebSite',
name: 'Lucide Icons',
url: 'https://lucide.dev',
},
breadcrumb: {
'@type': 'BreadcrumbList',
itemListElement: [
{ '@type': 'ListItem', position: 1, name: 'Icons', item: 'https://lucide.dev/icons' },
{ '@type': 'ListItem', position: 2, name: iconName, item: url },
],
},
mainEntity: {
'@type': 'ImageObject',
'@id': `${url}#icon`,
name: iconName,
// TODO: Add support for description extraction from icon metadata
// description: 'An ...SVG icon from the Lucide icon set.',
contentUrl: `https://lucide.dev/api/icons/${iconName}}?width=24&height=24&background=white`,
thumbnailUrl: `https://lucide.dev/api/icons/${iconName}}?width=256&height=256&background=white`,
encodingFormat: 'image/svg+xml',
keywords: pageData.params?.tags,
width: 24,
height: 24,
creator: {
'@type': 'Organization',
name: 'Lucide Icons',
},
datePublished: pageData?.params?.createdRelease?.date,
dateModified: pageData?.params?.changedRelease?.date,
},
};
}
+1 -1
View File
@@ -1,4 +1,4 @@
import React from 'react';
import React, { Fragment } from 'react';
interface BackdropProps {
src: string;
+14 -11
View File
@@ -1,4 +1,4 @@
import React from 'react';
import React, { Fragment } from 'react';
import { PathProps, Path } from './types';
import getPaths, { assert } from './utils';
import { GapViolationHighlight } from './GapViolationHighlight.tsx';
@@ -389,15 +389,18 @@ const Handles = ({
</g>
);
const SvgPreview = React.forwardRef<
SVGSVGElement,
{
height?: number;
width?: number;
src: string | ReturnType<typeof getPaths>;
showGrid?: boolean;
} & React.SVGProps<SVGSVGElement>
>(({ src, children, height = 24, width = 24, showGrid = false, ...props }, ref) => {
interface SvgPreviewProps extends React.SVGProps<SVGSVGElement> {
height?: number;
width?: number;
src: string | ReturnType<typeof getPaths>;
showGrid?: boolean;
children?: React.ReactNode;
}
const SvgPreview = (
{ src, children, height = 24, width = 24, showGrid = false, ...props }: SvgPreviewProps,
ref,
) => {
const subGridSize =
Math.max(height, width) % 3 === 0
? Math.max(height, width) > 24
@@ -494,7 +497,7 @@ const SvgPreview = React.forwardRef<
{children}
</svg>
);
});
};
SvgPreview.displayName = 'SvgPreview';
@@ -1,4 +1,4 @@
import memoize from 'lodash/memoize';
import { memoize } from 'lodash-es';
import SVGPathCommander from 'svg-path-commander';
import { Path } from './types';
+1 -1
View File
@@ -8,7 +8,7 @@ export type Path = {
prev: Point;
next: Point;
isStart: boolean;
circle?: { x: number; y: number; r: number };
circle?: { x: number; y: number; r: number; tangentIntersection?: Point };
cp1?: Point;
cp2?: Point;
c: ReturnType<typeof getCommands>[number];
+1 -3
View File
@@ -1,10 +1,8 @@
import { INode, parseSync } from 'svgson';
// @ts-ignore
import toPath from 'element-to-path';
// @ts-ignore
import { SVGPathData, encodeSVGPath } from 'svg-pathdata';
import { Path, Point } from './types';
import memoize from 'lodash/memoize';
import { memoize } from 'lodash-es';
function assertNever(x: never): never {
throw new Error('Unknown type: ' + x['type']);
@@ -113,16 +113,16 @@ import { LucideAngularModule, $PascalCase } from 'lucide-angular';
];
};
const highlighter = await createHighlighter({
themes: ['github-light', 'github-dark'],
langs: Object.keys(bundledLanguages),
});
export type ThemeOptions =
| ThemeRegistration
| { light: ThemeRegistration; dark: ThemeRegistration };
const highLightCode = async (code: string, lang: string, active?: boolean) => {
const highlighter = await createHighlighter({
themes: ['github-light', 'github-dark'],
langs: Object.keys(bundledLanguages),
});
export const highLightCode = async (code: string, lang: string, active?: boolean) => {
const highlightedCode = highlighter
.codeToHtml(code, {
lang,
@@ -1,5 +1,4 @@
import { bundledLanguages, type ThemeRegistration } from 'shiki';
import { createHighlighter } from 'shiki';
import { highLightCode } from './createCodeExamples';
type CodeExampleType = {
title: string;
@@ -105,45 +104,17 @@ import { $CamelCase } from '@lucide/lab';
@NgModule({
imports: [
LucideAngularModule.pick({ $CamelCase })
LucideAngularModule.pick({ $PascalCase: $CamelCase })
],
})
// app.component.html
<lucide-icon name="$CamelCase"></lucide-icon>
<lucide-icon name="$PascalCase"></lucide-icon>
`,
},
];
};
export type ThemeOptions =
| ThemeRegistration
| { light: ThemeRegistration; dark: ThemeRegistration };
const highLightCode = async (code: string, lang: string, active?: boolean) => {
const highlighter = await createHighlighter({
themes: ['github-light', 'github-dark'],
langs: Object.keys(bundledLanguages),
});
const highlightedCode = highlighter
.codeToHtml(code, {
lang,
themes: {
light: 'github-light',
dark: 'github-dark',
},
defaultColor: false,
})
.replace('shiki-themes', 'shiki-themes vp-code');
return `<div class="language-${lang} ${active ? 'active' : ''}">
<button title="Copy Code" class="copy"></button>
<span class="lang">${lang}</span>
${highlightedCode}
</div>`;
};
export default async function createCodeExamples() {
const codes = getIconCodes();
+1 -1
View File
@@ -1,5 +1,5 @@
import { createLucideIcon } from 'lucide-react/src/lucide-react';
import { type LucideProps, type IconNode } from 'lucide-react/src/createLucideIcon';
import { type LucideProps, type IconNode } from 'lucide-react/src/types';
import { IconEntity } from '../theme/types';
import { renderToStaticMarkup } from 'react-dom/server';
import { IconContent } from './generateZip';
@@ -1,23 +1,31 @@
<script setup lang="ts">
import { useData } from 'vitepress';
import { computed } from 'vue';
const props = defineProps<{
modelValue: string
id: string
}>()
modelValue: string;
id: string;
}>();
const emit = defineEmits(['update:modelValue'])
const { isDark } = useData();
const emit = defineEmits(['update:modelValue']);
const value = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
get: () => {
if (props.modelValue == null || props.modelValue === 'currentColor') {
return isDark.value ? '#ffffff' : '#000000';
}
return props.modelValue;
},
set: (val) => emit('update:modelValue', val),
});
</script>
<template>
<div class="color-picker">
<div class="color-input-wrapper">
<!-- TODO: Add currentColor div if value is currentColor -->
<input
type="color"
:id="id"
@@ -33,6 +41,7 @@ const value = computed({
class="color-input-text"
aria-label="Color picker input"
v-model="value"
placeholder="[default]"
/>
</div>
</template>
@@ -45,27 +54,33 @@ const value = computed({
top: -5px;
left: -5px;
}
.color-input-wrapper {
height: 24px;
width: 24px;
overflow: hidden;
position: relative;
border-radius: 12px;
border-radius: 4px;
flex-shrink: 0;
}
.color-picker {
background: var(--color-picker-bg, var(--vp-c-bg-alt));
border-radius: 8px;
color: var(--vp-c-text-2);
padding: 4px 8px;
padding: 3px 8px 3px 3px;
height: auto;
font-size: 14px;
font-size: 13px;
text-align: left;
border: 1px solid transparent;
cursor: text;
display: flex;
align-items: center;
gap: 2px;
transition:
color 0.25s,
border-color 0.25s,
background-color 0.25s;
}
.color-input-text {
@@ -75,19 +90,24 @@ const value = computed({
border: none;
background: transparent;
color: var(--vp-c-text-1);
font-size: 14px;
font-size: 13px;
text-align: left;
border-radius: 8px;
cursor: text;
transition: border-color 0.25s, background 0.4s ease;
transition:
border-color 0.25s,
background 0.4s ease;
letter-spacing: 1px;
}
.color-picker:hover, .color-picker:focus {
.color-picker:hover,
.color-picker:focus-within {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg-alt);
}
.color-picker:focus-within {
background-color: var(--vp-c-bg);
}
.color-input[value="currentColor"] {
.color-input[value='currentColor'] {
}
</style>
@@ -1,22 +1,27 @@
<script setup>
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
import { search } from '../../../data/iconNodes'
const SearchIcon = createLucideIcon('search', search)
import Icon from 'lucide-vue-next/src/Icon';
import { search } from '../../../data/iconNodes';
defineProps({
shortcut: {
type: String,
required: false
}
})
required: false,
},
});
</script>
<template>
<button class="fake-input">
<component :is="SearchIcon" class="search-icon"/>
<slot/>
<kbd v-if="shortcut" class="shortcut">{{ shortcut }}</kbd>
<Icon
:iconNode="search"
class="search-icon"
/>
<slot />
<kbd
v-if="shortcut"
class="shortcut"
>{{ shortcut }}</kbd
>
</button>
</template>
@@ -34,12 +39,15 @@ defineProps({
cursor: text;
display: flex;
gap: 12px;
transition: color 0.25s, border-color 0.25s, background-color 0.25s;
transition:
color 0.25s,
border-color 0.25s,
background-color 0.25s;
}
.fake-input:hover, .fake-input:focus {
.fake-input:hover,
.fake-input:focus {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg-alt);
}
.shortcut {
@@ -5,7 +5,6 @@
</template>
<style scoped>
.icon-button {
display: inline-flex;
border: 1px solid transparent;
@@ -30,9 +29,9 @@
}
.icon-button:active {
border-color: var(--vp-button-alt-active-border);
color: var(--vp-button-alt-active-text);
background-color: var(--vp-button-alt-active-bg);
border-color: var(--vp-button-alt-active-border);
color: var(--vp-button-alt-active-text);
background-color: var(--vp-button-alt-active-bg);
}
.icon-button.active {
+101 -27
View File
@@ -1,60 +1,93 @@
<script lang="ts">
export default {
inheritAttrs: false,
}
};
export interface InputProps {
type: string
modelValue: string
shortcut?: string
type: string;
modelValue: string;
shortcut?: string;
}
</script>
<script setup lang="ts">
import { ref, onMounted, nextTick, watch } from 'vue'
import { ref, onMounted, nextTick, watch } from 'vue';
import Icon from 'lucide-vue-next/src/Icon';
import { x } from '../../../data/iconNodes';
import IconButton from './IconButton.vue';
const props = withDefaults(defineProps<InputProps>(), {
type: 'text'
})
type: 'text',
});
const input = ref()
const wrapperEl = ref()
const shortcutEl = ref()
const input = ref();
const wrapperEl = ref();
const shortcutEl = ref();
defineEmits(['change', 'input', 'update:modelValue'])
const emit = defineEmits(['change', 'input', 'update:modelValue']);
const updateShortcutSpacing = () => {
nextTick(() => {
if (shortcutEl.value && wrapperEl.value) {
const shortcutWidth = shortcutEl.value.offsetWidth
wrapperEl.value.style.setProperty('--shortcut-width', `${shortcutWidth}px`)
const shortcutWidth = shortcutEl.value.offsetWidth;
wrapperEl.value.style.setProperty('--shortcut-width', `${shortcutWidth}px`);
}
})
}
});
};
onMounted(updateShortcutSpacing)
watch(() => props.shortcut, updateShortcutSpacing)
const isMac = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);
onMounted(updateShortcutSpacing);
watch(() => props.shortcut, updateShortcutSpacing);
function onClear() {
emit('update:modelValue', '');
input.value.focus();
}
defineExpose({
focus: () => {
input.value.focus()
}
})
input.value.focus();
},
});
</script>
<template>
<div class="input-wrapper" ref="wrapperEl">
<slot name="icon" class="icon" />
<div
class="input-wrapper"
ref="wrapperEl"
>
<slot
name="icon"
class="icon"
/>
<input
:type="type"
class="input"
:class="{'has-icon': $slots.icon, 'has-shortcut': shortcut}"
:class="{ 'has-icon': $slots.icon, 'has-shortcut': shortcut }"
ref="input"
:value="modelValue"
v-bind="$attrs"
@input="$emit('update:modelValue', $event.target.value)"
/>
<kbd v-if="shortcut" class="shortcut" ref="shortcutEl">{{ shortcut }}</kbd>
<IconButton
@click="onClear"
v-if="type === 'search' && modelValue"
class="clear-button"
aria-label="Clear input"
:style="{ right: isMac ? '50px' : '68px' }"
>
<Icon
:iconNode="x"
:size="20"
/>
</IconButton>
<kbd
v-if="shortcut"
class="shortcut"
ref="shortcutEl"
>{{ shortcut }}</kbd
>
</div>
</template>
@@ -62,6 +95,7 @@ defineExpose({
.input-wrapper {
position: relative;
}
.input {
justify-content: flex-start;
border: 1px solid transparent;
@@ -71,21 +105,36 @@ defineExpose({
height: 40px;
background-color: var(--vp-c-bg-alt);
font-size: 14px;
transition:
color 0.25s,
border-color 0.25s,
background-color 0.25s;
}
.input.has-shortcut {
padding-right: calc(var(--shortcut-width, 40px) + 22px);
}
.input:hover, .input:focus {
.input:hover,
.input:focus {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg-alt);
}
.input:focus {
background-color: var(--vp-c-bg);
}
.input.has-icon {
padding-left: 52px;
}
.clear-button {
position: absolute;
right: 68px;
top: 9px;
padding: 4px;
transition: background-color .25s;
}
.shortcut {
position: absolute;
right: 12px;
@@ -103,15 +152,37 @@ defineExpose({
pointer-events: none;
}
.input[type="search"]::-webkit-search-cancel-button {
-webkit-appearance: none;
appearance: none;
display: none;
}
.input[type="search"]::-ms-clear {
display: none;
}
.input[type="search"]::-o-clear {
display: none;
}
.input[type="search"]::-moz-clear {
display: none;
}
@media (hover: none) {
.shortcut {
display: none;
}
.clear-button {
right: 16px !important;
}
}
</style>
<style>
.input-wrapper svg {
.input-wrapper > svg {
position: absolute;
left: 16px;
top: 12px;
@@ -119,4 +190,7 @@ defineExpose({
color: var(--vp-c-text-2);
pointer-events: none;
}
.input-wrapper > svg:has(+ .input.has-icon:focus) {
color: var(--vp-c-text-1);
}
</style>
@@ -1,38 +1,36 @@
<script lang="ts">
export default {
inheritAttrs: false,
}
};
</script>
<script setup lang="ts">
import { computed, ref } from 'vue'
import Input from './Input.vue'
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
import { search } from '../../../data/iconNodes'
const SearchIcon = createLucideIcon('search', search)
import { computed, ref } from 'vue';
import Input from './Input.vue';
import Icon from 'lucide-vue-next/src/Icon';
import { search } from '../../../data/iconNodes';
interface Props {
modelValue: string
shortcut?: string
modelValue: string;
shortcut?: string;
}
const props = defineProps<Props>()
const props = defineProps<Props>();
const input = ref()
const input = ref();
const emit = defineEmits(['update:modelValue'])
const emit = defineEmits(['update:modelValue']);
defineExpose({
focus: () => {
input.value.focus()
}
})
input.value.focus();
},
});
const value = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
set: (val) => emit('update:modelValue', val),
});
</script>
<template>
@@ -46,7 +44,10 @@ const value = computed({
class="input-wrapper"
>
<template #icon>
<component :is="SearchIcon" class="search-icon" />
<Icon
:iconNode="search"
class="search-icon"
/>
</template>
</Input>
</template>
@@ -62,7 +63,8 @@ const value = computed({
background-color: var(--vp-c-bg-alt);
}
.input:hover, .input:focus {
.input:hover,
.input:focus {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg-alt);
}
@@ -1,14 +1,15 @@
<script setup lang="ts">
import { rotateCw } from '../../../data/iconNodes'
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
import IconButton from "./IconButton.vue";
const RotateIcon = createLucideIcon('RotateIcon', rotateCw)
import { rotateCw } from '../../../data/iconNodes';
import Icon from 'lucide-vue-next/src/Icon';
import IconButton from './IconButton.vue';
</script>
<template>
<IconButton class="reset-button">
<RotateIcon :size="20"/>
<Icon
:size="20"
:iconNode="rotateCw"
/>
</IconButton>
</template>
@@ -32,6 +33,7 @@ const RotateIcon = createLucideIcon('RotateIcon', rotateCw)
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(359deg);
}
@@ -22,16 +22,16 @@ export default {
logo: '/framework-logos/svelte.svg',
label: 'Lucide documentation for Svelte',
},
{
name: 'lucide-preact',
logo: '/framework-logos/preact.svg',
label: 'Lucide documentation for Preact',
},
{
name: 'lucide-solid',
logo: '/framework-logos/solid.svg',
label: 'Lucide documentation for Solid',
},
{
name: 'lucide-preact',
logo: '/framework-logos/preact.svg',
label: 'Lucide documentation for Preact',
},
{
name: 'lucide-angular',
logo: '/framework-logos/angular.svg',
@@ -48,11 +48,6 @@ export default {
logo: '/framework-logos/react-native.svg',
label: 'Lucide documentation for React Native',
},
{
name: 'lucide-flutter',
logo: '/framework-logos/flutter.svg',
label: 'Lucide documentation for Flutter',
},
],
};
},
@@ -2,45 +2,48 @@
import { useData } from 'vitepress';
import { useSessionStorage } from '@vueuse/core';
import IconButton from '../base/IconButton.vue';
import VPDocAsideCarbonAds from 'vitepress/dist/client/theme-default/components/VPDocAsideCarbonAds.vue'
import { x } from '../../../data/iconNodes'
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
import VPDocAsideCarbonAds from 'vitepress/dist/client/theme-default/components/VPDocAsideCarbonAds.vue';
import { x } from '../../../data/iconNodes';
import Icon from 'lucide-vue-next/src/Icon';
import { onMounted, ref } from 'vue';
const { theme } = useData()
const showAd = useSessionStorage('show-carbon-ads', true)
const carbonLoaded = ref(true)
const { theme } = useData();
const showAd = useSessionStorage('show-carbon-ads', true);
const carbonLoaded = ref(true);
defineProps<{
drawerOpen: boolean
}>()
const CloseIcon = createLucideIcon('Close', x)
drawerOpen: boolean;
}>();
onMounted(() => {
setTimeout(() => {
if (window?._carbonads == null) {
carbonLoaded.value = false
carbonLoaded.value = false;
}
}, 5000)
})
}, 5000);
});
</script>
<template>
<div
:class="{
'drawer-open': drawerOpen,
'hide-ad': !(showAd && carbonLoaded)
'hide-ad': !(showAd && carbonLoaded),
}"
class="floating-ad"
v-if="theme.carbonAds"
>
<IconButton @click="showAd = false" class="hide-button">
<component :is="CloseIcon" :size="20" absoluteStrokeWidth />
<IconButton
@click="showAd = false"
class="hide-button"
>
<Icon
:iconNode="x"
:size="20"
absoluteStrokeWidth
/>
</IconButton>
<VPDocAsideCarbonAds
:carbon-ads="theme.carbonAds"
/>
<VPDocAsideCarbonAds :carbon-ads="theme.carbonAds" />
</div>
</template>
@@ -51,7 +54,9 @@ onMounted(() => {
bottom: 32px;
width: 224px;
right: 32px;
transition: opacity 0.5s, transform 0.25s ease;
transition:
opacity 0.5s,
transform 0.25s ease;
}
.floating-ad.drawer-open {
@@ -67,8 +72,11 @@ onMounted(() => {
transform: translateY(-288px) translateX(224px);
}
.floating-ad.drawer-open, .floating-ad.hide-ad {
transition: opacity 0.25s, transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
.floating-ad.drawer-open,
.floating-ad.hide-ad {
transition:
opacity 0.25s,
transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
}
@media (min-width: 1280px) {
@@ -1,70 +1,68 @@
<script setup lang="ts">
import { ref } from 'vue';
import ButtonMenu from '../base/ButtonMenu.vue'
import ButtonMenu from '../base/ButtonMenu.vue';
import { useIconStyleContext } from '../../composables/useIconStyle';
import useConfetti from '../../composables/useConfetti';
import getSVGIcon from '../../utils/getSVGIcon';
import downloadData from '../../utils/downloadData';
const downloadText = 'Download!'
const copiedText = 'Copied!'
const confettiText = ref(copiedText)
const downloadText = 'Download!';
const copiedText = 'Copied!';
const confettiText = ref(copiedText);
const props = defineProps<{
name: string
popoverPosition?: 'top' | 'bottom'
}>()
name: string;
popoverPosition?: 'top' | 'bottom';
}>();
const { size } = useIconStyleContext()
const { size } = useIconStyleContext();
const { animate, confetti } = useConfetti()
const { animate, confetti } = useConfetti();
function copySVG() {
confettiText.value = copiedText
const svgString = getSVGIcon()
confettiText.value = copiedText;
const svgString = getSVGIcon();
navigator.clipboard.writeText(svgString)
navigator.clipboard.writeText(svgString);
confetti()
confetti();
}
function copyDataUrl() {
confettiText.value = copiedText
const svgString = getSVGIcon()
confettiText.value = copiedText;
const svgString = getSVGIcon();
// Create SVG data url
const dataUrl = `data:image/svg+xml;base64,${btoa(svgString)}`
navigator.clipboard.writeText(dataUrl)
const dataUrl = `data:image/svg+xml;base64,${btoa(svgString)}`;
navigator.clipboard.writeText(dataUrl);
confetti()
confetti();
}
function downloadSVG() {
confettiText.value = downloadText
const svgString = getSVGIcon()
confettiText.value = downloadText;
const svgString = getSVGIcon();
downloadData(`${props.name}.svg`, `data:image/svg+xml;base64,${btoa(svgString)}`)
confetti()
downloadData(`${props.name}.svg`, `data:image/svg+xml;base64,${btoa(svgString)}`);
confetti();
}
function downloadPNG() {
confettiText.value = downloadText
const svgString = getSVGIcon()
confettiText.value = downloadText;
const svgString = getSVGIcon();
const canvas = document.createElement('canvas');
canvas.width = size.value;
canvas.height = size.value;
const ctx = canvas.getContext("2d");
const ctx = canvas.getContext('2d');
const image = new Image();
image.src = `data:image/svg+xml;base64,${btoa(svgString)}`;
image.onload = function() {
image.onload = function () {
ctx.drawImage(image, 0, 0);
downloadData(`${props.name}.png`, canvas.toDataURL('image/png'))
confetti()
}
downloadData(`${props.name}.png`, canvas.toDataURL('image/png'));
confetti();
};
}
</script>
<template>
@@ -75,10 +73,10 @@ function downloadPNG() {
:data-confetti-text="confettiText"
:popoverPosition="popoverPosition"
:options="[
{ text: 'Copy SVG' , onClick: copySVG },
{ text: 'Copy Data URL' , onClick: copyDataUrl },
{ text: 'Download SVG' , onClick: downloadSVG },
{ text: 'Download PNG' , onClick: downloadPNG },
{ text: 'Copy SVG', onClick: copySVG },
{ text: 'Copy Data URL', onClick: copyDataUrl },
{ text: 'Download SVG', onClick: downloadSVG },
{ text: 'Download PNG', onClick: downloadPNG },
]"
/>
</template>
@@ -1,41 +1,44 @@
<script setup lang="ts">
import { computed, useSlots } from 'vue';
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
import { copy } from '../../../data/iconNodes'
import { copy } from '../../../data/iconNodes';
import useConfetti from '../../composables/useConfetti';
const { animate, confetti } = useConfetti()
const slots = useSlots()
import Icon from 'lucide-vue-next/src/Icon';
const { animate, confetti } = useConfetti();
const slots = useSlots();
const copiedText = computed(() => slots.default?.()[0].children)
const copiedText = computed(() => slots.default?.()[0].children);
function copyText() {
navigator.clipboard.writeText(copiedText.value)
navigator.clipboard.writeText(copiedText.value);
confetti()
confetti();
}
const Copy = createLucideIcon('ChevronUp', copy)
</script>
<template>
<h1
class="icon-name confetti-button"
:class="{animate}"
:class="{ animate }"
data-confetti-text="Copied!"
@click="copyText"
>
<slot />
<Copy :size="20" class="copy-icon"/>
<Icon
:iconNode="copy"
:size="20"
class="copy-icon"
/>
</h1>
</template>
<style scoped>
@import './confetti.css';
.icon-name {
font-size: 24px;
font-weight: 500;
line-height: 32px;
transition: background ease-in .15s;;
transition: background ease-in 0.15s;
padding: 2px 8px;
border-radius: 8px;
width: auto;
@@ -48,7 +51,7 @@ const Copy = createLucideIcon('ChevronUp', copy)
}
.icon-name:hover .copy-icon {
opacity: .9;
opacity: 0.9;
}
.icon-name:before,
@@ -65,10 +68,10 @@ const Copy = createLucideIcon('ChevronUp', copy)
opacity: 0;
margin-left: 12px;
margin-top: 6px;
transition:ease .3s opacity;
transition: ease 0.3s opacity;
}
.icon-name:hover .copy-icon:hover {
opacity: .6;
opacity: 0.6;
}
</style>
@@ -153,7 +153,7 @@ function handleCloseDrawer() {
>
<StickyBar class="category-search">
<InputSearch
:placeholder="`Search ${icons.length} icons ...`"
:placeholder="`Search ${icons.length} icons…`"
v-model="searchQuery"
:shortcut="kbdSearchShortcut"
class="input-wrapper"
@@ -129,7 +129,7 @@ function handleCloseDrawer() {
>
<StickyBar>
<InputSearch
:placeholder="`Search ${icons.length} icons ...`"
:placeholder="`Search ${icons.length} icons…`"
v-model="searchQuery"
ref="searchInput"
:shortcut="kbdSearchShortcut"
@@ -1,75 +1,72 @@
<script setup lang="ts">
import { shallowRef, type Ref, watch, computed } from 'vue'
import { useCssVar, syncRef } from '@vueuse/core'
import { STYLE_DEFAULTS, useIconStyleContext } from '../../composables/useIconStyle'
import RangeSlider from '../base/RangeSlider.vue'
import InputField from '../base/InputField.vue'
import ColorPicker from '../base/ColorPicker.vue'
import ResetButton from '../base/ResetButton.vue'
import Switch from '../base/Switch.vue'
import { shallowRef, type Ref, watch, computed } from 'vue';
import { useCssVar, syncRef } from '@vueuse/core';
import { STYLE_DEFAULTS, useIconStyleContext } from '../../composables/useIconStyle';
import RangeSlider from '../base/RangeSlider.vue';
import InputField from '../base/InputField.vue';
import ColorPicker from '../base/ColorPicker.vue';
import ResetButton from '../base/ResetButton.vue';
import Switch from '../base/Switch.vue';
const props = defineProps<{
rootEl?: Ref<HTMLElement>
}>()
rootEl?: Ref<HTMLElement>;
}>();
const { color, strokeWidth, size, absoluteStrokeWidth } = useIconStyleContext()
const documentRef = shallowRef<HTMLElement | undefined>(typeof document !== 'undefined' ? document?.documentElement : undefined)
const { color, strokeWidth, size, absoluteStrokeWidth } = useIconStyleContext();
const documentRef = shallowRef<HTMLElement | undefined>(
typeof document !== 'undefined' ? document?.documentElement : undefined,
);
const colorCssVar = useCssVar(
'--customize-color',
props.rootEl?.value ?? documentRef.value,
{
initialValue: `${STYLE_DEFAULTS.color}`
}
)
const colorCssVar = useCssVar('--customize-color', props.rootEl?.value ?? documentRef.value, {
initialValue: `${STYLE_DEFAULTS.color}`,
});
const strokeWidthCssVar = useCssVar(
'--customize-strokeWidth',
props.rootEl?.value ?? documentRef.value,
{
initialValue: `${STYLE_DEFAULTS.strokeWidth}`
}
)
initialValue: `${STYLE_DEFAULTS.strokeWidth}`,
},
);
const sizeCssVar = useCssVar(
'--customize-size',
props.rootEl?.value ?? documentRef.value,
{
initialValue: `${STYLE_DEFAULTS.size}`
}
)
const sizeCssVar = useCssVar('--customize-size', props.rootEl?.value ?? documentRef.value, {
initialValue: `${STYLE_DEFAULTS.size}`,
});
syncRef(color, colorCssVar, { direction: 'ltr' })
syncRef(strokeWidth, strokeWidthCssVar, { direction: 'ltr' })
syncRef(size, sizeCssVar, { direction: 'ltr' })
syncRef(color, colorCssVar, { direction: 'ltr' });
syncRef(strokeWidth, strokeWidthCssVar, { direction: 'ltr' });
syncRef(size, sizeCssVar, { direction: 'ltr' });
function resetStyle () {
color.value = STYLE_DEFAULTS.color
strokeWidth.value = STYLE_DEFAULTS.strokeWidth
size.value = STYLE_DEFAULTS.size
absoluteStrokeWidth.value = STYLE_DEFAULTS.absoluteStrokeWidth
function resetStyle() {
color.value = STYLE_DEFAULTS.color;
strokeWidth.value = STYLE_DEFAULTS.strokeWidth;
size.value = STYLE_DEFAULTS.size;
absoluteStrokeWidth.value = STYLE_DEFAULTS.absoluteStrokeWidth;
}
watch(absoluteStrokeWidth, (enabled) => {
const htmlEl = document.documentElement
const htmlEl = document.documentElement;
htmlEl.classList.toggle('absolute-stroke-width', enabled)
})
htmlEl.classList.toggle('absolute-stroke-width', enabled);
});
const customizingActive = computed(() => {
return color.value !== STYLE_DEFAULTS.color
|| strokeWidth.value !== STYLE_DEFAULTS.strokeWidth
|| size.value !== STYLE_DEFAULTS.size
|| absoluteStrokeWidth.value !== STYLE_DEFAULTS.absoluteStrokeWidth
})
return (
color.value !== STYLE_DEFAULTS.color ||
strokeWidth.value !== STYLE_DEFAULTS.strokeWidth ||
size.value !== STYLE_DEFAULTS.size ||
absoluteStrokeWidth.value !== STYLE_DEFAULTS.absoluteStrokeWidth
);
});
</script>
<template>
<div class="customizer-card" :class="{ customized: customizingActive }">
<div
class="customizer-card"
:class="{ customized: customizingActive }"
>
<div class="card-header">
<h2 class="card-title">
Customizer
</h2>
<h2 class="card-title">Customizer</h2>
<ResetButton @click="resetStyle"></ResetButton>
</div>
<InputField
@@ -77,7 +74,11 @@ const customizingActive = computed(() => {
label="Color"
>
<template #display>
<ColorPicker v-model="color" id="icon-color" class="color-picker"/>
<ColorPicker
v-model="color"
id="icon-color"
class="color-picker"
/>
</template>
</InputField>
@@ -117,7 +118,7 @@ const customizingActive = computed(() => {
<InputField
id="absolute-stroke-width"
label="Absolute Stroke width"
label="Absolute stroke width"
>
<Switch
id="absolute-stroke-width"
@@ -143,6 +144,7 @@ const customizingActive = computed(() => {
font-size: 16px;
/* margin-bottom: 12px; */
}
.customizer-card {
background: var(--vp-c-bg);
padding: 12px 24px 24px;
@@ -151,7 +153,7 @@ const customizingActive = computed(() => {
position: relative;
z-index: 0;
border: 1px solid transparent;
transition: border-color .4s ease-in-out;
transition: border-color 0.4s ease-in-out;
}
.customizer-card.customized {
@@ -1,4 +1,4 @@
import { IconNode } from 'lucide-vue-next/src/createLucideIcon';
import { type IconNode } from 'lucide-vue-next/src/types';
import Vue from 'vue';
declare module '*.vue' {
@@ -20,5 +20,6 @@ declare module 'node:module' {
}
declare module '*.node.json' {
export default IconNode;
const value: IconNode;
export default value;
}
+2
View File
@@ -1,5 +1,7 @@
---
aside: false
title: Contributing to Lucide
description: Guidelines and instructions for contributing to the Lucide project.
---
<!--@include: ../CONTRIBUTING.md -->
+5
View File
@@ -10,6 +10,11 @@ because they can quickly give information.
However, not everyone can understand them easily. When using icons it is very important to consider
the following aspects of accessibility.
::: info
By default, we hide icons from screen readers using `aria-hidden="true"`.
You can make them accessible yourself by following the guidelines below.
:::
## Provide visible labels
Icons are a helpful tool to improve perception, but they aren't a replacement for text.
+9
View File
@@ -90,6 +90,15 @@ Here are rules that should be followed to keep quality and consistency when maki
**Tip:** whenever possible align elements and arc centers to the grid.
### 14. Icons should share common shapes
You should try to create consistent groups and variants, reuse and try to create uniformity.
Consistency inside groups and variants has a lower priority than the rules above.
**Example:** All `-off` icons should look the same unless it for example violates the optical volume rule.
**Tip:** Try to not move the base shape to enable better use in a toggle context.
## Naming conventions
1. Icon names use lower kebab case.\
+5 -4
View File
@@ -91,22 +91,23 @@ Implementation of the lucide icon library for Svelte applications.
::: code-group
```sh [pnpm]
pnpm add lucide-svelte
pnpm add @lucide/svelte
```
```sh [yarn]
yarn add lucide-svelte
yarn add @lucide/svelte
```
```sh [npm]
npm install lucide-svelte
npm install @lucide/svelte
```
```sh [bun]
bun add lucide-svelte
bun add @lucide/svelte
```
:::
> `@lucide/svelte` is only for Svelte 5, for Svelte 4 use the `lucide-svelte` package.
For more details, see the [documentation](packages/lucide-svelte.md).
+12
View File
@@ -167,3 +167,15 @@ import { coconut } from '@lucide/lab';
})
export class AppModule { }
```
## Accessibility
By default, we hide icons from screen readers using `aria-hidden="true"`.
You can add accessibility attributes using aria-labels.
```html
<lucide-icon name="check" aria-label="Task completed"></lucide-icon>
```
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
+16
View File
@@ -192,3 +192,19 @@ import LucideIcon from './LucideIcon.astro';
<LucideIcon name="Menu" />
```
## Accessibility
By default, we hide icons from screen readers using `aria-hidden="true"`.
You can add accessibility attributes using aria-labels.
```jsx
---
import { Check } from '@lucide/astro';
---
<Check aria-label="Task completed" />
```
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
+16
View File
@@ -131,3 +131,19 @@ const App = () => {
export default App;
```
## Accessibility
By default, we hide icons from screen readers using `aria-hidden="true"`.
You can add accessibility attributes using aria-labels.
```jsx
import { Check } from 'lucide-preact';
const App = () => {
return <Check aria-label="Task completed" />;
};
```
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
+11 -5
View File
@@ -102,10 +102,16 @@ The example below imports all ES Modules, so exercise caution when using it. Imp
### Icon Component Example
```jsx
import { icons } from 'lucide-react-native';
```tsx
import * as icons from 'lucide-react-native/icons';
const Icon = ({ name, color, size }) => {
interface IconProps {
name: keyof typeof icons;
color?: string;
size?: number;
}
const Icon = ({ name, color, size }: IconProps) => {
const LucideIcon = icons[name];
return <LucideIcon color={color} size={size} />;
@@ -116,11 +122,11 @@ export default Icon;
#### Using the Icon Component
```jsx
```tsx
import Icon from './Icon';
const App = () => {
return <Icon name="house" />;
return <Icon name="House" />;
};
export default App;
+16
View File
@@ -109,3 +109,19 @@ const App = () => (
<DynamicIcon name="camera" color="red" size={48} />
);
```
## Accessibility
By default, we hide icons from screen readers using `aria-hidden="true"`.
You can add accessibility attributes using aria-labels.
```jsx
import { Check } from 'lucide-react';
const App = () => {
return <Check aria-label="Task completed" />;
};
```
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
+16
View File
@@ -144,3 +144,19 @@ const App = () => {
export default App;
```
## Accessibility
By default, we hide icons from screen readers using `aria-hidden="true"`.
You can add accessibility attributes using aria-labels.
```jsx
import { Check } from 'lucide-solid';
const App = () => {
return <Check aria-label="Task completed" />;
};
```
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
+16
View File
@@ -331,3 +331,19 @@ The example below imports all ES Modules, so exercise caution when using it. Imp
<LucideIcon name="Menu" />
```
## Accessibility
By default, we hide icons from screen readers using `aria-hidden="true"`.
You can add accessibility attributes using aria-labels.
```svelte
<script>
import { Check } from '@lucide/svelte';
</script>
<Check aria-label="Task completed" />
```
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
+22
View File
@@ -146,3 +146,25 @@ All other props listed above also work on the `Icon` Component.
</div>
</template>
```
## Accessibility
By default, we hide icons from screen readers using `aria-hidden="true"`.
You can add accessibility attributes using aria-labels.
```vue
<script setup>
import { Check } from 'lucide-vue-next';
</script>
<template>
<Check
color="red"
:size="32"
aria-label="Task completed"
/>
</template>
```
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
+21
View File
@@ -62,6 +62,7 @@ Here is a complete example with unpkg
</script>
</body>
```
We strongly suggest you anchor to a specific version, such as `https://unpkg.com/lucide@x.xxx.x/dist/umd/lucide.min.js`, rather than using `@latest`.
### With ESModules
@@ -203,3 +204,23 @@ createIcons({
}
});
```
## Accessibility
By default, we hide icons from screen readers using `aria-hidden="true"`.
You can add accessibility attributes using aria-labels.
```html
<!DOCTYPE html>
<body>
<i data-lucide="house" aria-label="Home icon"></i>
<script src="https://unpkg.com/lucide@latest"></script>
<script>
lucide.createIcons();
</script>
</body>
```
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
+2
View File
@@ -1,4 +1,6 @@
---
title: Categories
description: Explore Lucide icons organized into various categories for easier browsing.
layout: page
outline: 2
outlineTitle: Categories
+2
View File
@@ -1,4 +1,6 @@
---
title: Icons
description: Browse all Lucide icons.
layout: page
outline: 2
outlineTitle: Categories
+1
View File
@@ -2,6 +2,7 @@
# https://vitepress.dev/reference/default-theme-home-page
layout: home
markdownStyles: false
titleTemplate: false
head:
- - link
+2
View File
@@ -1,4 +1,6 @@
---
title: License
description: Review the licensing terms for using Lucide icons and resources.
aside: false
editLink: false
---
+2 -24
View File
@@ -1,32 +1,10 @@
import copy from 'rollup-plugin-copy';
import replace from '@rollup/plugin-replace';
export default defineNitroConfig({
compatibilityDate: '2025-07-30',
preset: 'vercel_edge',
compatibilityDate: '2026-02-26',
preset: 'vercel',
srcDir: '.vitepress',
routeRules: {
'/api/**': { cors: false },
},
rollupConfig: {
external: ['@resvg/resvg-wasm/index_bg.wasm', './index_bg.wasm?module'],
plugins: [
copy({
targets: [
{
src: './node_modules/@resvg/resvg-wasm/index_bg.wasm',
dest: './.vercel/output/functions/__nitro.func',
},
],
}),
replace({
include: ['./**/*.ts'],
'/* WASM_IMPORT */': 'import resvg_wasm from "./index_bg.wasm?module";',
delimiters: ['', ''],
preventAssignment: false,
}),
],
},
esbuild: {
options: {
jsxFactory: 'React.createElement',
+8 -8
View File
@@ -20,7 +20,7 @@
"dev": "npx nitropack dev",
"prebuild:api": "npx nitropack prepare",
"build:api": "npx nitropack build",
"build": "pnpm run /^prebuild:.*/ && pnpm run /^build:.*/ && pnpm postbuild:vercelJson",
"build": "pnpm run /^prebuild:.*/ && pnpm run build:api && pnpm run build:docs && pnpm postbuild:vercelJson",
"preview": "node .output/server/index.mjs"
},
"author": "Eric Fennis",
@@ -31,7 +31,8 @@
"@lucide/shared": "workspace:*",
"@rollup/plugin-replace": "^6.0.3",
"@types/semver": "^7.7.1",
"nitropack": "2.8.1",
"h3": "^1.15.6",
"nitropack": "^2.12.4",
"rollup-plugin-copy": "^3.5.0",
"svg-path-commander": "^2.1.11",
"vitepress": "^1.6.4"
@@ -39,22 +40,21 @@
"dependencies": {
"@floating-ui/vue": "^1.1.9",
"@headlessui/vue": "^1.7.23",
"@resvg/resvg-wasm": "^2.6.2",
"@vueuse/components": "^14.0.0",
"@vueuse/core": "^14.0.0",
"element-to-path": "^1.2.1",
"fuse.js": "^7.1.0",
"jszip": "^3.10.1",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"lodash-es": "^4.17.23",
"lucide-react": "workspace:*",
"lucide-vue-next": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"sandpack-vue3": "3.1.11",
"semver": "^7.7.3",
"sharp": "^0.34.5",
"shiki": "^3.15.0",
"simple-git": "^3.30.0",
"simple-git": "^3.32.3",
"sitemap": "^7.1.2",
"svg-pathdata": "^6.0.3",
"svgson": "^5.3.1",
+2
View File
@@ -1,4 +1,6 @@
---
title: Packages
description: Discover the various packages available in the Lucide ecosystem.
layout: page
outline: 2
outlineTitle: Packages
+7
View File
@@ -0,0 +1,7 @@
<svg width="800" height="800" viewBox="0 0 800 800" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M39 282C39 164 39 105.1 75.6 68.5C112.2 32 171.1 32 288.9 32H510.1C627.9 32 686.8 32 723.4 68.6C760 105.2 760 164.1 760 281.9V503.1C760 620.9 760 679.8 723.4 716.4C686.8 753 627.9 753 510.1 753H288.9C171.1 753 112.2 753 75.6 716.4C39 679.8 39 620.9 39 503.1V281.9Z" fill="#4945FF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M536.4 250.7H293.7V374.5H417.5V498.2H541.3V255.5C541.3 252.9 539.1 250.7 536.4 250.7Z" fill="white"/>
<path d="M412.7 374.5H417.5V379.3H412.7V374.5Z" fill="white"/>
<path d="M293.8 374.5H412.8C415.4 374.5 417.6 376.6 417.6 379.3V498.3H298.6C295.9 498.3 293.8 496.1 293.8 493.4V374.5Z" fill="#9593FF"/>
<path d="M417.5 498.2H541.3L421.6 618C420 619.6 417.5 618.5 417.5 616.3V498.2ZM293.8 374.5H175.8C173.6 374.5 172.5 371.9 174.1 370.4L293.8 250.7V374.5Z" fill="#9593FF"/>
</svg>

After

Width:  |  Height:  |  Size: 930 B

@@ -0,0 +1 @@
<svg width="161" height="132" viewBox="0 0 161 132" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="0%" y1="50%" y2="50%" id="a"><stop stop-color="#2A3B8F" offset="0%"/><stop stop-color="#29ABE2" offset="100%"/></linearGradient><linearGradient x1="100%" y1="50%" x2="0%" y2="50%" id="c"><stop stop-color="#B4D44E" offset="0%"/><stop stop-color="#E7F716" offset="100%"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><path fill="#166DA5" d="M160.6 65.9l-17.4 29.3-24.4-29.7 24.4-28.9z"/><path fill="#8FDB69" d="M141.3 100.2l-26.5-31.7-15.9 26.6 24.7 36.1z"/><path fill="#166DA5" d="M141 31.4l-26.2 31.8-15.9-26.6L123.6.9z"/><path fill="url(#a)" opacity=".95" d="M61.1 31.4H141L123.4.7H78.7z M114.8 63.3H159l-15.9-26.8H98.8"/><path fill="url(#c)" opacity=".95" d="M141.3 100.3H61l17.6 30.5h45z M114.8 68.4H159l-15.9 26.8H98.8"/><path fill="#010101" d="M78.6 130.8L41 65.8 79.1.8H37.9L.4 65.8l37.5 65z"/></g></svg>

After

Width:  |  Height:  |  Size: 936 B

+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="138" height="42" fill="none" viewBox="0 0 138 42">
<path fill="#fff" fill-rule="evenodd" d="M138 4a3.997 3.997 0 0 0-4-4H4a4 4 0 0 0-4 4v34a4 4 0 0 0 4 4h130a4 4 0 0 0 4-4z" clip-rule="evenodd"/>
<path fill="#000" fill-rule="evenodd" d="M27.963 16.943q1.08 0 1.864.43.783.428 1.212 1.154v-1.454h3.653V27.53H31.04v-1.454q-.429.727-1.23 1.156-.783.43-1.846.43-1.248 0-2.274-.653-1.006-.653-1.603-1.864-.578-1.23-.578-2.852t.578-2.834q.597-1.211 1.604-1.863a4.15 4.15 0 0 1 2.273-.653m1.175 3.188q-.82 0-1.36.577-.542.56-.542 1.585 0 1.006.541 1.602.54.579 1.36.579.802 0 1.343-.579.558-.578.56-1.602-.001-1.007-.56-1.585a1.76 1.76 0 0 0-1.342-.577" clip-rule="evenodd"/>
<path fill="#000" d="M75.361 16.943q2.05 0 3.225 1.006t1.361 2.648h-3.3q-.092-.504-.447-.765-.335-.28-.913-.28-.447 0-.69.169a.55.55 0 0 0-.223.465q0 .373.429.579.428.186 1.379.39 1.137.243 1.882.541.765.3 1.324.969.578.653.578 1.79 0 .914-.541 1.64-.522.727-1.51 1.156-.969.41-2.293.41-1.417 0-2.535-.466-1.1-.485-1.752-1.304a3.47 3.47 0 0 1-.708-1.883h3.542q.075.503.466.782.39.28.968.28.448 0 .71-.186a.57.57 0 0 0 .26-.485q0-.39-.428-.578-.43-.185-1.417-.41-1.12-.223-1.865-.503a3.25 3.25 0 0 1-1.304-.914q-.54-.633-.54-1.715 0-.93.502-1.677.504-.765 1.473-1.211.989-.448 2.367-.448"/>
<path fill="#000" fill-rule="evenodd" d="M94.305 16.943q1.564 0 2.796.653a4.8 4.8 0 0 1 1.957 1.863q.726 1.212.727 2.834 0 1.621-.727 2.852a4.8 4.8 0 0 1-1.957 1.864q-1.25.652-2.815.652-1.566 0-2.814-.652a4.8 4.8 0 0 1-1.939-1.864q-.709-1.212-.709-2.852 0-1.622.71-2.834a4.95 4.95 0 0 1 1.956-1.863q1.248-.653 2.815-.653m0 3.168q-.746 0-1.25.56-.502.56-.502 1.622 0 1.08.484 1.64.485.559 1.25.56.763-.001 1.267-.56.52-.578.521-1.64 0-1.063-.521-1.622a1.61 1.61 0 0 0-1.25-.56M118.921 16.943q1.081 0 1.864.43.783.428 1.212 1.154v-1.454h3.653V27.53h-3.653v-1.454q-.429.727-1.23 1.156-.784.43-1.846.43-1.248 0-2.274-.653-1.006-.653-1.603-1.864-.577-1.23-.577-2.852t.577-2.834q.597-1.211 1.603-1.863a4.15 4.15 0 0 1 2.274-.653m1.175 3.188q-.82 0-1.361.577-.54.56-.541 1.585 0 1.006.541 1.602.541.579 1.361.579.8 0 1.342-.579.558-.578.559-1.602 0-1.007-.559-1.585a1.77 1.77 0 0 0-1.342-.577M17.81 14.39q1.584 0 2.683.558 1.119.56 1.678 1.548.56.988.56 2.274 0 1.193-.56 2.18-.54.97-1.66 1.567-1.099.577-2.701.577H16v4.436h-3.653V14.39zM16 20.186h1.454q1.548 0 1.547-1.416 0-1.436-1.547-1.436h-1.454z" clip-rule="evenodd"/>
<path fill="#000" d="m41.658 19.702 1.51-2.629h4.008l-3.56 5.331 3.69 5.126h-4.1l-1.884-2.628-1.49 2.628h-4.009l3.487-5.424-3.635-5.033h4.1zM55.42 19.33h4.456v-4.94h3.653v13.14h-3.653v-5.274h-4.455v5.274h-3.653V14.39h3.653zM69.18 27.53h-3.654V17.073h3.654zM85.919 17.073h1.9v3.038h-1.9v3.505q0 .429.186.615.204.187.671.187h1.063v3.112h-1.585q-4.008 0-4.008-3.97v-3.449H80.96v-3.038h1.286v-2.535h3.673zM108.205 20.876h-1.024q-1.194 0-1.772.466-.577.465-.577 1.622v4.566h-3.654V17.073h3.654v1.846a4.76 4.76 0 0 1 1.491-1.417 3.6 3.6 0 0 1 1.882-.521zM113.075 27.53h-3.653V17.073h3.653zM67.372 12.339q.95 0 1.528.54.597.542.597 1.361 0 .801-.597 1.342-.577.523-1.528.523-.97 0-1.565-.523a1.76 1.76 0 0 1-.579-1.342q0-.82.579-1.36.596-.54 1.565-.541M111.268 12.339q.95 0 1.528.54.596.542.597 1.361 0 .801-.597 1.342-.578.522-1.528.523-.97 0-1.567-.523a1.76 1.76 0 0 1-.577-1.342q0-.82.577-1.36.597-.54 1.567-.541"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

+25 -19
View File
@@ -14,32 +14,38 @@ const iconAliasesRedirectRoutes = Object.entries(iconMetaData)
const aliasRouteMatches = aliases.map((alias) => alias.name).join('|');
return {
src: `/icons/${aliasRouteMatches}`,
status: 302,
src: `^/icons/(${aliasRouteMatches})$`,
status: 308,
headers: {
Location: `/icons/${iconName}`,
},
};
});
const vercelRouteConfig = {
version: 3,
overrides: {},
cleanUrls: true,
routes: [
{
handle: 'filesystem',
},
{
src: '(?<url>/api/.*)',
dest: '/__nitro?url=$url',
},
...iconAliasesRedirectRoutes,
],
};
const vercelOutputJSON = path.resolve(currentDir, '.vercel/output/config.json');
const vercelConfig = await fs.promises.readFile(vercelOutputJSON, 'utf-8');
const vercelRouteConfig = JSON.parse(vercelConfig);
vercelRouteConfig.routes = [...iconAliasesRedirectRoutes, ...vercelRouteConfig.routes];
// Adjust the existing catch-all route to only catch API routes, so that we can add a new catch-all route for 404s
const allCatchRoute = '/(.*)';
const fallBackIndex = vercelRouteConfig.routes.findIndex((route) => route.src === allCatchRoute);
if (fallBackIndex === -1) {
throw new Error(
`Could not find the expected catch-all route with src "${allCatchRoute}" in the existing Vercel config. Please make sure that the existing config has a catch-all route and that its src is "${allCatchRoute}".`,
);
}
vercelRouteConfig.routes[fallBackIndex].src = '/api/(.*)';
vercelRouteConfig.routes.push({
src: allCatchRoute,
dest: '/404.html',
});
const output = JSON.stringify(vercelRouteConfig, null, 2);
const vercelOutputJSON = path.resolve(currentDir, '.vercel/output/config.json');
await fs.promises.writeFile(vercelOutputJSON, output, 'utf-8');
+1
View File
@@ -1,4 +1,5 @@
---
title: Showcase
layout: page
outline: 2
outlineTitle: Showcase
+2
View File
@@ -2,6 +2,8 @@
"extends": "./.nitro/types/tsconfig.json",
"compilerOptions": {
"jsx": "react",
"jsxFactory": "React.createElement",
"jsxFragmentFactory": "React.Fragment",
"allowImportingTsExtensions": true,
"allowSyntheticDefaultImports": true,
"noEmit": true,
+2
View File
@@ -1,4 +1,6 @@
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"fluid": true,
"cleanUrls": true,
"github": {
"silent": true
Executable → Regular
View File

Before

Width:  |  Height:  |  Size: 412 B

After

Width:  |  Height:  |  Size: 412 B

+1 -1
View File
@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M4.929 4.929 19.07 19.071" />
<circle cx="12" cy="12" r="10" />
<path d="M4.929 4.929 19.07 19.071" />
</svg>

Before

Width:  |  Height:  |  Size: 285 B

After

Width:  |  Height:  |  Size: 285 B

+2 -1
View File
@@ -2,7 +2,8 @@
"$schema": "../icon.schema.json",
"contributors": [
"karsa-mistmere",
"jamiemlaw"
"jamiemlaw",
"jguddas"
],
"tags": [
"plaster",
+1 -1
View File
@@ -13,7 +13,7 @@
<path d="M10 14.01h.01" />
<path d="M14 10.01h.01" />
<path d="M14 14.01h.01" />
<path d="M18 6v11.5" />
<path d="M18 6v12" />
<path d="M6 6v12" />
<rect x="2" y="6" width="20" height="12" rx="2" />
</svg>

Before

Width:  |  Height:  |  Size: 426 B

After

Width:  |  Height:  |  Size: 424 B

+2 -1
View File
@@ -1,7 +1,8 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"danielbayley"
"danielbayley",
"jguddas"
],
"tags": [
"alarm",
+2 -2
View File
@@ -10,6 +10,6 @@
stroke-linejoin="round"
>
<path d="M10.268 21a2 2 0 0 0 3.464 0" />
<path d="M13.916 2.314A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.74 7.327A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673 9 9 0 0 1-.585-.665" />
<circle cx="18" cy="8" r="3" />
<path d="M11.68 2.009A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673c-.824-.85-1.678-1.731-2.21-3.348" />
<circle cx="18" cy="5" r="3" />
</svg>

Before

Width:  |  Height:  |  Size: 418 B

After

Width:  |  Height:  |  Size: 431 B

+9
View File
@@ -5,6 +5,15 @@
"mittalyashu"
],
"tags": [
"cryptocurrency",
"digital",
"blockchain",
"finance",
"coin",
"market",
"decentralized",
"investment",
"crypto",
"currency",
"money",
"payment"
+5 -5
View File
@@ -9,9 +9,9 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m19 3 1 1" />
<path d="m20 2-4.5 4.5" />
<path d="M20 7.898V21a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20" />
<path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2h7.844" />
<circle cx="14" cy="8" r="2" />
<path d="M13 2H6.5A2.5 2.5 0 0 0 4 4.5v15" />
<path d="M17 2v6" />
<path d="M17 4h2" />
<path d="M20 15.2V21a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20" />
<circle cx="17" cy="10" r="2" />
</svg>

Before

Width:  |  Height:  |  Size: 412 B

After

Width:  |  Height:  |  Size: 399 B

+2 -1
View File
@@ -1,7 +1,8 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"danielbayley"
"danielbayley",
"jguddas"
],
"tags": [
"read",
+1 -1
View File
@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2Z" />
<path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z" />
<path d="m9 10 2 2 4-4" />
</svg>

Before

Width:  |  Height:  |  Size: 301 B

After

Width:  |  Height:  |  Size: 371 B

+2 -1
View File
@@ -2,7 +2,8 @@
"$schema": "../icon.schema.json",
"contributors": [
"siarie",
"ericfennis"
"ericfennis",
"jguddas"
],
"tags": [
"delete",
+2 -2
View File
@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z" />
<line x1="15" x2="9" y1="10" y2="10" />
<path d="M15 10H9" />
<path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z" />
</svg>

Before

Width:  |  Height:  |  Size: 317 B

After

Width:  |  Height:  |  Size: 366 B

+2 -1
View File
@@ -2,7 +2,8 @@
"$schema": "../icon.schema.json",
"contributors": [
"siarie",
"ericfennis"
"ericfennis",
"jguddas"
],
"tags": [
"add"
+3 -3
View File
@@ -9,7 +9,7 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z" />
<line x1="12" x2="12" y1="7" y2="13" />
<line x1="15" x2="9" y1="10" y2="10" />
<path d="M12 7v6" />
<path d="M15 10H9" />
<path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z" />
</svg>

Before

Width:  |  Height:  |  Size: 359 B

After

Width:  |  Height:  |  Size: 389 B

+2 -1
View File
@@ -1,7 +1,8 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"danielbayley"
"danielbayley",
"jguddas"
],
"tags": [
"read",
+1 -1
View File
@@ -9,7 +9,7 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2Z" />
<path d="m14.5 7.5-5 5" />
<path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z" />
<path d="m9.5 7.5 5 5" />
</svg>

Before

Width:  |  Height:  |  Size: 329 B

After

Width:  |  Height:  |  Size: 399 B

+10 -1
View File
@@ -4,9 +4,18 @@
"colebemis",
"csandman",
"siarie",
"ericfennis"
"ericfennis",
"jguddas"
],
"tags": [
"save",
"favorite",
"mark",
"label",
"attachment",
"file",
"stick",
"pin",
"read",
"clip",
"marker",
+1 -1
View File
@@ -9,5 +9,5 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z" />
<path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z" />
</svg>

Before

Width:  |  Height:  |  Size: 275 B

After

Width:  |  Height:  |  Size: 342 B

+2 -1
View File
@@ -2,7 +2,8 @@
"$schema": "../icon.schema.json",
"contributors": [
"danielbayley",
"jamiemlaw"
"jamiemlaw",
"jguddas"
],
"tags": [
"issue",
+6 -4
View File
@@ -10,13 +10,15 @@
stroke-linejoin="round"
>
<path d="M12 20v-8" />
<path d="M12.656 7H14a4 4 0 0 1 4 4v1.344" />
<path d="M14.12 3.88 16 2" />
<path d="M15 7.13V6a3 3 0 0 0-5.14-2.1L8 2" />
<path d="M18 12.34V11a4 4 0 0 0-4-4h-1.3" />
<path d="M17.123 17.123A6 6 0 0 1 6 14v-3a4 4 0 0 1 1.72-3.287" />
<path d="m2 2 20 20" />
<path d="M21 5a4 4 0 0 1-3.55 3.97" />
<path d="M22 13h-3.34" />
<path d="M22 13h-3.344" />
<path d="M3 21a4 4 0 0 1 3.81-4" />
<path d="M3 5a4 4 0 0 0 3.55 3.97" />
<path d="M6 13H2" />
<path d="M7.7 7.7A4 4 0 0 0 6 11v3a6 6 0 0 0 11.13 3.13" />
<path d="m8 2 1.88 1.88" />
<path d="M9.712 4.06A3 3 0 0 1 15 6v1.13" />
</svg>

Before

Width:  |  Height:  |  Size: 579 B

After

Width:  |  Height:  |  Size: 656 B

+14
View File
@@ -0,0 +1,14 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"nickveles"
],
"tags": [
"cannabis",
"weed",
"leaf"
],
"categories": [
"nature"
]
}
+18
View File
@@ -0,0 +1,18 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 22v-4c1.5 1.5 3.5 3 6 3 0-1.5-.5-3.5-2-5" />
<path d="M13.988 8.327C13.902 6.054 13.365 3.82 12 2a9.3 9.3 0 0 0-1.445 2.9" />
<path d="M17.375 11.725C18.882 10.53 21 7.841 21 6c-2.324 0-5.08 1.296-6.662 2.684" />
<path d="m2 2 20 20" />
<path d="M21.024 15.378A15 15 0 0 0 22 15c-.426-1.279-2.67-2.557-4.25-2.907" />
<path d="M6.995 6.992C5.714 6.4 4.29 6 3 6c0 2 2.5 5 4 6-1.5 0-4.5 1.5-5 3 3.5 1.5 6 1 6 1-1.5 1.5-2 3.5-2 5 2.5 0 4.5-1.5 6-3" />
</svg>

After

Width:  |  Height:  |  Size: 681 B

+24
View File
@@ -0,0 +1,24 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"danielbayley",
"karsa-mistmere",
"rrod497"
],
"tags": [
"camera",
"surveillance",
"recording",
"film",
"videotape",
"crime",
"watching"
],
"categories": [
"security",
"devices",
"communication",
"connectivity",
"photography"
]
}
+18
View File
@@ -0,0 +1,18 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m12.309 6.652 4.797 2.401a1 1 0 0 1 .447 1.341l-.501 1.001.605.605h2.725a1 1 0 0 1 .894 1.447l-.724 1.448" />
<path d="m15.166 15.166-.719 1.439a1 1 0 0 1-1.342.447L3.61 12.3a2.92 2.92 0 0 1-1.3-3.91L3.69 5.6a2.9 2.9 0 0 1 .873-1.037" />
<path d="M2 19h3.76a2 2 0 0 0 1.8-1.1l1.441-2.902" />
<path d="m2 2 20 20" />
<path d="M2 21v-4" />
<path d="M7 9h.01" />
</svg>

After

Width:  |  Height:  |  Size: 589 B

+1 -1
View File
@@ -9,8 +9,8 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="12" cy="12" r="10" />
<line x1="8" x2="16" y1="12" y2="12" />
<line x1="12" x2="12" y1="16" y2="16" />
<line x1="12" x2="12" y1="8" y2="8" />
<circle cx="12" cy="12" r="10" />
</svg>

Before

Width:  |  Height:  |  Size: 370 B

After

Width:  |  Height:  |  Size: 370 B

+1 -1
View File
@@ -9,7 +9,7 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="12" cy="12" r="10" />
<path d="M7 10h10" />
<path d="M7 14h10" />
<circle cx="12" cy="12" r="10" />
</svg>

Before

Width:  |  Height:  |  Size: 292 B

After

Width:  |  Height:  |  Size: 292 B

Some files were not shown because too many files have changed in this diff Show More