Compare commits

...
211 Commits
Author SHA1 Message Date
Eric Fennis 6d1fc51b9a Prepare @lucide/lab 0.2.0 release 2026-07-31 14:09:41 +02:00
Eric FennisandCopilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> 1502285072 fix(@lucide/lab): Fix lab build (#4618)
* chore(lab): Adjust build scripts

* add check workflow

* Potential fix for pull request finding 'CodeQL / Workflow does not contain permissions'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* update gitignore

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-07-31 09:11:20 +02:00
Karsa 240118e521 feat(icons): improve calendar icons centre of gravity (#4614)
* feat(icons): improve calendar icons centre of gravity

* fix(icons): reoptimize everything using Lucide Studio
2026-07-30 09:50:10 +02:00
Samuel Alakegithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Eric Fennis
4aec3f892f feat(icons): add layout-freeform (#4543)
* feat(icons): add layout-freeform

Adds an icon for freeform layout: three blocks, no two sharing an edge.
It matches the "no auto layout" / free positioning mode found in design
tools, as the counterpart to constrained layout modes.

Design notes:
- Reuses the 7x7 rx=1 block already shared by layout-grid, layout-list
  and layout-panel-*, rather than introducing a new base shape.
- Each block is offset so that no two share an edge, which is what
  separates it from layout-grid.
- The offset is 1px: a 2px offset reads more clearly at 16px, but brings
  the top-right and bottom-left blocks within 1.66px of each other
  diagonally, under the 2px element spacing guideline. See the PR for the
  alternatives.

* Update icons/layout-freeform.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>
2026-07-25 22:59:55 +02:00
Karsa dbfe130652 feat(icons): replaces podcast icon with new mic-* icons (#4583)
* feat(icons): replaces `podcast` icon with new `mic-*` icons

* fix(icons): change contributors, since these are now essentially brand new icons

* fix(prettier): remove path fill from allowed SVG element attributes
2026-07-25 22:58:54 +02:00
Jakob GuddasandEric Fennis d29db5e98e feat(icons): added pilot icon (#2409)
* Added icons/pilot.svg

* Added icons/pilot.json

* Move pilot icon to lab directory

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-25 15:06:22 +02:00
Daniel BayleyandEric Fennis bb26580cfb feat(docs): Add lab requirement in pull_request_template.md (#3651)
* feat(docs): update pull_request_template.md

* Fix link to Lab directory in PR template

Updated link reference for the Lab directory in the pull request template.

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-25 13:13:01 +02:00
Jakob Guddas 74c46711c7 feat(analytics): add utm source and medium (#4596) 2026-07-25 12:26:26 +02:00
KarsaandKarsa c3b6795394 fix(icons): changed trophy icon (#4591)
* [github] Added issue template forms

* [github] yaml => yml

* Syntax fixes

* Further syntax fixes

* Sort issue templates

* Update 02_bug_report.yml

* Updated icons/trophy.svg

* Updated icons/trophy.svg

* fix(icons/trophy): fill in metadata

---------

Co-authored-by: Karsa <karsa@karsa.org>
2026-07-25 12:21:12 +02:00
Bálint TóthandEric Fennis 33342b8790 feat(icons): added police-cap icon to lab (#3019)
* Added icons/police-cap.svg

* Added icons/police-cap.json

* Move police cap to lab directory

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-24 15:57:26 +02:00
9ecaafbc4d feat(lab): Migrate lab to main repo. (#4521)
* Add directory

* Add lab check script

* Delete duplicated icons

* Fix the lab page

* Adjust paths

* update lockfile

* update lockfile

* fix(lab/planet): replace with guideline-compliant design

* Add install step

* Add second install step

* Adjust lab in site

* try this

* Fix workflow

* Add cspell

* Format code

* Temporary delete icons for copilot review

* Place back lab icons

* Apply suggestions from code review

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

* Update lock file

* Revert svg changes

* Fix list

* Rename filenames

* Format tsconfig

---------

Co-authored-by: Karsa <contact@karsa.org>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-24 15:05:40 +02:00
KarsaandEric Fennis 1d578ab536 fix(icons): changed barrel icon (#4592)
* Updated icons/barrel.svg

* Updated icons/barrel.json

* Update barrel.json

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-24 14:41:37 +02:00
Eric Fennis c757cb9d4b ci(ci.yml): Remove concurrency in ci.yml (#4595) 2026-07-24 14:39:12 +02:00
KarsaandEric Fennis 5d36179bf4 feat(ci): added custom prettier plugin for icon SVG files (#4576)
* feat(ci): added custom prettier plugin for icon SVG files

* feat(ci): added custom prettier plugin for icon SVG files

* feat(ci): replace prettier plugin implementation with one based on svgo

* fix(ci): fix linting issues in prettier plugin

* Allow fill in path to fix podcast icon

* Format code

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-24 14:23:56 +02:00
Karsa 357df0d660 fix(icons): changed feather icon (#4584)
* Updated icons/feather.svg

* Updated icons/feather.json

* Update feather.json
2026-07-24 13:28:42 +02:00
Eric Fennis 5a06f7cb1d fix(request-review): Remove pull_request_target (#4593) 2026-07-24 13:23:58 +02:00
مُحَمّد سِيّدgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Eric FennisKarsa
63d0ef6664 feat(icons): added mosque icon (#4494)
* Added icons/mosque.svg

* Added icons/mosque.json

* Update icons/mosque.json

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

* Update icons/mosque.json

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

* Add contributor 'rrod497' to mosque.json

* Add empty use-cases array to mosque.json

* Update mosque.svg

* Update mosque.json

* Update mosque.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: Karsa <contact@karsa.org>
2026-07-23 20:31:03 +02:00
Martin VítekCopilot Autofix powered by AIgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Eric Fennis
0adb963d07 feat(icons): added user-shield icon (#3099)
* Added icons/user-shield.svg

* Added icons/user-shield.json

* Apply design from karsa

* Potential fix for pull request finding

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

* Update icons/user-shield.json

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

* Update icons/user-shield.json

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

* Potential fix for pull request finding

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

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 15:20:10 +02:00
Samuel Alakegithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Eric FennisKarsa
89147bbecc feat(icons): add scan-square (#4550)
* feat(icons): add scan-square

Adds scan-square: a scanning frame with a square detected inside it.

The scan-* family covers what is being detected — scan-face, scan-heart,
scan-text, scan-eye, scan-barcode, scan-qr-code, scan-search, scan-line —
but has nothing for a plain shape or object.

Composed entirely from two existing icons rather than new geometry: the
four corner brackets are scan's, verbatim, and the inner block is
square-square's rect(8,8,8,8) rx=1, verbatim. Nothing here is drawn from
scratch, so it sits in the family without introducing a new vocabulary.

* chore(icons): fill scan-square use-cases and fix recognise/recognize tags

Addresses review on #4550: fills the use-cases field per @ericfennis, and
collapses the duplicate recognise/recognize tags into a single
recognition tag, matching scan-text's vocabulary per @Copilot.

* Update icons/scan-square.json

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

* Update icons/scan-square.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-07-23 14:08:52 +02:00
Karsa 0ad5aaf323 Updated icons/toolbox.svg (#4571) 2026-07-23 14:03:34 +02:00
dependabot[bot]dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Eric Fennis
50f9af4ed2 chore(deps-dev): bump astro from 6.4.8 to 7.1.0 (#4572)
Bumps [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) from 6.4.8 to 7.1.0.
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/astro@7.1.0/packages/astro)

---
updated-dependencies:
- dependency-name: astro
  dependency-version: 7.1.0
  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-07-23 14:02:34 +02:00
Octobergithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Karsa
4c61dc4826 feat(icons): add square-off icon (#4496)
* feat(icons): add square-off icon

* Apply suggestion from @github-actions[bot]

Added tags

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

* Apply suggestion from @github-actions[bot]

added categories

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

* Apply suggestion from @github-actions[bot]

added use cases

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

* Update icons/square-off.json

update use cases

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

* Update icons/square-off.svg

update code convention

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

* Update square-off.json

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Karsa <contact@karsa.org>
2026-07-23 14:00:53 +02:00
99a8602c5d fix(icons): changed zap and zap-off icons (#4536)
* fix(icons): changed `zap` and `zap-off` icons

* Update zap.svg

* Update zap-off.svg

---------

Co-authored-by: Karsa <contact@karsa.org>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-23 14:00:17 +02:00
NielsLazaromsgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Eric FennisKarsa
75b6ac1969 feat(icons): added pending-cw icon (#4439)
* Added icons/pending-cw.svg

* Added icons/pending-cw.json

* Update icons/pending-cw.json

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

* Rename pending-cw.json to clock-arrow-cw.json

* Add clock-arrow-cw.svg icon file

* Update icons/clock-arrow-cw.json

* Update icons: replace and refine `history` and `clock-*` SVGs and metadata

* update file name

* updated icon name

* Refine `clock-arrow-ccw` metadata: add use-cases, tags, and aliases

* fix(icons): rename history/pending _yet again_. Sorry, Niels 🫣

---------

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: Karsa <contact@karsa.org>
2026-07-23 11:59:09 +02:00
KarsaandEric Fennis 138ce8e748 fix(packages/angular): add more supported attributes for SVG nodes (#4570)
* fix(packages/angular): add more supported attributes for SVG nodes

* fix(packages/angular): use original matcher syntax instead of toMatchInlineSnapshot matcher

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-23 11:29:24 +02:00
KarsaandEric Fennis 87ec1a0587 fix(icons): optimised square-scissors icons (#4581)
* Updated icons/square-bottom-dashed-scissors.svg

* Updated icons/square-bottom-dashed-scissors.json

* Update square-bottom-dashed-scissors.json

* Update square-scissors.svg

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-23 10:43:44 +02:00
Eric Fennis 02eaf471a9 fix(docs): Fix site build (#4582)
* Fix site build

* Fix site build
2026-07-23 10:15:09 +02:00
Karsa 3035ed309e feat(icons): removed brand names from tags & revised brand stopwords (#4575) 2026-07-23 08:13:10 +02:00
Karsagithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Eric Fennis
4e50f0d759 feat(icons): added shield-keyhole icon (#4580)
* Added icons/shield-keyhole.svg

* Added icons/shield-keyhole.json

* Update shield-keyhole.json

* Update icons/shield-keyhole.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>
2026-07-23 08:10:33 +02:00
Karsa a924c01b8e fix(icons): changed book-open icons (#4565)
* Updated icons/book-open.svg

* Updated icons/book-open.json

* Updated icons/book-open-text.svg

* Updated icons/book-open-text.json

* Updated icons/book-open-check.svg
2026-07-23 08:10:07 +02:00
Karsa 37f32cb73a Update ad.json (#4579) 2026-07-23 07:47:39 +02:00
kamilaandKarsa 4e2efb9350 fix(icons): changed columns-3-cog icon (#4578)
* fix(icons)/columns-3-cog

* Update icons/columns-3-cog.svg

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

* add EOF new line to columns-3-cog.svg

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-07-22 16:13:09 +02:00
Karsa 658573b017 fix(docs): fix home page package links & accessible labels (#4540) 2026-07-17 13:33:45 +02:00
Karsagithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Eric Fennis
5136572c10 feat(icons): added scan-box icon (#4551)
* Added icons/scan-box.svg

* Added icons/scan-box.json

* Update scan-box.json

* Update scan-box.svg

* Update icons/scan-box.json

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

* Update icons/scan-box.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>
2026-07-17 10:25:16 +02:00
Karsa 4f8088fd90 fix(icons): changed file-box icon (#4552)
* Updated icons/file-box.svg

* chore(icons/file-box): extend tags & use case metadata
2026-07-17 10:24:40 +02:00
Karsa ae40cfbc73 fix(icons): changed ethernet-port icon (#4555)
* Updated icons/ethernet-port.svg

* Updated icons/ethernet-port.json
2026-07-17 09:28:22 +02:00
Karsa cdd7db1ce6 fix(icons): changed hdmi-port icon (#4554)
* Updated icons/hdmi-port.svg

* Updated icons/hdmi-port.json
2026-07-17 09:28:17 +02:00
Jakob Guddas f930bbe07c feat(docs): add studio link (#4534)
* feat: add studio link

* fix: add aria label
2026-07-16 14:41:14 +02:00
Eric Fennis f229f83f0c chore(depedencies): Update dependencies (#4553)
* update deps

* Update even more

* Fix lint errors

* Apply feedback

* Update lockfile
2026-07-16 14:38:12 +02:00
Jakob Guddas b442632ee6 fix: broken link in brand logo comment (#4533) 2026-07-11 12:59:38 +02:00
dependabot[bot]dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Eric Fennis
078a0b2339 chore(deps-dev): bump @babel/core from 7.28.5 to 7.29.6 (#4476)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.28.5 to 7.29.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.29.6/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-version: 7.29.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>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-10 11:53:34 +02:00
5d78605650 fix(site): empty search results on first load for tag-only matches (#4413)
* fix(site): fetch icon search metadata when typing

* fix(site): gate "No results" on metadata availability, not fetch state

* fix(site): also wait on categories metadata on the category page

Keeps the loading guard symmetric with the icons page. The narrower
tags-only check was technically more precise (this page's useSearch
doesn't index categories), but the failure case it guarded against —
brand search landing on a blank area if /api/categories lags behind
/api/tags — is too narrow to justify the asymmetry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-10 11:22:57 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ab61fa277b chore(deps-dev): bump astro from 6.1.10 to 6.4.6 (#4487)
Bumps [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) from 6.1.10 to 6.4.6.
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/astro@6.4.6/packages/astro)

---
updated-dependencies:
- dependency-name: astro
  dependency-version: 6.4.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-07-10 09:58:42 +02:00
Eric Fennis bb1329e512 fix(icons): Rename to circle-euro to match other euro icons (#4531)
* fix(icons): Rename to `circle-euro` to match other euro icons

* Add usecase
2026-07-10 09:58:01 +02:00
Turboman3000 b5b5d95933 feat(icons): added server-plus icon (#4232)
* Added icons/server-plus.svg

* Added icons/server-plus.json

* Updated icons/server-plus.json
2026-07-09 15:09:49 +02:00
Julian Solimandogithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Copilot Autofix powered by AIEric Fennis
7b589f2b5c feat(icons): added circle-euro-sign icon (#4353)
* Added icons/circle-euro-sign.svg

* Added icons/circle-euro-sign.json

* Update icons/circle-euro-sign.json

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

* Potential fix for pull request finding

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

* Apply suggestions from code review

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

* Potential fix for pull request finding

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

---------

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: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-09 14:54:38 +02:00
2d36863568 feat(icons): center the dot icon (#4492)
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Karsa <contact@karsa.org>
2026-07-09 14:54:20 +02:00
Eric FennisandCopilot Autofix powered by AI 7291cbcc0f fix(lucide-react-native): Add icon exports property to the package.json file (#4522)
* Add export per icon

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* Add documentations

* Format code

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-09 14:53:06 +02:00
4c663b9a32 fix(vue): support kebab-case icon-node prop on Icon component (#4512)
* fix(vue): support kebab-case icon-node prop on Icon component

The Icon component destructured `iconNode` camelCase-only while
`stroke-width`/`absolute-stroke-width` accept both cases, so the
idiomatic Vue usage `<Icon :icon-node="..." />` left iconNode undefined
and crashed with 'Cannot read properties of undefined (reading map)'
(#3485). Accept the kebab-case alias and guard the render path.

Closes #3485

* Potential fix for pull request finding

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

* chore(vue): apply prettier formatting to Icon.ts

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-09 14:11:20 +02:00
Pavlos Vinieratos 63369b1ac0 fix(lucide-react-native): restore the icons entry point in the JS bundles (#4528) 2026-07-09 13:57:22 +02:00
Jamie Law f07465f82e Updated icons/option.svg (#4326) 2026-07-09 13:32:55 +02:00
GyeongHo KimandEric Fennis 60d583ce4e docs(site): list @gyeonghokim/lucide-lit as third-party package (#4421)
Add the @gyeonghokim/lucide-lit Lit web components package to the
third-party packages list, with a Lit framework logo for the card icon.

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-08 09:55:54 +02:00
Karsa 5828ecb38f fix(packages/angular): move child rendering logic to template from effect (#4519)
* fix(packages/angular): move child rendering logic to template from effect

* test(packages/angular): add unit tests on SSR hydration
2026-07-06 12:16:52 +02:00
Eric Fennis 031b226ac6 Add merch link (#4524) 2026-07-05 14:22:51 +02:00
Copilotandcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> 35d535a477 chore(icons): remove toBeRemovedInVersion metadata and make it optional in schema (#4513)
* Remove toBeRemovedInVersion from icons and make optional in schema

* fix(build-icons): align alias deprecation type with schema optional removal version

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-02 12:34:23 +02:00
Karsa 8930dfa827 fix(scripts): fix typo in renameIcon.function.mts (#4514) 2026-07-02 11:41:51 +02:00
Daniel CastillejoandEric Fennis c67c9bdbfb feat(icons): added paper-bag icon (#4023)
* Added icons/paper-bag.svg

* Added icons/paper-bag.json

* Update paper-bag.svg

* Update paper-bag.json with new fields and tags

Added 'use-cases' field and updated 'tags' list.

* Update paper-bag.json

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-07-01 16:02:09 +02:00
Eric Fennis 52d7c549c3 Set custom COPILOT_GITHUB_TOKEN (#4509) 2026-06-30 20:06:34 +02:00
Eric Fennis 9cb4e49849 Small fix in the workflow (#4508) 2026-06-30 19:15:07 +02:00
Eric FennisandCopilot Autofix powered by AI f59db07ef9 ci(repo-journal.yml): GH copilot repo summary (#4505)
* gh bot posting info

* Set secret

* Potential fix for pull request finding

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

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-30 14:09:53 +02:00
Eric Fennis 46bcf1fa89 chore(docs): Remove certificates banner (#4504)
* chore(docs): Remove certificate dev banner

* Remove css
2026-06-29 15:41:58 +02:00
George Nick Gorzynski 7d15e8466a fix(docs): prevent scrollbar layout shift on icons page (#4500)
Adds scrollbar-gutter: stable to html to reserve space for the scrollbar,
preventing layout shift when navigating to/from the icons route.
2026-06-29 09:21:11 +02:00
Ankit SharmaandEric Fennis ce2d598d96 feat(icons): added phi icon also used as golden-ratio (#4218)
* Added icons/phi.svg

* Added icons/phi.json

* Updated icons/phi.json

* Add use-cases to phi.json

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-06-28 18:36:16 +02:00
Jakob GuddasandEric Fennis 627b4c1672 fix(icons): changed ungroup icon (#3969)
* Updated icons/ungroup.svg

* Updated icons/ungroup.json

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-06-28 17:23:52 +02:00
Jakob Guddasgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Eric Fennis
ee02505468 fix(icons): changed carrot icon (#4010)
* Updated icons/carrot.svg

* Updated icons/carrot.json

* Updated icons/carrot.svg

* Updated icons/carrot.json

* Apply suggestions from code review

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-06-28 17:20:06 +02:00
Konrad SzajnaandClaude Opus 4.8 7c8fbb4813 fix(astro): add Astro v7 compatibility (#4491)
Astro 7 is released and @lucide/astro works with it unchanged. Widen the peerDependencies range to include ^7.

Dev dependencies are intentionally kept on Astro 6: bumping them pulls Vite 8 into the workspace, which destabilizes pnpm's shared peer resolution and breaks the vitest snapshot tests in other packages (icons, svelte).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 17:32:55 +02:00
Eric Fennis 7e938845f0 fix(lcuide-react-native): Fix context provider export (#4497) 2026-06-25 07:22:42 +02:00
Eric Fennis 0d6c47d545 docs(installation.md): Remove outdate next tag in installation (#4495) 2026-06-24 12:03:14 +02:00
HsiandEric Fennis 2f5af2ceb5 fix(docs): allow icon popularity prebuild without token (#4481)
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-06-24 11:35:49 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 448bcc90fe chore(deps): bump esbuild from 0.25.12 to 0.28.1 (#4459)
Bumps [esbuild](https://github.com/evanw/esbuild) from 0.25.12 to 0.28.1.
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG-2025.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.12...v0.28.1)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.28.1
  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-06-24 11:23:17 +02:00
Bartek Iwańczuk 2fed527c00 docs(site): add Deno to installation instructions (#4486) 2026-06-24 11:17:59 +02:00
Hsi 8fc6b70aa5 fix(docs): fix color input clipping (#4488)
* fix(docs): cap customizer hex input

* fix(docs): use full width color field
2026-06-19 16:16:39 +02:00
Eric Fennis cf0e1e44ba ci(release.yml): Remove concurrency field to prevent release mess (#4485) 2026-06-18 14:41:27 +02:00
BarakudumandEric Fennis 65ef069acc feat(icons): add 6 database variant icons (#4336)
* feat(icons): added database-variants `database-check`, `database-x`, `database-plus`, `database-minus`, `database-arrow-down`, `database-arrow-up`

* fix(metadata): add missing use-cases for database variant icons

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-06-18 09:06:07 +02:00
7983b2a262 feat(icons): added broken-bone icon (#4131)
* Added icons/broken-bone.svg

* Added icons/broken-bone.json

* redesign according to guidelines

* fix(bone-fracture.json): Remove trailing comma and ensure proper JSON formatting

* Potential fix for pull request finding

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

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-18 08:54:04 +02:00
Hsi 7ddb1e237d fix(docs): rename navigation category label (#4483) 2026-06-17 07:42:12 +02:00
Eric Fennis 5ff536e139 ci(release.yml): Fix workflow and remove version scripts in package scripts (#4479)
* ci(release.yml): Remove new-version in release flow

* Remove version in scripts

* Update workflow
2026-06-16 16:24:07 +02:00
Eric Fennis bb7d2d9839 ci(release.yml): Remove new-version in release flow (#4478) 2026-06-16 15:01:58 +02:00
fc20eb6c7a feat(icons): added pencil-sparkles icon (#4445)
* Added icons/pencil-sparkles.svg

* Added icons/pencil-sparkles.json

* Fix pencil-sparkles artboard

viewbox was previously set to 22px instead of 24px

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Karsa <contact@karsa.org>
2026-06-16 13:21:44 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> d850228c3c chore(deps-dev): bump @angular/common from 21.2.5 to 21.2.17 (#4471)
Bumps [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) from 21.2.5 to 21.2.17.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.17/packages/common)

---
updated-dependencies:
- dependency-name: "@angular/common"
  dependency-version: 21.2.17
  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-06-16 08:41:07 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> f6cef23cd7 chore(deps-dev): bump markdown-it from 14.1.1 to 14.2.0 (#4475)
Bumps [markdown-it](https://github.com/markdown-it/markdown-it) from 14.1.1 to 14.2.0.
- [Changelog](https://github.com/markdown-it/markdown-it/blob/master/CHANGELOG.md)
- [Commits](https://github.com/markdown-it/markdown-it/compare/14.1.1...14.2.0)

---
updated-dependencies:
- dependency-name: markdown-it
  dependency-version: 14.2.0
  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-06-16 08:37:37 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 766c98af22 chore(deps-dev): bump vitest from 4.0.12 to 4.1.0 (#4429)
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 4.0.12 to 4.1.0.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.0/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-version: 4.1.0
  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-06-16 08:36:08 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 1f0f070e84 chore(deps-dev): bump @angular/core from 21.2.5 to 21.2.17 (#4470)
Bumps [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) from 21.2.5 to 21.2.17.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.17/packages/core)

---
updated-dependencies:
- dependency-name: "@angular/core"
  dependency-version: 21.2.17
  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-06-16 08:08:03 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> a90271b282 chore(deps-dev): bump @angular/compiler from 21.2.5 to 21.2.17 (#4474)
Bumps [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) from 21.2.5 to 21.2.17.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.17/packages/compiler)

---
updated-dependencies:
- dependency-name: "@angular/compiler"
  dependency-version: 21.2.17
  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-06-16 06:32:06 +02:00
Scott Krukowski c81680e066 docs(docs): fix broken Svelte package source link in README (#4468) 2026-06-15 09:42:24 +02:00
0c57f7265a feat(icons): added clock-arrow-out icon (#2404)
* Added icons/clock-arrow-out.svg

* Added icons/clock-arrow-out.json

* Rename icon

* Add empty use-cases array

* Potential fix for pull request finding

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

* Update clock-arrow-right.json

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 17:51:32 +02:00
Jakob Guddasgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Eric Fennis
f917f247e3 feat(icons): added user-round-arrow-in icon (#2283)
* Added icons/user-round-arrow-inwards.svg

* Added icons/user-round-arrow-inwards.json

* Updated icons/user-round-arrow-inwards.json

* Rename user-round-arrow-inwards.json to user-round-arrow-in.json

* Rename user-round-arrow-inwards.svg to user-round-arrow-in.svg

* Rename icon

* Add use cases empty

* Apply suggestions from code review

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-06-13 17:35:55 +02:00
Jacob Padillagithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Copilot Autofix powered by AIEric FennisJakob Guddas
aef0f98a68 feat(icons): added summary icon (#3114)
* ai summary icon

* other summary icon svg

* slightly less pronounced curve

* Modify SVG paths in summary.svg

* Update icons/summary.json

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

* Potential fix for pull request finding

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

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Jakob Guddas <github@jguddas.de>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 17:31:07 +02:00
6e5c250af0 feat(icons): added clock-arrow-in icon (#2403)
* Added icons/clock-arrow-in.svg

* Added icons/clock-arrow-in.json

* Updated icons/clock-arrow-in.json

* Rename to clock-arrow-left

* Potential fix for pull request finding

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

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 17:25:43 +02:00
Marcos Ramírez F.github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>KarsaCopilot Autofix powered by AIEric Fennis
f37f235d78 feat(icons): added banknote-check icon (#3956)
* Added icons/banknote-check.svg

* Added icons/banknote-check.json

* Update icons/banknote-check.json

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

* Apply suggestions from code review

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

* Potential fix for pull request finding

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

* Update banknote-check.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>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 17:02:57 +02:00
b973e42174 feat(icons): added tag-plus and tag-x icons (#3980)
* add tag-plus icon

* add tag-x icon

* Update icons/tag-x.svg

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

* Apply suggestions from code review

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

* Apply suggestions from code review

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

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Karsa <contact@karsa.org>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 17:02:40 +02:00
Eric Fennis ce6fb3dd6c fix(metadata): Add use-cases to auto-save 2026-06-13 16:55:50 +02:00
c3262987be feat(icons): added save-check icon (#3120)
* Added icons/save-check.svg

* Added icons/save-check.json

* Fixing angle of the checkmark to be 90 degrees

* Adding contributors of the save icon

* Update save-check.svg paths for new design

* Update save-check.svg

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Karsa <contact@karsa.org>
2026-06-13 15:51:47 +02:00
Jamie Law 52ee7b3692 Add tags to search- icons (#4099) 2026-06-13 15:32:02 +02:00
Jakob Guddas 04ee825d6b fix(icons): decreased size of arrows inside square-arrow-* icons (#3926)
* Updated icons/square-arrow-down-left.svg

* Updated icons/square-arrow-down-left.json

* Updated icons/square-arrow-up-right.svg

* Updated icons/square-arrow-up-right.json

* Updated icons/square-arrow-up-left.svg

* Updated icons/square-arrow-up-left.json

* Updated icons/square-arrow-down-right.svg

* Updated icons/square-arrow-down-right.json
2026-06-13 15:29:54 +02:00
Jakob GuddasKyle Angelo GalendezEric Fennisgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Copilot Autofix powered by AI
0241b57c35 feat(icons): added podium icon (#2124)
* Added icons/podium.svg

* Added icons/podium.json

* Updated icons/podium.svg

* Update icons/podium.json

Co-authored-by: Kyle Angelo Galendez <xcxkyleangelo26@gmail.com>

* Update icons/podium.svg

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

* Apply suggestion from @github-actions[bot]

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

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Kyle Angelo Galendez <xcxkyleangelo26@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 15:25:52 +02:00
Eric FennisandCopilot Autofix powered by AI 24dd855b87 feat(site): Improve search and add sorting options (#4453)
* setup icon popularity call

* Adjust sort button

* Adjust sorting

* Adds aliases

* Format code

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* Add check for env variable

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* Improve styling on mobile

* Remove hardcoded sort icon

* Fix build

* Format code

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 15:25:41 +02:00
Jakob Guddasgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Eric Fennis
4e5fce4adc fix(icons): changed wallet-cards icon (#3888)
* Updated icons/wallet-cards.svg

* Updated icons/wallet-cards.json

* Update icons/wallet-cards.json

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

* Updated icons/wallet-cards.svg

* Updated icons/wallet-cards.json

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-06-13 15:23:19 +02:00
Vyctor H. Brzezowski ae94b5118b fix(site): reserve space for icon detail drawer (#4344) 2026-06-13 15:04:57 +02:00
Eric Fennis 2dd4be802a Fix provider exports (#4463) 2026-06-13 14:51:48 +02:00
Eric Fennisgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Copilot Autofix powered by AI
f4fa0512d3 feat(icons): added list-sort-descending icon (#4457)
* Added icons/list-sort.svg

* Added icons/list-sort.json

* Update list-sort.json

* Apply suggestions from code review

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

* Potential fix for pull request finding

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

* Update naming

* Also add the ascending version

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 14:05:31 +02:00
d1150cea7a feat(icons): added save-plus icon (#4448)
* add json for icons

* Added icons/save-plus.svg

* Added icons/save-plus.json

* Add additional tags to save-plus.json

* Removed out of scope changes

* Potential fix for pull request finding

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

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 14:04:52 +02:00
KarsaandEric Fennis 4afccc1842 feat(icons): added eye-dashed icon (#4415)
* Added icons/eye-dashed.svg

* Added icons/eye-dashed.json

* Update icons/eye-dashed.json

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

* Improve writing of use-cases

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-06-13 14:04:20 +02:00
4e161a15ef feat(icons): added ad icon (#4323)
* Added icons/ad.svg

* Added icons/ad.json

* Add use-cases to meta json file

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

* Potential fix for pull request finding

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

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 12:41:38 +02:00
76175250cd feat(icons): added wrench-off icon (#4434)
* Added icons/wrench-off.svg

* Added icons/wrench-off.json

* Update icons/wrench-off.svg

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

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* Add new tags to wrench-off.json

---------

Co-authored-by: Karsa <contact@karsa.org>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 12:38:38 +02:00
2e58e319e7 feat(icons): added save-pen icon (#4179)
* Added icons/save-pen.svg

* Added icons/save-pen.json

* Updated icons/save-pen.svg

* Apply design from karsa

* Potential fix for pull request finding

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

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 12:33:48 +02:00
Eric FennisandCopilot Autofix powered by AI 283e4b2805 chore(suggest-tags): Update metadata suggestion script (#4462)
* feat(metadata): implement pull request metadata suggestions workflow and replace suggestTags script

* Switch to GPT 5

* Update comment description

* Potential fix for pull request finding

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

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-13 12:28:04 +02:00
db63e66333 feat(icons): added star-* icons (#3918)
* Added icons/star-check.svg

* Added icons/star-check.json

* Add star-x.svg icon

* Add star-x icon JSON

* Add star-minus.svg icon file

* Add star-plus SVG icon

* Add star-plus icon JSON configuration

* Add 'remove' and 'deselect' to star-minus.json

* Update star-check.svg with new path data

* Modify star-x.svg paths for new design

* Modify star-minus SVG paths for new design

* Modify star-plus.svg paths for new design

* Update star-x.svg

* Username change

* Username change

* Update star-minus.json

* Update and rename star-check.json to Username change

* Username change

* Modify star-plus.svg paths for new design

* Refactor star-minus.svg paths for clarity

* Update star-plus.svg paths for new design

* Update SVG path for star-check icon

* Adjust path element in star-minus.svg

* Update star-minus.svg paths and adjust dimensions

* Update icons/star-x.svg

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

* Update icons/star-check.svg

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

* Update star-check.svg

* Merge pull request #1

Added use case

* Fix JSON formatting in star-minus.json

* Update star-plus.json

* Fix JSON syntax in star-x.json

---------

Co-authored-by: Rajnish Mehta <172272341+KnarliX@users.noreply.github.com>
Co-authored-by: Karsa <contact@karsa.org>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-06-13 12:19:51 +02:00
Eric Fennis 4b3521a3e3 chore(deps): upgrade pnpm to version 11.6.0 (#4458)
* chore: upgrade pnpm to version 11.6.0 and restore package extensions and overrides in pnpm workspace

* Remove packageExtensions

* Update lockfile
2026-06-12 16:09:47 +02:00
f664af1933 feat(icons): added webcam-off icon (#4242)
* Added icons/webcam-off.svg

* Added icons/webcam-off.json

* Update webcam-off.svg

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

* Update webcam-off.json

* Potential fix for pull request finding

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

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Karsa <contact@karsa.org>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-12 14:38:04 +02:00
Eric FennisandCopilot Autofix powered by AI 03ad294db0 fix(ci): add check to skip release if latest tag was created today (#4085)
* fix(ci): add check to skip release if latest tag was created today

* Apply dispatch gate to the ci workflow

* Fix ci

* Revert svg changes

* Revert svg

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* Format ci file

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-12 14:27:59 +02:00
Karsa a2ec77fc7f feat(packages/angular): remove upper limit for peer dependencies, as the risk of breakage is very little (#4450) 2026-06-11 15:03:02 +02:00
Alec Glassford 602bca62a2 fix(docs): Remove @next from installation instructions for@lucide/svelte (#4432)
Installing `@lucide/svelte@next` currently gets version 1.3.0, which is out of date compared to installing `@lucide/svelte` (aka `@lucide/svelte@latest`), which gets version 1.17.0. It seems to make more sense to instruct users to get the latest version.

This change matches identical changes to the getting-started guides for other frameworks in 5f83bbf7e7 - it seems like the omission of Svelte was likely an oversight (?)
2026-06-09 09:57:13 +02:00
KarsaandEric Fennis 423afc6d03 fix(): force hide #bb-banner, if html.has-bb-banner is missing (#4422)
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-05-30 17:39:05 +02:00
KarsaandEric Fennis 374398b58d fix(metadata): add missing use-cases prop on play-off.json (#4423)
* fix: add missing use-cases prop on play-off.json

* Apply suggestion from @ericfennis

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-05-30 15:28:33 +02:00
Ahmed Dghaiesgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Copilot Autofix powered by AI
6c2b8e6fa0 feat(icons): added play-off icon (#4412)
* Added icons/no-play.svg

* Added icons/no-play.json

* Update icons/no-play.json

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

* Update no-play.svg

* Update no-play.json

* Potential fix for pull request finding

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

* Update and rename no-play.json to play-off.json

* Rename no-play.svg to play-off.svg

* Update play-off.svg

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-28 10:53:16 +02:00
Eric Fennis ecc612044e chore(site): Remove survey from site (#4417)
* chore(site): Remove survey from site

* Add usecases to parasol
2026-05-28 10:49:54 +02:00
KarsaandEric Fennis 896aba0d19 feat(icons): added parasol icon (#4347)
* feat(github): create release-angular.yml for testing purposes

* Update release-angular.yml

* Update release-angular.yml

* Added icons/parasol.svg

* Added icons/parasol.json

* Delete .github/workflows/release-angular.yml

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-05-28 10:20:16 +02:00
Eric FennisandCopilot 45740bef8b feat(metadata): Require use-cases in meta json (#4321)
* Require use-cases in meta json

Co-authored-by: Copilot <copilot@github.com>

* adjust schema

* Adjust icon meta json files

* Add usecases to tags.json

---------

Co-authored-by: Copilot <copilot@github.com>
2026-05-28 10:15:02 +02:00
BarakudumandKarsa 84ab8524b5 feat(icon): added globe-check (#4342)
Co-authored-by: Karsa <contact@karsa.org>
2026-05-27 13:45:13 +02:00
Eric FennisandCopilot Autofix powered by AI 071e4d2738 feat(copilot): Adding copilot instructions (#4407)
* Adding copilot instructions

* Adjust text

* Potential fix for pull request finding

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

* Add contributors to schema

* Adjust headers

* Potential fix for pull request finding

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

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-22 16:08:38 +02:00
Eric Fennisandcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> 3c9d1a56a4 Update deps (#4377)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-05-22 12:58:05 +02:00
Jakob Guddas c20dd8464d fix: limit icon size to a maximum of 256 pixels (#4398)
Ensure icon size does not exceed 256 pixels.
2026-05-22 12:04:48 +02:00
dependabot[bot] 29af709846 chore(deps): bump ws from 8.18.0 to 8.20.1 (#4392) 2026-05-22 10:03:13 +02:00
dependabot[bot] 410dfc3577 chore(deps): bump devalue from 5.8.0 to 5.8.1 (#4391) 2026-05-22 10:03:01 +02:00
dependabot[bot] 574e156701 chore(deps): bump @tootallnate/once from 2.0.0 to 2.0.1 (#4404) 2026-05-22 09:56:47 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 22cfe96931 chore(deps): bump brace-expansion from 1.1.11 to 5.0.6 (#4386)
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.11 to 5.0.6.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/1.1.11...v5.0.6)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 5.0.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-20 11:38:51 +02:00
Jamie Law 1475fc02e0 fix(icons): changed martini icon (#4335)
* Updated icons/martini.svg

* Updated icons/martini.json

* Don't round bottom of glass

Also increase the size of the base to make the glass a little less top-heavy

* Update tags for `martini`
2026-05-20 11:35:37 +02:00
Eric FennisandCopilot Autofix powered by AI 7f14e74e4d feat(site): Certificate dev links (#4390)
* Update readme

* Add carbon ads component

* Adjust config

* Adjust ads

* minor fixes

* Remove script

* Place back script

* Add cert link component

* add certificates link

* Adds new images

* Formatting

* Potential fix for pull request finding

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

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-20 11:34:51 +02:00
Eric Fennis 5b40f2c5a7 feat(site): Adds survey overlay to website (#4380)
* Finalize overlay

* Minor fix

* Remove if

* cleanup

* Revert theme config change

* Remove comments

* Format code

* Use localstorage instead of session storage

* Improve css

* Update old-package link
2026-05-15 18:36:44 +02:00
Eric Fennis bac39e6c53 chore(repo): Update issue templates and documentation for package ren… (#4379)
* chore(repo): Update issue templates and documentation for package renaming and deprecations

* Format code

* Remove flutter label

* Format code
2026-05-15 17:55:33 +02:00
Eric Fennis 523026ac18 chore(lucide-vue-next|lucide-svelte|lucide-angular): Remove deprecated packages (#4376)
* Remove deprecated packages

* Remove `lucide-angular` package

* Remove workflow

* Update lock file
2026-05-15 15:03:42 +02:00
Rodrigo Rodrigues 2214caa407 feat(icons): added blender icon (#3884)
* original/blender: add  icon

* fix typo in tags, clean tags

* srhink width by 1px
2026-05-14 13:39:44 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 105f501730 chore(deps-dev): bump astro from 6.1.6 to 6.1.10 (#4361)
Bumps [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) from 6.1.6 to 6.1.10.
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/astro@6.1.10/packages/astro)

---
updated-dependencies:
- dependency-name: astro
  dependency-version: 6.1.10
  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-05-14 13:29:14 +02:00
BarakudumandKarsa 5f787f956b feat(icons): added sticky note variants (#4348)
* feat(icons): added `sticky-note` variants

* feat(icons): added `sticky-notes`

* applied requested changes from @karsa-mistmere

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

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-05-14 13:28:36 +02:00
Eric Fennis 437c370821 chore(site): Updates to site and updated carbon ads (#4359)
* Update readme

* Add carbon ads component

* Adjust config

* Adjust ads

* minor fixes

* Remove script

* Remove commented code

* Revert icon changes

* Format code

* Apply some feedback from Copilot
2026-05-12 08:09:01 +02:00
Eric Fennis fb885f333a Merge branch 'main' of https://github.com/lucide-icons/lucide 2026-05-11 19:31:00 +02:00
Eric Fennis 71ec48ce30 chore: Remove npm lock file 2026-05-11 19:30:54 +02:00
Swastik Sharmagithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Jakob Guddas
d624fc51ab feat(icon): added broccoli icon (#4263)
* feat(icon): add broccoli icon against issue#4094

* Update icons/broccoli.json

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

* fix(icons): tilt broccoli icon to 45 degrees and update contributors

* Modify broccoli SVG paths for updated design

* Update contributors in broccoli.json

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jakob Guddas <github@jguddas.de>
2026-05-11 19:20:49 +02:00
Jakob Guddas 1c381a075c fix(icons): changed chart-no-axes-combined icon (#3567)
* Updated icons/chart-no-axes-combined.svg

* Updated icons/chart-no-axes-combined.json
2026-05-11 19:17:24 +02:00
Jamie LawandJakob Guddas a168a87834 fix(icons): changed volleyball icon (#4338)
* Updated icons/volleyball.svg

* Updated icons/volleyball.json

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>
2026-05-11 19:13:17 +02:00
Jakob Guddas 7e9def13a6 fix(icons): changed candy-cane icon (#4148)
* Updated icons/candy-cane.svg

* Updated icons/candy-cane.json
2026-05-11 19:12:44 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 228c86ed12 chore(deps-dev): bump simple-git from 3.33.0 to 3.36.0 (#4349)
Bumps [simple-git](https://github.com/steveukx/git-js/tree/HEAD/simple-git) from 3.33.0 to 3.36.0.
- [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.36.0/simple-git)

---
updated-dependencies:
- dependency-name: simple-git
  dependency-version: 3.36.0
  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-05-11 19:11:18 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 50b7038d27 chore(deps-dev): bump nitropack from 2.13.1 to 2.13.4 (#4352)
Bumps [nitropack](https://github.com/nitrojs/nitro) from 2.13.1 to 2.13.4.
- [Release notes](https://github.com/nitrojs/nitro/releases)
- [Changelog](https://github.com/nitrojs/nitro/blob/main/changelog.config.ts)
- [Commits](https://github.com/nitrojs/nitro/compare/v2.13.1...v2.13.4)

---
updated-dependencies:
- dependency-name: nitropack
  dependency-version: 2.13.4
  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-05-11 19:10:30 +02:00
Jamie Law a51e94b25c fix(icons): changed landmark icon (#4334)
* Updated icons/landmark.svg

* Updated icons/landmark.json

* Update tags for `landmark`
2026-05-08 09:55:11 +02:00
Jamie LawandJakob Guddas 3d7a12949b fix(icons): changed text-cursor icon (#4340)
* Updated icons/text-cursor.svg

* Updated icons/text-cursor.json

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>
2026-05-08 09:53:23 +02:00
Karsa 07c885e6c1 fix(docs): fix zephyr-cloud URL in readmes 2026-05-07 15:35:49 +02:00
Thomas HochstetterandAxtho 446e644e63 fix(vue): clone slots before passing to icon (#4339)
Co-authored-by: Axtho <th@ebtc.org>
2026-05-01 14:52:32 +02:00
Jakob Guddas 6d38f90429 fix: remove 'less' from brand stopwords (#4331) 2026-04-30 10:42:58 +02:00
Jakob Guddas 56e49f1216 feat(icons): added repeat-off icon (#3102)
* Added icons/repeat-off.svg

* Added icons/repeat-off.json

* Updated icons/repeat-off.json
2026-04-29 09:28:37 +02:00
cc5129073e feat(icons): add waves-vertical icon (#3867)
* Rename `waves` to `waves-horizontal` and add `waves-vertical`

* Increase spacing

* Update tags for `waves-vertical`

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

* Remove old `waves` icons

---------

Co-authored-by: Karsa <contact@karsa.org>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-04-29 08:52:45 +02:00
1da4059d59 fix(docs): sync URL params with UI state on categories page (#4111)
* fix(docs): sync URL params with UI state on category and search interactions

Search, category selection, and the icon detail drawer each modified the
URL independently, causing parameters to be silently dropped. Searching
didn't clear the category hash, clicking a category dropped the search
param, and closing the drawer hard-coded the path without preserving
either.

Consolidate URL construction so every navigation preserves both ?search=
and #category as appropriate. Split useCategoryView into a pure getter
and a sync variant (useCategoryViewSync) so event listeners and route
watchers are registered once in CategoryList.vue instead of in every
consumer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(docs): disable click on inactive categories during search

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update docs/.vitepress/theme/components/icons/IconsCategoryOverview.vue

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

* Update docs/.vitepress/theme/components/icons/IconsOverview.vue

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

* refactor(docs): use URL constructor in CategoryListItem

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-04-28 20:38:59 +02:00
Ankit Sharma 4b2d07b79c feat(icons): added astroid icon (#4217)
* Added icons/astroid.svg

* Added icons/astroid.json

* Update astroid.svg to match Lucide Guidelines

fix: update astroid SVG to match Lucide design guidelines
2026-04-28 18:57:44 +02:00
50d8af5a10 docs(readme): Update readme files (#4320)
* Update readme

* Update vue readme file

* Update readme files

Co-authored-by: Copilot <copilot@github.com>

* Update badge paths

* Update docs paths

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

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

* Update README.md

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

* Update packages/svelte/README.md

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

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-26 10:43:49 +02:00
Swastik Sharmaandgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 92e02f5042 feat(icon): add folder-bookmark icon (#4262)
* feat(icon): add folder-bookmark icon

* Update icons/folder-bookmark.json

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

* refactor(icon): Update folder-bookmark design

* refactor(icons): Add contributors and update tags for folder-bookmark icon

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-26 09:37:24 +02:00
Petter Lauvrak 1675213eb6 feat(icons): added bell-check icon (#4152)
* Added icons/bell-check.svg

* Added icons/bell-check.json
2026-04-24 15:50:13 +02:00
Spleefies ac25ea327d feat(icons): added layers-minus icon (#4005)
* Added icons/layers-minus.svg

* Added icons/layers-minus.json

* use alternative design

* Update layers-minus.svg
2026-04-24 15:50:03 +02:00
Jamie LawandKarsa b9e922b100 Updated icons/rotate-3d.svg (#4299)
Co-authored-by: Karsa <contact@karsa.org>
2026-04-24 15:42:47 +02:00
Swastik SharmaandKarsa 6e42a8792a feat(icon): add heart-x icon (#4264)
* feat(icon): add heart-x icon

* Update icons/heart-x.json

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

* Update icons/heart-x.json

* Update heart-x.json

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-04-24 15:42:41 +02:00
SpleefiesandKarsa d7f8d17986 feat(docs): blur background of framework-select (#4238)
* blur background of framework-select

* Update docs/.vitepress/theme/components/guide/FrameworkSelect.vue

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

* remove duplicate label css

* Update docs/.vitepress/theme/components/guide/FrameworkSelect.vue

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-04-24 14:41:42 +02:00
Karsa c81e6846c5 test(build-font): added comprehensive unit tests on build-font tool (#4315) 2026-04-24 14:12:43 +02:00
Swastik SharmaandEric Fennis 804d25586b feat(icons): add power and quick tags to zap and zap-off (#4268)
* feat(icons): add power and quick tags to zap and zap-off

* chore(icons): add contributor name

* Update icons/zap.json

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

* Update icons/zap-off.json

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

* Update icons/zap.json

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

* Update icons/zap-off.json

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-04-24 14:10:20 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 39e3964a9b chore(deps-dev): bump astro from 6.0.8 to 6.1.6 (#4310)
Bumps [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) from 6.0.8 to 6.1.6.
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/astro@6.1.6/packages/astro)

---
updated-dependencies:
- dependency-name: astro
  dependency-version: 6.1.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-04-24 13:31:53 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 2f8257d8b4 chore(deps): bump svgo from 3.3.2 to 3.3.3 (#4119)
Bumps [svgo](https://github.com/svg/svgo) from 3.3.2 to 3.3.3.
- [Release notes](https://github.com/svg/svgo/releases)
- [Commits](https://github.com/svg/svgo/compare/v3.3.2...v3.3.3)

---
updated-dependencies:
- dependency-name: svgo
  dependency-version: 3.3.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-04-24 11:24:47 +02:00
blt-randEric Fennis fe0bd9b887 fix(@lucide/svelte): proper doc comments for svelte components (#4267)
* fix(@lucide/svelte): proper doc comments for svelte components

* Update license text

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-04-24 10:42:50 +02:00
Jessica Lu d0229f4cfc docs: add missing period to TypeScript Support guide (#4309)
Add period to the end of sentence in the description of https://lucide.dev/guide/react/advanced/typescript.
2026-04-24 10:07:51 +02:00
Jakob Guddas cc1caae101 feat(icons): added timeline icon (#4270)
* Added icons/timeline.svg

* Added icons/timeline.json

* Updated icons/timeline.svg

* Updated icons/timeline.json
2026-04-23 17:26:46 +02:00
KarsaandEric Fennis d632a8e272 fix(build-font): add collision detection to font codepoints & make allocation explicitly sequential (#4300)
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2026-04-23 17:24:21 +02:00
Karsa 653e44b832 feat(packages): use .mjs for ESM bundles (#4285) 2026-04-23 17:00:02 +02:00
Jakob GuddasandKarsa f0eaba827e fix(gh-icon): update colors for ColoredPath component (#4233)
* Update colors for ColoredPath component

* fix(site): fix linting issues SvgPreview

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-04-20 11:23:35 +02:00
Swastik SharmaandKarsa dc803026e0 fix(packages/angular): allow string inputs for size (#4253)
* fix: Type change for size: string | number across the LucideConfig

* fix(packages/angular): fix typing issues in @lucide/angular, should update all usages and declarations of size

* fix: revert changes made to lucide-react context.ts

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-04-20 07:41:32 +02:00
Zeenat Lawal 3c62e4bfef feat(icons): added bookmark-off icon (#4283)
* feat: add icons/bookmark-off.svg

* feat: add icons/bookmark-off.json

* feat: update icons/bookmark-off.json contributors and tags
2026-04-09 08:46:23 +02:00
Karsa 6d6da7ca3a feat(docs): use initOnMounted: true for useSessionStorage in CarbonAdOverlay (#4275)
* feat(docs): use computed for `hide-ad`

* Update CarbonAdOverlay.vue

* Update CarbonAdOverlay.vue

* feat(site): add initOnMounted: true to useSessionStorage in CarbonAdOverlay.vue
2026-04-08 10:01:52 +02:00
dependabot[bot]dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Karsa
2453b6467d chore(deps): bump vite from 5.4.21 to 6.4.2 (#4286)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.21 to 6.4.2.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.4.2/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.4.2/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.4.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Karsa <contact@karsa.org>
2026-04-08 09:55:28 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> a88e7070cc chore(deps): bump lodash-es from 4.17.23 to 4.18.1 (#4251)
Bumps [lodash-es](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.23...4.18.1)

---
updated-dependencies:
- dependency-name: lodash-es
  dependency-version: 4.18.1
  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-04-08 09:44:26 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> a7611e2957 chore(deps-dev): bump vite from 7.3.1 to 7.3.2 (#4276)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.3.1 to 7.3.2.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.3.2/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.3.2/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.3.2
  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-04-08 09:29:30 +02:00
Karsa 7c2ff2e5d6 fix(icons): remove ui/ux tag from heart-minus, add delete instead (#4266) 2026-04-04 17:25:09 +02:00
blt-r 51e37e2e2c fix aria-hidden="true" in @lucide/svelte (#4234) 2026-04-03 14:43:35 +02:00
Karsa 5faceb5495 fix(docs): improve mobile layout of v1 banner (#4254)
* fix(docs): improve mobile layout of v1 banner

* fix(docs): make top banner sticky instead of fixed, this way there's no need for hack-ish explicit heights

* fix(docs): add --vp-layout-top-height media query declaration for when navbar becomes sticky
2026-04-03 10:16:39 +02:00
Karsa 3814a64cd5 fix(docs): fix typo in combining icons docs 2026-04-01 13:22:05 +02:00
Jakob GuddasandKarsa 43c76b1f08 fix(icons): renamed text-select to square-dashed-text (#3943)
* fix(icons): renamed `text-select` to `square-dashed-text`

* Update square-dashed-text.json

* Update square-dashed-text.json

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-03-30 09:15:51 +02:00
Karsa 2401a39571 fix(icons): fixes gap issues in radio-off.svg (#4227) 2026-03-28 09:38:32 +01:00
Karsa 7623e23f78 feat(docs): add Zephyr Cloud to Hero Backers tier & rework updateSponsors script to also handle, well, sponsors (#4226) 2026-03-28 07:48:26 +01:00
Ankit Sharma 663a9d7fc3 Fix link to icon design principles in statement (#4225)
Updated the link to the icon design guide in the brand logos statement. Previous like was giving 404 error.
2026-03-28 07:48:12 +01:00
Toma d53f615cf3 fix(lucide-static): add viewBox attribute to sprite symbol elements (#4223)
Sprite symbols were missing the viewBox attribute, causing icons to be clipped instead of scaling proportionally when used at smaller sizes.

Fixes #2768
2026-03-28 07:47:55 +01:00
Ankit Sharma d8700b257a docs: fix broken links in documentation (#4224)
docs: fix broken links in documentation (pull request template and brand logos statement) from "lucide.dev/guide/design/" to "lucide.dev/contribute/"
2026-03-28 07:47:36 +01:00
Eric Fennis 30bb61917b ci(@lucide/angular): Fix publishing problem (#4213)
* ci(@lucide/angular): Fix publishing problem

* Format files
2026-03-26 14:14:22 +01:00
Rajnish Mehta 1e6b96db3d chore(icons): Username change knarlix to RajnishKMehta (#4208)
* Update shield-cog-corner.json

* Update shield-cog.json
2026-03-26 07:32:49 +01:00
Ryan Hutchison 5c52182778 Add packageDirname for @lucide/angular (#4211) 2026-03-26 07:31:46 +01:00
Tony SullivanandKarsa 1fde1f1c1a feat(icons): added map-pin-search icon (#4125)
* Added icons/map-pin-search.svg

* Added icons/map-pin-search.json

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-03-25 18:46:24 +01:00
Eric Fennis dada0a8297 fix(lucide-react): Fix dynamic imports (#4210)
* fix(lucide-react): Fix dynamic imports

* Adjust imports

* Format code

* Ignore eslint error
2026-03-25 18:44:25 +01:00
Karsa fa09963bf8 fix(pipeline): revert custom angular publish step. not even this solves it. 2026-03-24 17:58:37 +01:00
Sondre Kongsgård cc53931091 feat(icons): added radio-off icon (#4138)
* Added icons/radio-off.svg

* Added icons/radio-off.json
2026-03-24 17:52:39 +01:00
Karsa 86b3ddfdca Merge remote-tracking branch 'origin/main' 2026-03-24 17:51:45 +01:00
Karsa f1360e1d9b feat(pipeline): fix working directory (angular, not @lucide/angular) 2026-03-24 17:50:32 +01:00
Jakob Guddas e2df99b883 feat(icons): added beef-off icon (#3816)
* Added icons/beef-off.svg

* Added icons/beef-off.json
2026-03-24 17:47:31 +01:00
Karsa aed7aeaa72 feat(pipeline): move angular publish step from lucide-static ⇒ release 2026-03-24 17:46:54 +01:00
Youri NouchetandKarsa 11ff82b056 feat(icons): added sport-shoe icon (#3953)
* Added icons/sport-shoe.svg

* Added icons/sport-shoe.json

* Update sport-shoe.svg

---------

Co-authored-by: Karsa <contact@karsa.org>
2026-03-24 17:41:27 +01:00
Karsa 25d96b7ec0 feat(pipeline): fix linting issues 2026-03-24 17:41:09 +01:00
Karsa 10962ce51b feat(pipeline): add separate Angular publish step using dist as the working directory & stripping publishConfig.directory from its package.json 2026-03-24 17:36:52 +01:00
Karsa 7dfbd21bce feat(pipeline): revert debug changes made to release.yml 2026-03-24 17:23:20 +01:00
Karsa b18f27ea8d feat(pipeline): add angular debug to release workflow 2026-03-24 17:14:31 +01:00
Karsa 5e6186ff70 feat(pipeline): add angular debug to release workflow 2026-03-24 17:12:55 +01:00
Karsa acb947a770 Merge remote-tracking branch 'origin/main' 2026-03-24 17:11:02 +01:00
Karsa e9bec8e6f8 feat(pipeline): add angular debug to release workflow 2026-03-24 17:10:48 +01:00
Karsa 4ea3561788 feat(pipeline): add angular debug to release workflow 2026-03-24 17:09:32 +01:00
Karsa 76c1b0caa9 feat(pipeline): add release-angular workflow for testing 2026-03-24 16:45:40 +01:00
Karsa f2eab2c30a feat(icons): debug angular release 2026-03-24 16:21:47 +01:00
Karsa 3fc90467a3 feat(pipeline): re-revert from the working-directory solution & set default tag as latest 2026-03-24 16:18:39 +01:00
Rajnish MehtaandRajnish Mehta 519aae64d6 feat(icons): added shield-cog icon (#3902)
* Added icons/shield-cog.svg

* Added icons/shield-cog.json

* Added icons/shield-cog-2.svg

* Added icons/shield-cog-2.json

* name issue fixed

* Add shield-cog-corner.svg icon file

* Add shield-cog-corner.json icon file

* Rename shield-cog-mid.svg to shield-cog.svg

* Add shield-cog.json file

---------

Co-authored-by: Rajnish Mehta <43362941-KnarliX@users.noreply.replit.com>
2026-03-24 16:12:32 +01:00
Karsa 7a395122a1 feat(pipeline): revert to working-directory solution for testing 2026-03-24 16:10:24 +01:00
2890 changed files with 32383 additions and 27703 deletions
+1
View File
@@ -9,3 +9,4 @@ strikethrough
touchpad
ungroup
toc
sunlounger
+9 -11
View File
@@ -13,21 +13,19 @@ body:
description: Which Lucide packages are affected? You may select more than one.
options:
- label: lucide
- label: lucide-angular (old version)
- label: '@lucide/angular (new version)'
- label: '@lucide/astro'
- label: lucide-flutter
- label: lucide-preact
- label: lucide-react
- label: '@lucide/vue'
- label: '@lucide/svelte'
- label: '@lucide/angular'
- label: '@lucide/astro'
- label: lucide-react-native
- label: lucide-preact
- label: lucide-solid
- label: lucide-static
- label: lucide-svelte (old version)
- label: '@lucide/svelte (new version)'
- label: lucide-vue
- label: lucide-vue-next
- label: lucide-astro
- label: '@lucide/icons'
- label: lucide-vue-next (deprecated)
- label: lucide-svelte (deprecated)
- label: lucide-angular (deprecated)
- label: Figma plugin
- label: source/main
- label: other/not relevant
@@ -38,7 +36,7 @@ body:
attributes:
label: Version
description: What version of Lucide are you running?
placeholder: e.g. 0.289.1
placeholder: e.g. 1.1.0
validations:
required: true
- type: checkboxes
+8 -10
View File
@@ -13,21 +13,19 @@ body:
description: Which Lucide project do you wish this feature were added to? You may select more than one.
options:
- label: lucide
- label: lucide-angular (old version)
- label: '@lucide/angular (new version)'
- label: '@lucide/astro'
- label: lucide-flutter
- label: lucide-preact
- label: lucide-react
- label: '@lucide/vue'
- label: '@lucide/svelte'
- label: '@lucide/angular'
- label: '@lucide/astro'
- label: lucide-react-native
- label: lucide-preact
- label: lucide-solid
- label: lucide-static
- label: lucide-svelte (old version)
- label: '@lucide/svelte (new version)'
- label: lucide-vue
- label: lucide-vue-next
- label: lucide-astro
- label: '@lucide/icons'
- label: lucide-vue-next (deprecated)
- label: lucide-svelte (deprecated)
- label: lucide-angular (deprecated)
- label: Figma plugin
- label: all JS packages
- label: site
+8
View File
@@ -0,0 +1,8 @@
## Reviewing PRs
When reviewing PRs, please respond in a friendly and constructive manner.
- First, thank the contributor for their contribution in an enthusiastic way.
- If you have any suggestions for improvement, provide them clearly and concisely.
- If you have any questions about the PR, ask them respectfully.
- Let the contributor know that we have many PRs to review and that we appreciate their patience while we review their contribution.
@@ -0,0 +1,20 @@
---
applyTo: "icons/*.json"
---
# JSON Metadata Descriptor
The schema for the JSON metadata descriptor can be found in `icon.schema.json`. It defines the required and optional properties for the JSON files that accompany each icon. The JSON metadata descriptor should be placed in the same directory as the SVG file of the icon and should have the same name as the SVG file, but with a `.json` extension. For example, if the SVG file is named `home.svg`, the JSON metadata descriptor should be named `home.json`.
## Contributors
The `contributors` property is a required array of GitHub usernames for the people who created or contributed to the icon. It is used to give credit to contributors and to track the icon's history. Add the PR author to the `contributors` array if they are not already listed and they have made a significant contribution to the icon's SVG.
## Tags
The `tags` property is an array of strings that describe the icon and can be used for searching.
Validate the tags against the `icon.schema.json` to ensure they are correctly formatted and adhere to the defined structure.
Provide tag suggestions based on the name of the icon and the use cases provided in the PR description. Use the existing tags in the repository as a reference for consistency and to avoid duplicates. Don't suggest words like: 'icon' and preferably use single words. Tags should always be in lowercase and should not contain spaces. The name of icon should not be included in the tags, as it is already specified.
# Categories
The `categories` property is an array of strings that specify the categories to which the icon belongs, such as "devices", "interface", "media", etc. See the `categories` property in the `icon.schema.json` for more details on the allowed values. The categories should be chosen based on the use cases provided in the PR description and the existing categories in the repository. The categories should be relevant to the icon and should help users find the icon when searching for specific types of icons. The name of icon should not be included in the categories, as it is already specified. Suggest categories based on the name of the icon and the use cases provided in the PR description. Use the existing categories in the repository as a reference for consistency and to avoid duplicates. Categories should always be in lowercase and should not contain spaces.
+2 -10
View File
@@ -52,15 +52,13 @@
💎 vue package:
- changed-files:
- any-glob-to-any-file:
- 'packages/lucide-vue/*'
- 'packages/lucide-vue-next/*'
- 'packages/vue/*'
# For changes in the Lucide angular package
🅰️ angular package:
- changed-files:
- any-glob-to-any-file:
- 'packages/angular/*'
- 'packages/lucide-angular/*'
# For changes in the Lucide preact package
⚛️ preact package:
@@ -72,7 +70,7 @@
🧣 svelte package:
- changed-files:
- any-glob-to-any-file:
- 'packages/lucide-svelte/*'
- 'packages/svelte/*'
# For changes in the Lucide solid package
🪝 solid package:
@@ -97,9 +95,3 @@
- changed-files:
- any-glob-to-any-file:
- 'packages/lucide-static/*'
# For changes in the Lucide flutter package
🏹 flutter package:
- changed-files:
- any-glob-to-any-file:
- 'packages/lucide-flutter/*'
+4 -2
View File
@@ -41,13 +41,15 @@ Common scopes: icons, docs, studio, site, dev
### Naming <!-- ONLY for new icons -->
<!-- All of these requirements must be fulfilled. -->
- [ ] I've read and followed the [naming conventions](https://lucide.dev/guide/design/icon-design-guide#naming-conventions)
- [ ] I've read and followed the [naming conventions](https://lucide.dev/contribute/icon-design-guide#naming-conventions)
- [ ] I've named icons by what they are rather than their use case.
- [ ] I've provided meta JSON files in `icons/[iconName].json`.
### Design <!-- ONLY for new icons -->
<!-- All of these requirements must be fulfilled. -->
- [ ] I've read and followed the [icon design guidelines](https://lucide.dev/guide/design/icon-design-guide)
- [ ] I've read and followed the [icon design guidelines](https://lucide.dev/contribute/icon-design-guide)
- [ ] I've made sure that the icons don't [already exist](https://lucide.dev/icons), including the [Lab directory](https://github.com/lucide-icons/lucide/tree/main/lab).
- [ ] I've made sure that the icons look sharp on low DPI displays.
- [ ] I've made sure that the icons look consistent with the icon set in size, optical volume and density.
- [ ] I've made sure that the icons are visually centered.
+30 -5
View File
@@ -27,13 +27,38 @@ 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:
check-dispatch-gate:
if: github.repository == 'lucide-icons/lucide' &&
startsWith(github.event.head_commit.message, 'feat(icons)') &&
github.event_name != 'workflow_dispatch'
runs-on: ubuntu-latest
outputs:
RELEASE_ENVIRONMENT: ${{ steps.environment.outputs.RELEASE_ENVIRONMENT }}
steps:
- uses: actions/checkout@v6
- name: Fetch tags
run: git fetch --all --tags
- name: Check if latest tag was created today
id: environment
run: |
LATEST_TAG=$(git tag --sort=-v:refname | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1)
TAG_DATE=$(git log -1 --format=%cs "$LATEST_TAG")
TODAY=$(date +%Y-%m-%d)
if [ "$TAG_DATE" == "$TODAY" ]; then
echo "::warning::A release tag already exists for today ($TODAY): $LATEST_TAG. Manual approval will be required to proceed."
echo "RELEASE_ENVIRONMENT=Icon Release Gated" >> $GITHUB_OUTPUT
else
echo "RELEASE_ENVIRONMENT=Icon Release" >> $GITHUB_OUTPUT
fi
create-release:
if: github.repository == 'lucide-icons/lucide' && startsWith(github.event.head_commit.message, 'feat(icons)') && github.event_name != 'workflow_dispatch'
if: github.repository == 'lucide-icons/lucide'
needs: check-dispatch-gate
environment: ${{ needs.check-dispatch-gate.outputs.RELEASE_ENVIRONMENT }}
runs-on: ubuntu-latest
outputs:
VERSION: ${{ steps.new-version.outputs.NEW_VERSION }}
@@ -33,7 +33,7 @@ jobs:
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**.
[Click here to read our official statement about brand logos in Lucide.](./BRAND_LOGOS_STATEMENT.md)
[Click here to read our official statement about brand logos in Lucide.](https://github.com/lucide-icons/lucide/blob/main/BRAND_LOGOS_STATEMENT.md)
You can [search for similar issues.](https://github.com/lucide-icons/lucide/issues?q=is%3Aissue+${VALUE})
+1 -3
View File
@@ -1,9 +1,7 @@
name: Linting PR
name: Linting PR code
on:
pull_request:
paths-ignore:
- icons/*.svg
jobs:
lint-code:
+1 -1
View File
@@ -1,4 +1,4 @@
name: Linting PR
name: Linting PR title
on:
pull_request:
+29 -1
View File
@@ -7,6 +7,7 @@ on:
pull_request:
paths:
- 'icons/*'
- 'lab/*'
jobs:
lint-filenames:
@@ -17,20 +18,47 @@ jobs:
contents: read
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: Get changed files
id: changed-files
uses: tj-actions/changed-files@v46
with:
files: icons/*
files: |
icons/*
lab/*
- name: Generate annotations
run: node ./scripts/lintFilenames.mts
env:
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
check-lab-icons:
name: Check Lab Icons
runs-on: ubuntu-latest
permissions:
contents: read
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: Check lab icons do not already exist in icons
run: node ./scripts/checkLabIcons.mts
lint-aliases:
name: Check Uniqueness of Aliases
runs-on: ubuntu-latest
-44
View File
@@ -1,44 +0,0 @@
name: Lucide Angular checks
on:
push:
branches:
- next
pull_request:
paths:
- packages/lucide-angular/**
- tools/build-icons/**
- pnpm-lock.yaml
jobs:
build:
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: Build
run: pnpm --filter lucide-angular build
test:
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-angular test
+3
View File
@@ -23,6 +23,9 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Execute unit tests for build-font
run: pnpm test:font
- name: Create font in ./lucide-font
run: pnpm build:font
+30
View File
@@ -0,0 +1,30 @@
name: Lucide Lab checks
on:
pull_request:
paths:
- packages/lab/**
- packages/shared/**
- tools/build-icons/**
- tools/rollup-plugins/**
- pnpm-lock.yaml
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
cache: 'pnpm'
node-version-file: 'package.json'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm --filter @lucide/lab build
-46
View File
@@ -1,46 +0,0 @@
name: Lucide Svelte checks
on:
push:
branches:
- next
pull_request:
paths:
- packages/lucide-svelte/**
- packages/shared/**
- tools/build-icons/**
- tools/rollup-plugins/**
- pnpm-lock.yaml
jobs:
build:
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: Build
run: pnpm --filter lucide-svelte build
test:
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 test
-46
View File
@@ -1,46 +0,0 @@
name: Lucide Vue Next checks
on:
push:
branches:
- next
pull_request:
paths:
- packages/lucide-vue-next/**
- packages/shared/**
- tools/build-icons/**
- tools/rollup-plugins/**
- pnpm-lock.yaml
jobs:
build:
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: Build
run: pnpm --filter lucide-vue-next build
test:
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-vue-next test
@@ -1,4 +1,4 @@
name: Pull request tags suggestions
name: Pull request metadata suggestions
on:
pull_request_target:
@@ -6,8 +6,8 @@ on:
- 'icons/*.json'
jobs:
pull-request-tags-suggestions:
name: Pull Request Tags Suggestions
pull-request-metadata-suggestions:
name: Pull Request Metadata Suggestions
runs-on: ubuntu-latest
permissions:
contents: read
@@ -29,7 +29,7 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Generate comment markup
run: node ./scripts/suggestTags.mts
run: node ./scripts/suggestMetaData.mts
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
PULL_REQUEST_NUMBER: ${{ github.event.number }}
+6 -6
View File
@@ -13,16 +13,13 @@ on:
type: string
tag:
description: NPM tag
default: 'next' # set to latest after v1 release
default: 'latest'
type: string
permissions:
id-token: write # Required for OIDC
contents: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
prepare:
if: github.repository == 'lucide-icons/lucide' && contains('["ericfennis", "karsa-mistmere", "jguddas"]', github.actor)
@@ -74,7 +71,7 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Set new version
run: pnpm --fail-if-no-match --filter ${{ matrix.package }} version --new-version ${{ needs.prepare.outputs.VERSION }} --no-git-tag-version
run: pnpm version ${{ needs.prepare.outputs.VERSION }} --filter ${{ matrix.package }} --fail-if-no-match --no-git-tag-version
- name: Build
run: pnpm --filter ${{ matrix.package }} build
@@ -108,7 +105,7 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Set new version
run: pnpm --filter lucide-static version --new-version ${{ needs.prepare.outputs.VERSION }} --no-git-tag-version
run: pnpm version ${{ needs.prepare.outputs.VERSION }} --filter lucide-static --no-git-tag-version
- name: Move Font
run: cp -r lucide-font packages/lucide-static/font
@@ -136,6 +133,9 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Execute unit tests for build-font
run: pnpm test:font
- name: Create font in ./lucide-font
run: pnpm build:font --saveCodePoints
env:
+42
View File
@@ -0,0 +1,42 @@
name: Weekly Repo Report
on:
workflow_dispatch:
# Run this workflow every Monday at 07:00 UTC
schedule:
- cron: '0 7 * * 1'
permissions:
contents: read
jobs:
weekly-summary:
runs-on: ubuntu-latest
steps:
- name: Set up Node.js environment
uses: actions/setup-node@v4
with:
node-version: 24
- name: Install Copilot CLI
run: npm install -g @github/copilot
- name: Run the prompt
env:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
run: |
copilot -p "${{ vars.REPO_REPORT_PROMPT }} Write the details to summary.md" --allow-tool='shell(git:*)' --allow-tool=write --no-ask-user
cat summary.md >> "$GITHUB_STEP_SUMMARY"
- name: Post report to Discord (private channel)
env:
DISCORD_WEBHOOK_URL: ${{ secrets.LUCIDE_DISCORD_WEBHOOK }}
run: |
jq -Rs '{
embeds: [{
title: "📊 Weekly Repo Report",
description: (.[0:4096]),
color: 5814783
}]
}' summary.md > payload.json
curl -sS --fail -X POST \
-H "Content-Type: application/json" \
-d @payload.json \
"$DISCORD_WEBHOOK_URL"
+2 -2
View File
@@ -1,6 +1,6 @@
name: 'Request Review'
name: Request Review
on:
pull_request_target:
pull_request:
types: [opened]
paths:
- icons/*.svg
+9 -1
View File
@@ -26,15 +26,20 @@ packages/**/src/utils/*.ts
packages/**/src/dynamicIconImports.ts
packages/**/DynamicIcon.d.ts
packages/**/dynamicIconImports.js
packages/**/dynamicIconImports.mjs
packages/**/dynamicIconImports.d.ts
packages/**/dynamicIconImports.d.mts
packages/**/dynamicIconImports.js.map
packages/**/dynamicIconImports.mjs.map
packages/**/dynamic.d.ts
packages/**/dynamic.d.mts
packages/**/dynamic.mjs.map
packages/**/dynamic.mjs
packages/**/LICENSE
categories.json
tags.json
.vercel
package-lock.json
# docs
docs/.vitepress/cache
@@ -48,8 +53,11 @@ docs/.vitepress/data/categoriesData.json
docs/.vitepress/data/iconDetails
docs/.vitepress/data/relatedIcons.json
docs/.vitepress/data/brandStopwords.json
docs/.vitepress/data/iconPopularity
docs/.vitepress/data/lab/iconNodes
docs/.vitepress/data/lab/iconMetaData.ts
docs/.vitepress/data/lab/iconPopularity
docs/.vercel
docs/.nitro
docs/public/og/**
!docs/public/og/general.png
.gitignore
+5 -4
View File
@@ -7,8 +7,8 @@ docs/.vitepress/cache
docs/.vitepress/data
docs/.nitro
# lucide-angular
packages/lucide-angular/.angular/cache
# @lucide/angular
packages/angular/.angular
# lucide-static
packages/lucide-static/icons
@@ -17,7 +17,8 @@ packages/lucide-static/sprite.svg
packages/lucide-static/tags.json
packages/lucide-static/icon-nodes.json
packages/lucide-static/font
packages/svelte/.svelte-kit
# lucide-svelte
packages/lucide-svelte/src/icons/*.svelte
packages/lucide-svelte/.svelte-kit
packages/svelte/src/icons/*.svelte
packages/svelte/.svelte-kit
+1 -1
View File
@@ -39,7 +39,7 @@ This means adding them could:
Lucide is all about **visual consistency**.
Adding brand logos would:
- Break [our own design rules](https://lucide.dev/guide/design/icon-design-guide#icon-design-principles) for shapes, proportions, and stroke.
- Break [our own design rules](https://lucide.dev/contribute/icon-design-guide#icon-design-principles) for shapes, proportions, and stroke.
- Mix two fundamentally different categories of graphics (pictograms vs. corporate logos).
- Create a library where a subset of icons will always look "out of place".
+1 -1
View File
@@ -30,7 +30,7 @@ Read it here: [ICON_GUIDELINES](https://lucide.dev/contribute/icon-design-guide)
#### Lucide Studio
For formatting and adjusting SVG icons, [@jguddas](https://github.com/jguddas) made a great tool called [Lucide Studio](https://studio.lucide.dev/). It is a web-based SVG editor that allows you to edit and adjust icons in the Lucide style. You can use it to create new icons or modify existing ones.
For formatting and adjusting SVG icons, [@jguddas](https://github.com/jguddas) made a great tool called [Lucide Studio](https://studio.lucide.dev/?utm_source=lucide.dev&utm_medium=contributing-guide). It is a web-based SVG editor that allows you to edit and adjust icons in the Lucide style. You can use it to create new icons or modify existing ones.
#### Editor guides
+19 -14
View File
@@ -7,9 +7,9 @@
</a>
</p>
<p align="center">
<a href="https://github.com/lucide-icons/lucide/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/lucide" alt="license"></a>
<a href="https://github.com/lucide-icons/lucide/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-ISC-green" alt="license"></a>
<a href="https://www.figma.com/community/plugin/939567362549682242/Lucide-Icons"><img src="https://img.shields.io/badge/Figma-F24E1E?logo=figma&logoColor=white" alt="figma installs"></a>
<a href="https://github.com/lucide-icons/lucide/actions/workflows/release.yml"><img src="https://github.com/lucide-icons/lucide/actions/workflows/release.yml/badge.svg" alt="build status"></a>
<a href="https://github.com/lucide-icons/lucide/actions/workflows/ci.yml"><img src="https://github.com/lucide-icons/lucide/actions/workflows/ci.yml/badge.svg" alt="build status"></a>
<a href="https://discord.gg/EH6nSts"><img src="https://img.shields.io/discord/723074157486800936?label=chat&logo=discord&logoColor=%23ffffff&colorB=%237289DA" alt="discord chat"></a>
</p>
<p align="center">
@@ -26,22 +26,22 @@
# Lucide
Lucide is an open-source icon library that provides 1000+ vector (svg) files for displaying icons and symbols in digital and non-digital projects. The library aims to make it easier for designers and developers to incorporate icons into their projects by providing several official [packages](https://lucide.dev/packages) to make it easier to use these icons in your project.
Lucide is an open-source icon library that provides 1600+ vector (svg) files for displaying icons and symbols in digital and non-digital projects. The library aims to make it easier for designers and developers to incorporate icons into their projects by providing several official [packages](https://lucide.dev/packages) to make it easier to use these icons in your project.
## Packages
| Logo | Package | Version | Downloads | Links |
| ---- | ------- | ------- | --------- | ----- |
| <img src="https://lucide.dev/framework-logos/js.svg" alt="JS logo" width="48"> | **`lucide`** | [![npm](https://img.shields.io/npm/v/lucide)](https://www.npmjs.com/package/lucide) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide) | [Docs](https://lucide.dev/guide/packages/lucide) · [Source](./packages/lucide) |
| <img src="https://lucide.dev/framework-logos/react.svg" alt="React logo" width="48"> | **`lucide-react`** | [![npm](https://img.shields.io/npm/v/lucide-react)](https://www.npmjs.com/package/lucide-react) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-react) | [Docs](https://lucide.dev/guide/packages/lucide-react) · [Source](./packages/lucide-react) |
| <img src="https://lucide.dev/framework-logos/vue.svg" alt="Vue logo" width="48"> | **`lucide-vue-next`** | [![npm](https://img.shields.io/npm/v/lucide-vue-next)](https://www.npmjs.com/package/lucide-vue-next) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-vue-next) | [Docs](https://lucide.dev/guide/packages/lucide-vue-next) · [Source](./packages/lucide-vue-next) |
| <img src="https://lucide.dev/framework-logos/svelte.svg" alt="Svelte logo" width="48"> | **`lucide-svelte`** | [![npm](https://img.shields.io/npm/v/lucide-svelte)](https://www.npmjs.com/package/lucide-svelte) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-svelte) | [Docs](https://lucide.dev/guide/packages/lucide-svelte) · [Source](./packages/lucide-svelte) |
| <img src="https://lucide.dev/framework-logos/solid.svg" alt="Solid logo" width="48"> | **`lucide-solid`** | [![npm](https://img.shields.io/npm/v/lucide-solid)](https://www.npmjs.com/package/lucide-solid) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-solid) | [Docs](https://lucide.dev/guide/packages/lucide-solid) · [Source](./packages/lucide-solid) |
| <img src="https://lucide.dev/framework-logos/preact.svg" alt="Preact logo" width="48"> | **`lucide-preact`** | [![npm](https://img.shields.io/npm/v/lucide-preact)](https://www.npmjs.com/package/lucide-preact) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-preact) | [Docs](https://lucide.dev/guide/packages/lucide-preact) · [Source](./packages/lucide-preact) |
| <img src="https://lucide.dev/framework-logos/react-native.svg" alt="React Native logo" width="48"> | **`lucide-react-native`** | [![npm](https://img.shields.io/npm/v/lucide-react-native)](https://www.npmjs.com/package/lucide-react-native) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-react-native) | [Docs](https://lucide.dev/guide/packages/lucide-react-native) · [Source](./packages/lucide-react-native) |
| <img src="https://lucide.dev/framework-logos/angular.svg" alt="Angular logo" width="48"> | **`lucide-angular`** | [![npm](https://img.shields.io/npm/v/lucide-angular)](https://www.npmjs.com/package/lucide-angular) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-angular) | [Docs](https://lucide.dev/guide/packages/lucide-angular) · [Source](./packages/lucide-angular) |
| <img src="https://lucide.dev/framework-logos/astro.svg" alt="Astro logo" width="48"> | **`@lucide/astro`** | [![npm](https://img.shields.io/npm/v/@lucide/astro)](https://www.npmjs.com/package/@lucide/astro) | ![NPM Downloads](https://img.shields.io/npm/dw/@lucide/astro) | [Docs](https://lucide.dev/guide/packages/lucide-astro) · [Source](./packages/astro) |
| <img src="https://lucide.dev/framework-logos/svg.svg" alt="SVG logo" width="48"> | **`lucide-static`** | [![npm](https://img.shields.io/npm/v/lucide-static)](https://www.npmjs.com/package/lucide-static) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-static) | [Docs](https://lucide.dev/guide/packages/lucide-static) · [Source](./packages/lucide-static) |
| <img src="https://lucide.dev/framework-logos/js.svg" alt="JS logo" width="48"> | **`lucide`** | [![npm](https://img.shields.io/npm/v/lucide)](https://www.npmjs.com/package/lucide) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide) | [Docs](https://lucide.dev/guide/lucide) · [Source](./packages/lucide) |
| <img src="https://lucide.dev/framework-logos/react.svg" alt="React logo" width="48"> | **`lucide-react`** | [![npm](https://img.shields.io/npm/v/lucide-react)](https://www.npmjs.com/package/lucide-react) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-react) | [Docs](https://lucide.dev/guide/react) · [Source](./packages/lucide-react) |
| <img src="https://lucide.dev/framework-logos/vue.svg" alt="Vue logo" width="48"> | **`@lucide/vue`** | [![npm](https://img.shields.io/npm/v/@lucide/vue)](https://www.npmjs.com/package/@lucide/vue) | ![NPM Downloads](https://img.shields.io/npm/dw/@lucide/vue) | [Docs](https://lucide.dev/guide/vue) · [Source](./packages/vue) |
| <img src="https://lucide.dev/framework-logos/svelte.svg" alt="Svelte logo" width="48"> | **`@lucide/svelte`** | [![npm](https://img.shields.io/npm/v/@lucide/svelte)](https://www.npmjs.com/package/@lucide/svelte) | ![NPM Downloads](https://img.shields.io/npm/dw/@lucide/svelte) | [Docs](https://lucide.dev/guide/svelte) · [Source](./packages/svelte) |
| <img src="https://lucide.dev/framework-logos/solid.svg" alt="Solid logo" width="48"> | **`lucide-solid`** | [![npm](https://img.shields.io/npm/v/lucide-solid)](https://www.npmjs.com/package/lucide-solid) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-solid) | [Docs](https://lucide.dev/guide/solid) · [Source](./packages/lucide-solid) |
| <img src="https://lucide.dev/framework-logos/preact.svg" alt="Preact logo" width="48"> | **`lucide-preact`** | [![npm](https://img.shields.io/npm/v/lucide-preact)](https://www.npmjs.com/package/lucide-preact) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-preact) | [Docs](https://lucide.dev/guide/preact) · [Source](./packages/lucide-preact) |
| <img src="https://lucide.dev/framework-logos/react-native.svg" alt="React Native logo" width="48"> | **`lucide-react-native`** | [![npm](https://img.shields.io/npm/v/lucide-react-native)](https://www.npmjs.com/package/lucide-react-native) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-react-native) | [Docs](https://lucide.dev/guide/react-native) · [Source](./packages/lucide-react-native) |
| <img src="https://lucide.dev/framework-logos/angular.svg" alt="Angular logo" width="48"> | **`@lucide/angular`** | [![npm](https://img.shields.io/npm/v/@lucide/angular)](https://www.npmjs.com/package/@lucide/angular) | ![NPM Downloads](https://img.shields.io/npm/dw/@lucide/angular) | [Docs](https://lucide.dev/guide/angular) · [Source](./packages/angular) |
| <img src="https://lucide.dev/framework-logos/astro.svg" alt="Astro logo" width="48"> | **`@lucide/astro`** | [![npm](https://img.shields.io/npm/v/@lucide/astro)](https://www.npmjs.com/package/@lucide/astro) | ![NPM Downloads](https://img.shields.io/npm/dw/@lucide/astro) | [Docs](https://lucide.dev/guide/astro) · [Source](./packages/astro) |
| <img src="https://lucide.dev/framework-logos/svg.svg" alt="SVG logo" width="48"> | **`lucide-static`** | [![npm](https://img.shields.io/npm/v/lucide-static)](https://www.npmjs.com/package/lucide-static) | ![NPM Downloads](https://img.shields.io/npm/dw/lucide-static) | [Docs](https://lucide.dev/guide/static) · [Source](./packages/lucide-static) |
### Figma
@@ -80,6 +80,8 @@ Thank you to all the people who contributed to Lucide!
<img src="https://opencollective.com/lucide-icons/contributors.svg?width=800" />
</a>
[//]: <> (Sponsors)
## Sponsors
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
@@ -88,7 +90,10 @@ 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)
### Hero backers 🦸
<a href="https://zephyr-cloud.io/"><img src="docs/public/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
### Awesome backers 🍺
<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>
+4 -6
View File
@@ -54,10 +54,8 @@
"jira": "Jira",
"kotlin": "Kotlin",
"kubernetes": "Kubernetes",
"less": "Less",
"leetcode": "LeetCode",
"leet-code": "LeetCode",
"line": "LINE",
"linkedin": "LinkedIn",
"lua": "Lua",
"mariadb": "MariaDB",
@@ -70,7 +68,7 @@
"nestjs": "NestJS",
"netflix": "Netflix",
"netlify": "Netlify",
"next": "Next.js",
"nextjs": "Next.js",
"nodejs": "Node.js",
"notion": "Notion",
"nostr": "Nostr",
@@ -106,7 +104,8 @@
"shopify": "Shopify",
"skype": "Skype",
"slack": "Slack",
"solid": "SolidJS",
"snapchat": "Snapchat",
"solidjs": "SolidJS",
"soundcloud": "SoundCloud",
"spotify": "Spotify",
"sqlite": "SQLite",
@@ -145,6 +144,5 @@
"xbox": "Xbox",
"yarn": "Yarn",
"youtube": "YouTube",
"zig": "Zig",
"zoom": "Zoom"
"zig": "Zig"
}
+1 -1
View File
@@ -1,5 +1,5 @@
{
"$schema": "../category.schema.json",
"title": "Navigation, Maps, and POIs",
"title": "Navigation & Places",
"icon": "compass"
}
@@ -11,7 +11,7 @@ export default eventHandler(async (event) => {
const name = params.data.split('/').at(-3);
const iconSizeString = params.data.split('/').at(-2);
const svgData = params.data.split('/').at(-1);
const iconSize = parseInt(iconSizeString, 10);
const iconSize = Math.min(parseInt(iconSizeString, 10) || imageSize, 256);
const data = svgData.slice(0, -4);
const prevSvg = iconNodes[name]
@@ -0,0 +1,25 @@
import { eventHandler, setResponseHeader } from 'h3';
import iconMetaData from '../../../data/lab/iconMetaData';
import iconPopularity from '../../../data/lab/iconPopularity';
import iconNodes from '../../../data/lab/iconNodes';
export default eventHandler((event) => {
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
return Object.fromEntries(
Object.entries(iconMetaData).map(([iconName, iconData]) => {
// Remove $schema from the response
delete iconData['$schema'];
return [
iconName,
{
name: iconName,
iconNode: iconNodes[iconName],
popularity: iconPopularity[iconName]?.count ?? 0,
...iconData,
},
];
}),
);
});
@@ -0,0 +1,14 @@
import { eventHandler, setResponseHeader } from 'h3';
import iconMetaData from '../../../data/lab/iconMetaData';
export default eventHandler((event) => {
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400');
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
for (const iconDetail in iconMetaData) {
// Remove $schema from the response
delete iconMetaData[iconDetail]['$schema'];
}
return iconMetaData;
});
@@ -0,0 +1,30 @@
import { eventHandler, getQuery, setResponseHeader } from 'h3';
import iconNodes from '../../../data/lab/iconNodes';
type IconNodeWithKeys = [elementName: string, attrs: Record<string, string> & { key?: string }][];
export default eventHandler((event) => {
const query = getQuery(event);
const withUniqueKeys = query.withUniqueKeys === 'true';
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400');
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
if (withUniqueKeys) {
return iconNodes;
}
return Object.entries(iconNodes).reduce((acc, [name, iconNode]) => {
if (withUniqueKeys) {
return [name, iconNode];
}
const newIconNode = (iconNode as IconNodeWithKeys).map(([name, { key, ...attrs }]) => {
return [name, attrs];
});
acc[name] = newIconNode;
return acc;
}, {});
});
+14 -195
View File
@@ -1,14 +1,14 @@
import { fileURLToPath, URL } from 'node:url';
import { defineConfig } from 'vitepress';
import { defineConfig, UserConfig } from 'vitepress';
import { groupIconMdPlugin, groupIconVitePlugin } from 'vitepress-plugin-group-icons';
import sidebar from './sidebar';
import snackPlayer from './markdown/snackPlayer';
import sandpackPlugin from './markdown/sandpack';
import { readFile } from 'node:fs/promises';
import { resourcesSidebar } from './sidebar/resources';
import getStructuredData from './getStructuredData';
import { createGeneralOGImage, createIconOGImage } from './createOGImage';
import llmstxt from 'vitepress-plugin-llms';
import { transformPageData } from './transformPageData';
import getHeadConfig from './getHeadConfig';
const defaultSandpackCSS = await readFile(
fileURLToPath(new URL('./theme/sandpack-default.css', import.meta.url)),
@@ -56,6 +56,12 @@ export default defineConfig({
new URL('./theme/components/overrides/VPFooter.vue', import.meta.url),
),
},
{
find: /^.*\/VPCarbonAds\.vue$/,
replacement: fileURLToPath(
new URL('./theme/components/overrides/VPCarbonAds.vue', import.meta.url),
),
},
{
find: '~/.vitepress',
replacement: fileURLToPath(new URL('./', import.meta.url)),
@@ -73,199 +79,11 @@ export default defineConfig({
'brand-logo-statement.md',
'icons/**', // Not working, need investigation
],
}),
}) as unknown as UserConfig['vite']['plugins'][0],
],
},
head: [
[
'link',
{
rel: 'preconnect',
href: 'https://analytics.lucide.dev',
},
],
[
'script',
{
src: 'https://analytics.lucide.dev/js/script.js',
'data-domain': 'lucide.dev',
defer: '',
},
],
[
'meta',
{
property: 'og:locale',
content: 'en_US',
},
],
[
'meta',
{
property: 'og:type',
content: 'website',
},
],
[
'meta',
{
property: 'og:site_name',
content: title,
},
],
[
'meta',
{
property: 'og:title',
content: socialTitle,
},
],
[
'meta',
{
property: 'og:description',
content: description,
},
],
[
'meta',
{
property: 'og:url',
content: 'https://lucide.dev',
},
],
[
'meta',
{
property: 'og:image',
content: 'https://lucide.dev/og.png',
},
],
[
'meta',
{
property: 'og:image:width',
content: '1200',
},
],
[
'meta',
{
property: 'og:image:height',
content: '630',
},
],
[
'meta',
{
property: 'og:image:type',
content: 'image/png',
},
],
[
'meta',
{
property: 'twitter:card',
content: 'summary_large_image',
},
],
[
'meta',
{
property: 'twitter:title',
content: socialTitle,
},
],
[
'meta',
{
property: 'twitter:description',
content: description,
},
],
[
'meta',
{
property: 'twitter:image',
content: 'https://lucide.dev/og.png',
},
],
],
async transformPageData(pageData) {
pageData.frontmatter.head ??= [];
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);
const ogPath = await createIconOGImage(iconName, pageData.params?.tags || []);
if (ogPath) {
const content = `https://lucide.dev${ogPath}`;
pageData.frontmatter.head.push(
[
'meta',
{
property: 'og:image',
content,
},
],
[
'meta',
{
property: 'twitter:image',
content,
},
],
);
}
pageData.frontmatter.head.push([
'script',
{ type: 'application/ld+json' },
JSON.stringify(structuredData),
]);
}
if (pageData.relativePath.startsWith('guide/')) {
const ogPath = await createGeneralOGImage(pageData);
if (ogPath) {
const content = `https://lucide.dev${ogPath}`;
pageData.frontmatter.head.push(
[
'meta',
{
property: 'og:image',
content,
},
],
[
'meta',
{
property: 'twitter:image',
content,
},
],
);
}
}
},
head: getHeadConfig({ title, description, socialTitle }),
transformPageData,
themeConfig: {
logo: {
light: '/logo.light.svg',
@@ -283,6 +101,7 @@ export default defineConfig({
},
{ text: 'Packages', link: '/packages' },
{ text: 'Showcase', link: '/showcase' },
{ text: 'Merch', link: 'https://merch.lucide.dev/' },
],
sidebar,
socialLinks: [
@@ -291,7 +110,7 @@ export default defineConfig({
],
footer: {
message: 'Released under the ISC License.',
copyright: `Copyright © ${new Date().getFullYear()} Lucide Contributors`,
copyright: `Copyright © ${new Date().getFullYear()} Lucide Icons`,
},
editLink: {
pattern: 'https://github.com/lucide-icons/lucide/edit/main/docs/:path',
+1 -1
View File
@@ -97,7 +97,7 @@
},
{
"name": "navigation",
"title": "Navigation, Maps, and POIs"
"title": "Navigation & Places"
},
{
"name": "notifications",
View File
+8 -24
View File
@@ -50,20 +50,21 @@
}
]
},
"lucide-svelte": {
"@lucide/svelte": {
"order": 3,
"icon": "svelte",
"docsAlias": "svelte",
"packageDirname": "svelte",
"shields": [
{
"alt": "npm",
"src": "https://img.shields.io/npm/v/lucide-svelte",
"href": "https://www.npmjs.com/package/lucide-svelte"
"src": "https://img.shields.io/npm/v/@lucide/svelte",
"href": "https://www.npmjs.com/package/@lucide/svelte"
},
{
"alt": "npm",
"src": "https://img.shields.io/npm/dw/lucide-svelte",
"href": "https://www.npmjs.com/package/lucide-svelte"
"src": "https://img.shields.io/npm/dw/@lucide/svelte",
"href": "https://www.npmjs.com/package/@lucide/svelte"
}
]
},
@@ -105,6 +106,7 @@
"order": 6,
"icon": "angular",
"docsAlias": "angular",
"packageDirname": "angular",
"shields": [
{
"alt": "npm",
@@ -118,24 +120,6 @@
}
]
},
"lucide-angular": {
"order": 7,
"icon": "angular-old",
"description": "Our legacy Angular package with a module based API.",
"documentation": "https://v0.lucide.dev/guide/packages/lucide-angular",
"shields": [
{
"alt": "npm",
"src": "https://img.shields.io/npm/v/lucide-angular",
"href": "https://www.npmjs.com/package/lucide-angular"
},
{
"alt": "npm",
"src": "https://img.shields.io/npm/dw/lucide-angular",
"href": "https://www.npmjs.com/package/lucide-angular"
}
]
},
"lucide-preact": {
"order": 8,
"icon": "preact",
@@ -208,4 +192,4 @@
}
]
}
}
}
@@ -209,5 +209,24 @@
],
"source": "https://github.com/shx08/strapi-lucide-icons",
"documentation": "https://github.com/shx08/strapi-lucide-icons/blob/main/README.md"
},
{
"name": "lucide-lit",
"description": "Implementation of Lucide icons as Lit web components.",
"icon": "/framework-logos/lit.svg",
"shields": [
{
"alt": "Latest Stable Version",
"src": "https://img.shields.io/npm/v/@gyeonghokim/lucide-lit",
"href": "https://www.npmjs.com/package/@gyeonghokim/lucide-lit"
},
{
"alt": "Total Downloads",
"src": "https://img.shields.io/npm/dw/@gyeonghokim/lucide-lit",
"href": "https://www.npmjs.com/package/@gyeonghokim/lucide-lit"
}
],
"source": "https://github.com/GyeongHoKim/lucide-lit",
"documentation": "https://github.com/GyeongHoKim/lucide-lit/blob/main/README.md"
}
]
+127
View File
@@ -0,0 +1,127 @@
import { HeadConfig } from 'vitepress';
const getHeadConfig = ({
title,
description,
socialTitle,
}: {
title: string;
description: string;
socialTitle?: string;
}): HeadConfig[] => [
[
'link',
{
rel: 'preconnect',
href: 'https://analytics.lucide.dev',
},
],
[
'script',
{
src: 'https://analytics.lucide.dev/js/script.js',
'data-domain': 'lucide.dev',
defer: '',
},
],
[
'meta',
{
property: 'og:locale',
content: 'en_US',
},
],
[
'meta',
{
property: 'og:type',
content: 'website',
},
],
[
'meta',
{
property: 'og:site_name',
content: title,
},
],
[
'meta',
{
property: 'og:title',
content: socialTitle,
},
],
[
'meta',
{
property: 'og:description',
content: description,
},
],
[
'meta',
{
property: 'og:url',
content: 'https://lucide.dev',
},
],
[
'meta',
{
property: 'og:image',
content: 'https://lucide.dev/og.png',
},
],
[
'meta',
{
property: 'og:image:width',
content: '1200',
},
],
[
'meta',
{
property: 'og:image:height',
content: '630',
},
],
[
'meta',
{
property: 'og:image:type',
content: 'image/png',
},
],
[
'meta',
{
property: 'twitter:card',
content: 'summary_large_image',
},
],
[
'meta',
{
property: 'twitter:title',
content: socialTitle,
},
],
[
'meta',
{
property: 'twitter:description',
content: description,
},
],
[
'meta',
{
property: 'twitter:image',
content: 'https://lucide.dev/og.png',
},
],
];
export default getHeadConfig;
+14 -1
View File
@@ -459,7 +459,20 @@ const SvgPreview = (
/>
<ColoredPath
paths={paths}
colors={['#dfdfd6']}
colors={[
'#1982c4',
'#4267AC',
'#6a4c93',
'#B55379',
'#FF595E',
'#FF7655',
'#ff924c',
'#FFAE43',
'#ffca3a',
'#C5CA30',
'#8ac926',
'#52A675',
]}
/>
<Radii
paths={paths}
+5
View File
@@ -72,6 +72,11 @@ export const reactNativeSidebar = [
link: '/guide/react-native/advanced/combining-icons',
desc: 'Combine multiple icons into one',
},
{
text: 'Optimizations',
link: '/guide/react-native/advanced/optimizations',
desc: 'Optimizing your app for performance',
},
],
},
{
@@ -0,0 +1,160 @@
<script setup lang="ts">
import { useLocalStorage } from '@vueuse/core';
import IconButton from './base/IconButton.vue';
import { x } from '../../data/iconNodes';
import Icon from '@lucide/vue/src/Icon';
import { computed, onMounted, ref } from 'vue';
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
const showAskSurvey = useLocalStorage('show-ask-overlay', true, {
initOnMounted: true,
});
const delayedShow = ref(false)
const showPopup = computed(() => showAskSurvey.value && delayedShow.value );
let isInitialized = false
function startTally() {
window.Tally.openPopup('EkvOpB', {
layout: 'modal',
width: 700,
autoClose: 5000,
onClose() {
showAskSurvey.value = false;
},
onSubmit() {
showAskSurvey.value = false;
},
});
}
onMounted(() => {
setTimeout(() => {
delayedShow.value = true
}, 10000)
})
function initTally() {
try {
if (!isInitialized) {
isInitialized = true
const s = document.createElement('script')
s.src = `//tally.so/widgets/embed.js`
s.async = true
s.onload = startTally
document.body.appendChild(s)
} else {
startTally();
}
} catch (error) {
window.open('https://tally.so/r/EkvOpB', '_blank');
}
}
function hidePopup() {
showAskSurvey.value = false;
}
</script>
<template>
<Teleport to="body">
<div
:class="{
'show-popup': showPopup,
}"
class="ask-overlay"
>
<IconButton
@click="hidePopup"
class="hide-button"
>
<Icon
:iconNode="x"
:size="20"
absoluteStrokeWidth
/>
</IconButton>
<h2 class="title">
We value your feedback!
</h2>
<p class="description">
Can you spare a moment to take our survey? <br>Your feedback helps us improve Lucide and make it better for everyone.
</p>
<div class="buttons">
<VPButton
text="Take the Survey"
theme="brand"
@click="initTally"
/>
<VPButton
text="Close"
theme="alt"
@click="hidePopup"
/>
</div>
</div>
</Teleport>
</template>
<style scoped>
.ask-overlay {
position: fixed;
z-index: 99;;
bottom: 24px;
width: calc(100% - 48px);
max-width: 420px;
left: 24px;
transition:
opacity 0.25s,
transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
padding: 20px;
border-radius: 12px;
box-shadow: var(--vp-shadow-4);
background-color: var(--vp-carbon-ads-bg-color);
opacity: 0;
transform: translateY(200px);
}
.ask-overlay .title {
line-height: 24px;
font-size: 16px;
font-weight: 600;
}
.ask-overlay .description {
padding-top: 8px;
line-height: 24px;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-text-2);
}
.ask-overlay.show-popup {
transform: translateY(0);
opacity: 1;
pointer-events: auto;
transition:
opacity 0.5s,
transform 0.25s ease;
}
.ask-overlay .buttons {
margin-top: 16px;
display: flex;
gap: 16px;
}
.hide-button {
padding: 4px;
position: absolute;
top: 8px;
right: 8px;
z-index: 3;
background-color: transparent;
}
</style>
@@ -11,6 +11,14 @@ const { isDark } = useData();
const emit = defineEmits(['update:modelValue']);
function limitHexInput(val: string) {
if (val.startsWith('#')) {
return val.slice(0, 9);
}
return val.slice(0, 8);
}
const value = computed({
get: () => {
if (props.modelValue == null || props.modelValue === 'currentColor') {
@@ -19,7 +27,7 @@ const value = computed({
return props.modelValue;
},
set: (val) => emit('update:modelValue', val),
set: (val) => emit('update:modelValue', limitHexInput(val)),
});
</script>
@@ -41,6 +49,7 @@ const value = computed({
class="color-input-text"
aria-label="Color picker input"
v-model="value"
maxlength="9"
placeholder="[default]"
/>
</div>
@@ -91,6 +100,7 @@ const value = computed({
background: transparent;
color: var(--vp-c-text-1);
font-size: 13px;
font-family: var(--vp-font-family-mono);
text-align: left;
border-radius: 8px;
cursor: text;
@@ -1,15 +1,22 @@
<script setup lang="ts">
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue';
import Icon from '@lucide/vue/src/Icon';
import RocketDuotoneIcon from '../home/RocketDuotoneIcon.ts';
</script>
<template>
<div class="top-notification">
<p>
<Icon
:iconNode="RocketDuotoneIcon"
size="18"
class="rocket-icon"
/>
<VPLink
class="notification-link"
href="/guide/version-1"
>Lucide v1 is out!</VPLink
>🚀<br />
>
You're looking at the site for v1, for v0 go to
<VPLink
class="notification-link"
@@ -21,11 +28,7 @@ import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue';
</template>
<style>
:root {
--vp-layout-top-height: 64px;
}
@media (min-width: 640px) {
@media (min-width: 960px) {
:root {
--vp-layout-top-height: 32px;
}
@@ -34,19 +37,19 @@ import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue';
<style scoped>
.top-notification {
position: fixed;
position: sticky;
top: 0;
left: 0;
width: 100%;
z-index: 9999;
display: flex;
height: var(--vp-layout-top-height);
justify-content: center;
align-items: center;
background: var(--vp-c-brand-dark);
color: var(--vp-c-bg-alt-down);
font-size: 14px;
padding: 0 16px;
padding: 4px 16px;
text-wrap: balance;
}
.notification-link {
@@ -58,9 +61,9 @@ import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue';
display: none !important;
}
@media (min-width: 640px) {
.top-notification br {
display: none;
}
.rocket-icon {
display: inline-block;
vertical-align: middle;
margin-right: 4px;
}
</style>
@@ -6,10 +6,10 @@ import SelectIcon from './SelectIcon.vue';
defineProps<{
id?: string;
items?: { name: string; route: string; icon: string; iconDark?: string }[];
items?: { name: string; value: string; icon?: string; iconDark?: string }[];
}>();
const selected = defineModel<{ name: string; icon: string; iconDark?: string }>();
const selected = defineModel<{ name: string; value: string; icon?: string; iconDark?: string }>();
</script>
<template>
@@ -19,14 +19,18 @@ const selected = defineModel<{ name: string; icon: string; iconDark?: string }>(
class="select-button"
:id="id"
>
<SelectIcon :item="selected" />
<slot name="start-icon">
<SelectIcon v-if="selected.icon" :item="selected" />
</slot>
<span class="select-text">{{ selected.name }}</span>
<span class="select-icon">
<Icon
:iconNode="chevronsUpDown"
class="chevron-icon"
aria-hidden="true"
/>
<slot name="end-icon">
<Icon
:iconNode="chevronsUpDown"
class="chevron-icon"
aria-hidden="true"
/>
</slot>
</span>
</ListboxButton>
@@ -43,8 +47,9 @@ const selected = defineModel<{ name: string; icon: string; iconDark?: string }>(
:value="item"
as="template"
>
<li :class="['select-option', { active, selected }]">
<SelectIcon :item="item" />
<SelectIcon v-if="item.icon" :item="item" />
<span :class="['option-text', { selected }]">{{ item.name }}</span>
<span
v-if="selected"
@@ -2,25 +2,28 @@
const { item } = defineProps<{
item: {
name: string;
icon: string;
icon?: string;
iconDark?: string;
};
}>();
</script>
<template>
<img
:src="item.icon"
:class="{ 'select-item-icon': true, light: item.iconDark }"
:alt="`${item.name} logo`"
loading="lazy"
/>
<img
v-if="item.iconDark"
:src="item.iconDark"
:alt="`${item.name} logo`"
class="select-item-icon dark"
/>
<div v-if="item.icon || item.iconDark">
<img
v-if="item.icon"
:src="item.icon"
:class="{ 'select-item-icon': true, light: item.iconDark }"
:alt="`${item.name} logo`"
loading="lazy"
/>
<img
v-if="item.iconDark"
:src="item.iconDark"
:alt="`${item.name} logo`"
class="select-item-icon dark"
/>
</div>
</template>
<style scoped>
@@ -11,49 +11,49 @@ const { page } = useData();
const router = useRouter();
const frameworks = [
{ name: 'Vanilla', icon: '/framework-logos/js.svg', route: '/guide/lucide/' },
{ name: 'React', icon: '/framework-logos/react.svg', route: '/guide/react/' },
{ name: 'Vue', icon: '/framework-logos/vue.svg', route: '/guide/vue/' },
{ name: 'Svelte', icon: '/framework-logos/svelte.svg', route: '/guide/svelte/' },
{ name: 'Solid', icon: '/framework-logos/solid.svg', route: '/guide/solid/' },
{ name: 'Angular', icon: '/framework-logos/angular.svg', route: '/guide/angular/' },
{ name: 'Preact', icon: '/framework-logos/preact.svg', route: '/guide/preact/' },
{ name: 'Vanilla', icon: '/framework-logos/js.svg', value: '/guide/lucide/' },
{ name: 'React', icon: '/framework-logos/react.svg', value: '/guide/react/' },
{ name: 'Vue', icon: '/framework-logos/vue.svg', value: '/guide/vue/' },
{ name: 'Svelte', icon: '/framework-logos/svelte.svg', value: '/guide/svelte/' },
{ name: 'Solid', icon: '/framework-logos/solid.svg', value: '/guide/solid/' },
{ name: 'Angular', icon: '/framework-logos/angular.svg', value: '/guide/angular/' },
{ name: 'Preact', icon: '/framework-logos/preact.svg', value: '/guide/preact/' },
{
name: 'React Native',
icon: '/framework-logos/react-native.svg',
route: '/guide/react-native/',
value: '/guide/react-native/',
},
{
name: 'Astro',
icon: '/framework-logos/astro.svg',
iconDark: '/framework-logos/astro-dark.svg',
route: '/guide/astro/',
value: '/guide/astro/',
},
{ name: 'Static', icon: '/framework-logos/svg.svg', route: '/guide/static/' },
{ name: 'Static', icon: '/framework-logos/svg.svg', value: '/guide/static/' },
];
const fallbackFramework = useLocalStorage('lucide-docs-fallback-framework', frameworks[1]);
const selected = computed(() => {
const current = frameworks.find(({ route }) => {
const current = frameworks.find(({ value }) => {
if (router.route.path?.startsWith?.('/guide')) {
const [, , framework] = router.route.path.split('/');
const [, frameWorkRoute] = route.split('/').filter(Boolean);
const [, frameWorkRoute] = value.split('/').filter(Boolean);
return framework === frameWorkRoute;
}
return router.route.path.split('/').slice(0, 3).join('/') === route;
return router.route.path.split('/').slice(0, 3).join('/') === value;
});
return current || fallbackFramework.value;
return current || (fallbackFramework.value?.value ? fallbackFramework.value : frameworks[0]);
});
function onSelectFramework(item: { name: string; icon: string; iconDark?: string; route: string }) {
function onSelectFramework(item: { name: string; icon: string; iconDark?: string; value: string }) {
fallbackFramework.value = item;
if (item.route !== router.route.path) {
const likeRoute = router.route.path.replace(selected.value.route, item.route);
if (item.value !== router.route.path) {
const likeRoute = router.route.path.replace(selected.value.value, item.value);
const hasRoute = sidebar[item.route]?.some((section) =>
const hasRoute = sidebar[item.value]?.some((section) =>
section?.items?.some(({ link }) => link === likeRoute),
);
@@ -62,7 +62,7 @@ function onSelectFramework(item: { name: string; icon: string; iconDark?: string
return;
}
router.go(item.route);
router.go(item.value);
}
}
</script>
@@ -85,12 +85,12 @@ function onSelectFramework(item: { name: string; icon: string; iconDark?: string
/>
</div>
<VPSidebarGroup
:key="selected.route"
:key="selected.value"
v-if="
page?.relativePath?.startsWith?.('guide') &&
!page?.relativePath?.startsWith?.(selected.route.substring(1))
!page?.relativePath?.startsWith?.(selected.value.substring(1))
"
:items="sidebar[selected.route]"
:items="sidebar[selected.value]"
/>
</template>
@@ -118,5 +118,15 @@ label {
font-weight: bold;
margin-bottom: 4px;
display: block;
position: relative;
}
.framework-select:before {
content: ' ';
position: absolute;
inset: 0 -16px -24px;
background: color-mix(in srgb, var(--vp-c-bg-alt), transparent 50%);
backdrop-filter: blur(4px);
mask-image: linear-gradient(to bottom, black calc(100% - 16px), transparent 100%);
}
</style>
@@ -3,25 +3,7 @@ import Badge from '../base/Badge.vue';
import { moveRight } from '../../../data/iconNodes';
import Icon from '@lucide/vue/src/Icon';
import { data } from './HomeHeroInfoBefore.data';
const rocketDuoTone = [
[
'path',
{
d: 'M8 18a2 2 0 0 0-2-2c-2.53-.078-3.247 3.605-3.5 5.5 1.895-.253 5.578-.97 5.5-3.5',
fill: 'currentColor',
opacity: 0.5,
},
],
[
'path',
{
d: 'M22 2c0 2.72-.78 7.5-6 11 0 0 1.08 3.38 0 5-.969 1.448-4 2-4 2v-5l-3-3H4s.553-3.033 2-4c1.616-1.077 4.982.043 5 .05A12.88 12.88 0 0 1 22 2m-6 3a3 3 0 1 0 0 6 3 3 0 0 0 0-6',
fill: 'currentColor',
'fill-rule': 'evenodd',
'clip-rule': 'evenodd',
},
],
] as const;
import RocketDuotoneIcon from './RocketDuotoneIcon.ts';
</script>
<template>
@@ -33,7 +15,7 @@ const rocketDuoTone = [
class="badge-special confetti-button animate"
href="/guide/version-1"
>
<Icon :iconNode="rocketDuoTone" />
<Icon :iconNode="RocketDuotoneIcon" />
Version 1
<Icon
:iconNode="moveRight"
@@ -13,23 +13,21 @@ const { go } = useRouter()
<HomeSectionTitle>Available For:</HomeSectionTitle>
<div class="packages-list">
<a
v-for="{ name, logo, logoDark } in data.packages"
:href="`/guide/packages/${name}`"
v-for="{ name, label, path, logo, logoDark } in data.packages"
:href="path"
class="package-logo"
:aria-label="`Read more about: ${name} package`"
@click.prevent="go(`/guide/packages/${name}`)"
@click.prevent="go(path)"
>
<img
:src="logo"
:class="{ light: logoDark, 'image-logo': true }"
:alt="`${name} logo`"
:alt="label"
loading="lazy"
/>
<img
v-if="logoDark"
:src="logoDark"
:alt="`${name} logo`"
:alt="label"
class="image-logo dark"
loading="lazy"
/>
@@ -0,0 +1,21 @@
const RocketDuotoneIcon = [
[
'path',
{
d: 'M8 18a2 2 0 0 0-2-2c-2.53-.078-3.247 3.605-3.5 5.5 1.895-.253 5.578-.97 5.5-3.5',
fill: 'currentColor',
opacity: 0.5,
},
],
[
'path',
{
d: 'M22 2c0 2.72-.78 7.5-6 11 0 0 1.08 3.38 0 5-.969 1.448-4 2-4 2v-5l-3-3H4s.553-3.033 2-4c1.616-1.077 4.982.043 5 .05A12.88 12.88 0 0 1 22 2m-6 3a3 3 0 1 0 0 6 3 3 0 0 0 0-6',
fill: 'currentColor',
'fill-rule': 'evenodd',
'clip-rule': 'evenodd',
},
],
] as const;
export default RocketDuotoneIcon;
@@ -5,11 +5,18 @@ import IconButton from '../base/IconButton.vue';
import VPDocAsideCarbonAds from 'vitepress/dist/client/theme-default/components/VPDocAsideCarbonAds.vue';
import { x } from '../../../data/iconNodes';
import Icon from '@lucide/vue/src/Icon';
import { onMounted, ref } from 'vue';
import { computed, onMounted, ref } from 'vue';
const { theme } = useData();
const showAd = useSessionStorage('show-carbon-ads', true);
const showAd = useSessionStorage('show-carbon-ads', true, {
initOnMounted: true,
});
const carbonLoaded = ref(true);
const shouldHideAd = computed(() => !showAd.value || !carbonLoaded.value);
function hideAd() {
showAd.value = false;
}
defineProps<{
drawerOpen: boolean;
@@ -28,13 +35,13 @@ onMounted(() => {
<div
:class="{
'drawer-open': drawerOpen,
'hide-ad': !(showAd && carbonLoaded),
'hide-ad': shouldHideAd,
}"
class="floating-ad"
v-if="theme.carbonAds"
>
<IconButton
@click="showAd = false"
@click="hideAd"
class="hide-button"
>
<Icon
@@ -43,7 +50,7 @@ onMounted(() => {
absoluteStrokeWidth
/>
</IconButton>
<VPDocAsideCarbonAds :carbon-ads="theme.carbonAds" />
<VPDocAsideCarbonAds :carbon-ads="theme.carbonAds" overlay />
</div>
</template>
@@ -66,6 +73,7 @@ onMounted(() => {
.floating-ad.hide-ad {
transform: translateX(224px);
opacity: 0;
pointer-events: none;
}
.floating-ad.drawer-open.hide-ad {
@@ -96,6 +104,7 @@ onMounted(() => {
position: absolute;
top: 8px;
right: 8px;
z-index: 3;
background-color: transparent;
}
</style>
@@ -7,10 +7,14 @@ import { useActiveAnchor } from '../../composables/useActiveAnchor'
import { data } from './CategoryList.data'
import CategoryListItem from './CategoryListItem.vue'
import SidebarTitle from './SidebarTitle.vue'
import { useCategoryView } from '../../composables/useCategoryView'
import { useCategoryViewSync } from '../../composables/useCategoryView'
const { page } = useData()
const { categoryCounts } = useCategoryView();
const { categoryCounts, selectedCategory } = useCategoryViewSync();
function onCategoriesClick() {
selectedCategory.value = '';
}
const categoriesIsActive = computed(() => {
return isActive(page.value.relativePath, '/icons/categories');
@@ -53,7 +57,7 @@ watch(headers, () => {
<VPLink class="sidebar-link sidebar-text" href="/icons/" :class="{ 'active': overviewIsActive } ">
All
</VPLink>
<VPLink class="sidebar-link sidebar-text" href="/icons/categories" :class="{ 'active': categoriesIsActive } ">
<VPLink class="sidebar-link sidebar-text" href="/icons/categories" :class="{ 'active': categoriesIsActive }" @click="onCategoriesClick">
Categories
</VPLink>
<div class="content">
@@ -28,7 +28,10 @@ function onClick(categoryName: string) {
const heading = document.querySelector<HTMLAnchorElement>(categoryName);
heading?.focus();
window.history.pushState({}, '', `/icons/categories#${categoryName}`)
const url = new URL(window.location.href);
url.pathname = '/icons/categories';
url.hash = categoryName;
window.history.pushState({}, '', url);
}
</script>
@@ -85,6 +88,7 @@ function onClick(categoryName: string) {
.outline-link.inactive {
color: var(--vp-c-text-4);
pointer-events: none;
}
.outline-link.nested {
@@ -188,7 +188,7 @@ const deprecatedTitle = computed(() => {
-ms-overflow-style: none;
scrollbar-width: none;
scrollbar-width: thin; /* can also be normal, or none, to not render scrollbar */
scrollbar-color: currentColor transparent; /* foreground background */
scrollbar-color: var(--vp-c-text-4) transparent; /* foreground background */
}
.horizontal-scroller::-webkit-scrollbar {
width: 0;
@@ -3,6 +3,7 @@ import type { IconEntity } from '../../types';
import { computed, ref } from 'vue';
import createLucideIcon from '@lucide/vue/src/createLucideIcon';
import { useIconStyleContext } from '../../composables/useIconStyle';
import { squarePen } from '../../../data/iconNodes';
const props = defineProps<{
name: IconEntity['name'];
@@ -19,6 +20,31 @@ const iconComponent = computed(() => {
if (!props.name || !props.iconNode) return null;
return createLucideIcon(props.name, props.iconNode);
});
const SquarePenIcon = createLucideIcon('SquarePen', squarePen);
const innerSvg = computed(() => {
if (!props.iconNode) return '';
const string = props.iconNode
.map(([tag, attrs]) => {
const attributes = Object.entries(attrs)
.map(([key, value]) => `${key}="${value}"`)
.join(' ');
return `<${tag} ${attributes}/>`;
})
.join('');
return string
.replace(/>[\r\n ]+</g, '><')
.replace(/(<.*?>)|\s+/g, (m, $1) => $1 || ' ')
.trim();
});
const base64InnerSvg = computed(() => {
if (typeof window === 'undefined') return '';
return btoa(innerSvg.value);
});
</script>
<template>
@@ -57,6 +83,16 @@ const iconComponent = computed(() => {
/>
</g>
</svg>
<a
:href="`https://studio.lucide.dev/edit?value=${encodeURIComponent(base64InnerSvg)}&name=${name}&utm_source=lucide.dev&utm_medium=icon-detail-preview`"
target="_blank"
rel="noopener noreferrer"
class="studio-button"
title="Open in Lucide Studio"
aria-label="Open in Lucide Studio"
>
<SquarePenIcon :size="14" />
</a>
</div>
</template>
@@ -75,6 +111,8 @@ const iconComponent = computed(() => {
position: relative;
background: var(--vp-c-bg-alt);
border-radius: 8px;
overflow: hidden;
flex-shrink: 0;
}
.icon-container > :deep(svg:not(.icon-grid)) {
width: 100%;
@@ -85,6 +123,34 @@ const iconComponent = computed(() => {
opacity: 0.8;
}
.studio-button {
position: absolute;
bottom: 8px;
right: 8px;
background: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
padding: 5px;
display: flex;
align-items: center;
justify-content: center;
color: var(--vp-c-text-2);
opacity: 0;
transition: opacity 0.2s, color 0.2s, background-color 0.2s;
z-index: 2;
}
.icon-container:hover .studio-button,
.studio-button:focus-visible {
opacity: 1;
}
.studio-button:hover,
.studio-button:focus-visible {
background: var(--vp-c-bg-soft);
color: var(--vp-c-text-1);
}
.icon-component.customizable {
will-change: width, height, stroke-width, stroke;
/* color: var(--customize-color, currentColor);
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, computed, defineAsyncComponent, onMounted } from 'vue';
import { ref, computed, watch, defineAsyncComponent, onMounted } from 'vue';
import type { IconEntity, Category } from '../../types';
import useSearch from '../../composables/useSearch';
import InputSearch from '../base/InputSearch.vue';
@@ -12,6 +12,7 @@ import useFetchCategories from '../../composables/useFetchCategories';
import { useElementSize, useEventListener, useVirtualList } from '@vueuse/core';
import chunkArray from '../../utils/chunkArray';
import useScrollToCategory from '../../composables/useScrollToCategory';
import { useCategoryView } from '../../composables/useCategoryView';
import CarbonAdOverlay from './CarbonAdOverlay.vue';
import useSearchPlaceholder from '../../utils/useSearchPlaceholder.ts';
@@ -26,8 +27,15 @@ const props = defineProps<{
const activeIconName = ref(null);
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
const { selectedCategory } = useCategoryView();
const isSearching = computed(() => !!searchQuery.value);
watch(searchQueryDebounced, (searchString) => {
if (searchString !== '') {
selectedCategory.value = '';
}
});
const { shortcutText: kbdSearchShortcut } = useSearchShortcut(() => {
searchInput.value?.focus();
});
@@ -36,8 +44,12 @@ function setActiveIconName(name: string) {
activeIconName.value = name;
}
const { execute: fetchTags, data: tags } = useFetchTags();
const { execute: fetchCategories, data: categoriesMap } = useFetchCategories();
const { execute: fetchTags, data: tags, isFetching: isFetchingTags } = useFetchTags();
const {
execute: fetchCategories,
data: categoriesMap,
isFetching: isFetchingCategories,
} = useFetchCategories();
const overviewEl = ref<HTMLElement | null>(null);
const { width: containerWidth } = useElementSize(overviewEl);
@@ -109,6 +121,9 @@ const categoriesList = computed(() => {
}, []);
});
const searchPlaceholder = useSearchPlaceholder(searchQuery, searchResults);
const isSearchMetadataLoading = computed(
() => searchQuery.value.length > 0 && (tags.value == null || categoriesMap.value == null),
);
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(categoriesList, {
itemHeight: ICON_SIZE + ICON_GRID_GAP,
@@ -127,22 +142,39 @@ onMounted(() => {
useEventListener(window, 'scroll', containerProps.onScroll);
});
function onFocusSearchInput() {
if (tags.value == null) {
fetchTags();
function loadSearchMetadata() {
if (tags.value == null && !isFetchingTags.value) {
void fetchTags();
}
if (categoriesMap.value == null) {
fetchCategories();
if (categoriesMap.value == null && !isFetchingCategories.value) {
void fetchCategories();
}
}
watch(searchQuery, (searchString) => {
if (searchString !== '') {
loadSearchMetadata();
}
});
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
function handleCloseDrawer() {
setActiveIconName('');
window.history.pushState({}, '', '/icons/categories');
const url = new URL(window.location);
url.pathname = '/icons/categories';
if (searchQueryDebounced.value) {
url.searchParams.set('search', searchQueryDebounced.value);
}
if (selectedCategory.value) {
url.hash = selectedCategory.value;
}
window.history.pushState({}, '', url);
}
</script>
@@ -150,6 +182,7 @@ function handleCloseDrawer() {
<div
ref="overviewEl"
class="overview-container"
:class="{ 'icon-drawer-open': activeIconName }"
>
<StickyBar class="category-search">
<InputSearch
@@ -158,11 +191,11 @@ function handleCloseDrawer() {
:shortcut="kbdSearchShortcut"
class="input-wrapper"
ref="searchInput"
@focus="onFocusSearchInput"
@focus="loadSearchMetadata"
/>
</StickyBar>
<NoResults
v-if="searchPlaceholder.isNoResults"
v-if="searchPlaceholder.isNoResults && !isSearchMetadataLoading"
:searchQuery="searchPlaceholder.query"
:isBrandSearch="searchPlaceholder.isBrand"
@clear="searchQuery = ''"
@@ -4,6 +4,7 @@ import type { IconEntity } from '../../types';
import { useElementSize, useEventListener, useVirtualList } from '@vueuse/core';
import { useRoute } from 'vitepress';
import IconGrid from './IconGrid.vue';
import Select from '../base/Select.vue';
import InputSearch from '../base/InputSearch.vue';
import useSearch from '../../composables/useSearch';
import useSearchInput from '../../composables/useSearchInput';
@@ -14,9 +15,26 @@ import useFetchCategories from '../../composables/useFetchCategories';
import chunkArray from '../../utils/chunkArray';
import CarbonAdOverlay from './CarbonAdOverlay.vue';
import useSearchPlaceholder from '../../utils/useSearchPlaceholder.ts';
import Icon from '@lucide/vue/src/Icon';
import { listSortDescending } from '~/.vitepress/data/iconNodes';
const ICON_SIZE = 56;
const ICON_GRID_GAP = 8;
const SORTING = [
{
name: 'Popularity',
value: 'popularity',
},
{
name: 'Release date',
value: 'release-date',
},
{
name: 'Name',
value: 'name',
},
]
const initialGridItems = computed(() => {
if (containerWidth.value === 0) return 120;
@@ -32,9 +50,14 @@ const props = defineProps<{
}>();
const activeIconName = ref(null);
const selectedSort = ref(SORTING[0])
const { execute: fetchTags, data: tags } = useFetchTags();
const { execute: fetchCategories, data: categories } = useFetchCategories();
const { execute: fetchTags, data: tags, isFetching: isFetchingTags } = useFetchTags();
const {
execute: fetchCategories,
data: categories,
isFetching: isFetchingCategories,
} = useFetchCategories();
const overviewEl = ref<HTMLElement | null>(null);
const { width: containerWidth } = useElementSize(overviewEl);
@@ -43,12 +66,29 @@ const columnSize = computed(() => {
return Math.floor(containerWidth.value / (ICON_SIZE + ICON_GRID_GAP));
});
const sortedIcons = computed(() => {
switch (selectedSort.value.value) {
case 'popularity':
return [...props.icons].sort((a, b) => (b.popularity || 0) - (a.popularity || 0));
case 'release-date':
return [...props.icons].sort((a, b) => {
const aDate = a.createdRelease?.date ? new Date(a.createdRelease.date).getTime() : 0;
const bDate = b.createdRelease?.date ? new Date(b.createdRelease.date).getTime() : 0;
return bDate - aDate;
});
case 'name':
return [...props.icons].sort((a, b) => a.name.localeCompare(b.name));
default:
return props.icons;
}
});
const mappedIcons = computed(() => {
if (tags.value == null) {
return props.icons;
return sortedIcons.value;
}
return props.icons.map((icon) => {
return sortedIcons.value.map((icon) => {
const iconTags = tags.value[icon.name];
const iconCategories = categories.value?.[icon.name] ?? [];
@@ -68,11 +108,15 @@ const { shortcutText: kbdSearchShortcut } = useSearchShortcut(() => {
const searchResults = useSearch(searchQueryDebounced, mappedIcons, [
{ name: 'name', weight: 3 },
{ name: 'aliases', weight: 3 },
{ name: 'aliases', weight: 8 },
{ name: 'tags', weight: 2 },
{ name: 'categories', weight: 1 },
]);
const searchPlaceholder = useSearchPlaceholder(searchQuery, searchResults);
const isSearchMetadataLoading = computed(
() => searchQuery.value.length > 0 && (tags.value == null || categories.value == null),
);
const chunkedIcons = computed(() => {
return chunkArray(searchResults.value, columnSize.value);
@@ -98,15 +142,21 @@ function setActiveIconName(name: string) {
activeIconName.value = name;
}
function onFocusSearchInput() {
if (tags.value == null) {
fetchTags();
function loadSearchMetadata() {
if (tags.value == null && !isFetchingTags.value) {
void fetchTags();
}
if (categories.value == null) {
fetchCategories();
if (categories.value == null && !isFetchingCategories.value) {
void fetchCategories();
}
}
watch(searchQuery, (searchString) => {
if (searchString !== '') {
loadSearchMetadata();
}
});
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
@@ -118,7 +168,14 @@ watch(searchQueryDebounced, () => {
function handleCloseDrawer() {
setActiveIconName('');
window.history.pushState({}, '', '/icons/');
const url = new URL(window.location);
url.pathname = '/icons/';
if (searchQueryDebounced.value) {
url.searchParams.set('search', searchQueryDebounced.value);
}
window.history.pushState({}, '', url);
}
</script>
@@ -126,6 +183,7 @@ function handleCloseDrawer() {
<div
ref="overviewEl"
class="overview-container"
:class="{ 'icon-drawer-open': activeIconName }"
>
<StickyBar>
<InputSearch
@@ -134,11 +192,25 @@ function handleCloseDrawer() {
ref="searchInput"
:shortcut="kbdSearchShortcut"
class="input-wrapper"
@focus="onFocusSearchInput"
@focus="loadSearchMetadata"
/>
<Select
id="sort-select"
:items="SORTING"
v-model="selectedSort"
>
<template #start-icon>
<Icon
:iconNode="listSortDescending"
class="chevron-icon"
aria-hidden="true"
/>
</template>
</Select>
</StickyBar>
<NoResults
v-if="searchPlaceholder.isNoResults"
v-if="searchPlaceholder.isNoResults && !isSearchMetadataLoading"
:searchQuery="searchPlaceholder.query"
:isBrandSearch="searchPlaceholder.isBrand"
@clear="searchQuery = ''"
@@ -73,13 +73,11 @@ const customizingActive = computed(() => {
id="icon-color"
label="Color"
>
<template #display>
<ColorPicker
v-model="color"
id="icon-color"
class="color-picker"
/>
</template>
<ColorPicker
v-model="color"
id="icon-color"
class="color-picker"
/>
</InputField>
<InputField
@@ -161,6 +159,6 @@ const customizingActive = computed(() => {
}
.color-picker {
margin-left: auto;
width: 100%;
}
</style>
@@ -9,20 +9,63 @@
margin-bottom: 16px;
position: sticky;
z-index: 10;
top: 48px;
padding-top: 24px;
margin-top: -32px;
top: var(--vp-layout-top-height);
width: 100%;
display: flex;
margin-bottom: 32px;
background: var(--vp-c-bg);
box-shadow: 0 16px 24px var(--vp-c-bg);
gap: 16px;
}
.search-bar :deep(.select-button) {
padding: 11px 14px;
background-color: var(--vp-c-bg-alt);
color: var(--vp-c-text-2);
flex-shrink: 0;
flex: 1;
font-weight: 500;
cursor: pointer;
}
.search-bar :deep(.select-button):hover,
.search-bar :deep(.select-button):focus {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg-alt);
}
.search-bar :deep(.select-options) {
min-width: 160px;
}
.search-bar :deep(.select-option) {
padding-right: 36px;
padding-left: 8px;
}
.search-bar :deep(.select-icon) {
display: none;
}
.search-bar :deep(.select-button) .select-text {
display: none;
}
@media (min-width: 640px) {
.search-bar :deep(.select-button) {
padding: 11px 16px 11px 16px;
}
.search-bar :deep(.select-button) .select-text {
display: block;
}
}
@media (min-width: 960px) {
.search-bar {
padding-top: 32px;
top: 64px;
margin-top: calc((var(--vp-layout-top-height, 0px) + 32px) * -1);
top: calc(var(--vp-layout-top-height, 0px) + 64px);
}
}
</style>
@@ -0,0 +1,133 @@
<script setup lang="ts">
import type { DefaultTheme } from 'vitepress/theme'
import { ref, watch, onMounted } from 'vue'
import { useAside } from 'vitepress/dist/client/theme-default/composables/aside.js'
import { useData } from 'vitepress/dist/client/theme-default/composables/data.js'
const { page } = useData()
const props = defineProps<{
carbonAds: DefaultTheme.CarbonAdsOptions
overlay?: boolean
}>()
const carbonOptions = props.carbonAds
const { isAsideEnabled } = useAside()
const container = ref()
let isInitialized = false
function init() {
if (!isInitialized) {
isInitialized = true
const params = new URLSearchParams({
serve: carbonOptions.code,
placement: carbonOptions.placement,
format: 'responsive',
})
const s = document.createElement('script')
s.id = '_carbonads_js'
s.src = `//cdn.carbonads.com/carbon.js?${params.toString()}`
s.async = true
container.value.appendChild(s)
}
}
watch(() => page.value.relativePath, () => {
if (isInitialized && isAsideEnabled.value) {
;(window as any)._carbonads?.refresh()
}
})
// no need to account for option changes during dev, we can just
// refresh the page
if (carbonOptions) {
onMounted(() => {
// if the page is loaded when aside is active, load carbon directly.
// otherwise, only load it if the page resizes to wide enough. this avoids
// loading carbon at all on mobile where it's never shown
if (isAsideEnabled.value || props.overlay) {
init()
} else {
watch(isAsideEnabled, (wide) => wide && init())
}
})
}
</script>
<template>
<div class="VPCarbonAds" ref="container" />
</template>
<style scoped>
.VPCarbonAds {
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
border-radius: 12px;
min-height: 256px;
text-align: center;
line-height: 18px;
font-size: 12px;
font-weight: 500;
background-color: var(--vp-carbon-ads-bg-color);
}
.VPCarbonAds :deep(img) {
margin: 0 auto;
border-radius: 6px;
}
.VPCarbonAds :deep(.carbon-text) {
display: block;
margin: 0 auto;
padding-top: 12px;
color: var(--vp-carbon-ads-text-color);
transition: color 0.25s;
}
.VPCarbonAds :deep(.carbon-text:hover) {
color: var(--vp-carbon-ads-hover-text-color);
}
.VPCarbonAds :deep(#carbon-responsive .carbon-poweredby),
.VPCarbonAds :deep(.carbon-poweredby) {
display: block;
padding-bottom: 2px;
font-size: 11px;
font-weight: 500;
color: var(--vp-carbon-ads-poweredby-color);
text-transform: uppercase;
transition: color 0.25s;
}
.VPCarbonAds :deep(#carbon-responsive) {
font-size: 12px;
line-height: 18px;
font-weight: 500;
}
.VPCarbonAds :deep(#carbon-responsive .carbon-poweredby) {
text-align: left;
}
.VPCarbonAds :deep(#carbon-responsive .carbon-poweredby:hover),
.VPCarbonAds :deep(.carbon-poweredby:hover) {
color: var(--vp-carbon-ads-hover-poweredby-color);
}
.VPCarbonAds :deep(> div) {
display: none;
}
.VPCarbonAds :deep(> div:first-of-type) {
display: block;
}
.VPCarbonAds :deep(#carbon-responsive) {
flex-direction: column-reverse;
}
.VPCarbonAds :deep(#carbon-responsive .carbon-responsive-wrap) {
border-radius: 10px;
}
</style>
@@ -3,6 +3,7 @@ import { useData } from 'vitepress';
import { useSidebar } from 'vitepress/dist/client/theme-default/composables/sidebar';
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue';
import { computed } from 'vue';
import SurveyAskOverlay from '../SurveyAskOverlay.vue';
const { theme } = useData();
const { hasSidebar } = useSidebar();
@@ -1,5 +1,5 @@
import { useRoute } from 'vitepress';
import { ref, inject, Ref, onMounted, watch } from 'vue';
import { ref, inject, Ref, onMounted, onUnmounted, watch } from 'vue';
export const CATEGORY_VIEW_CONTEXT = Symbol('categoryView');
@@ -13,25 +13,53 @@ export const categoryViewContext = {
categoryCounts: ref({}),
};
const CATEGORIES_PATH = '/icons/categories';
export function useCategoryView(): CategoryViewContext {
const context = inject<CategoryViewContext>(CATEGORY_VIEW_CONTEXT);
const route = useRoute();
if (!context) {
throw new Error('useCategoryView must be used with categoryView context');
}
onMounted(() => {
if (window.location.hash) {
context.selectedCategory.value = decodeURIComponent(window.location.hash.slice(1));
return context;
}
export function useCategoryViewSync(): CategoryViewContext {
const context = useCategoryView();
const route = useRoute();
function syncCategoryFromLocation() {
if (!window.location.pathname.startsWith(CATEGORIES_PATH)) {
context.selectedCategory.value = '';
context.categoryCounts.value = {};
return;
}
context.selectedCategory.value = window.location.hash
? decodeURIComponent(window.location.hash.slice(1))
: '';
}
onMounted(() => {
syncCategoryFromLocation();
window.addEventListener('hashchange', syncCategoryFromLocation);
window.addEventListener('popstate', syncCategoryFromLocation);
});
onUnmounted(() => {
window.removeEventListener('hashchange', syncCategoryFromLocation);
window.removeEventListener('popstate', syncCategoryFromLocation);
});
watch(route, (currentRoute) => {
if (currentRoute.path !== '/icons/categories') {
if (currentRoute.path !== CATEGORIES_PATH) {
context.selectedCategory.value = '';
context.categoryCounts.value = {};
return;
}
syncCategoryFromLocation();
});
return context;
@@ -16,7 +16,7 @@ export const externalLibContext = {
};
const externalLibIconNodesAPI = {
lab: 'https://lab.lucide.dev/api/icon-details',
lab: `${import.meta.env.DEV ? 'http://localhost:3000' : ''}/api/lab/icon-details`,
};
export function useExternalLibs(): ExternalLibContext {
@@ -32,13 +32,15 @@ export function useExternalLibs(): ExternalLibContext {
newExternalIconNodes[lib] = savedIconNodes[lib];
} else {
const response = await fetch(externalLibIconNodesAPI[lib]);
const iconNodes = await response.json();
const iconDetails = await response.json();
if (iconNodes) {
newExternalIconNodes[lib] = Object.values(iconNodes).map((iconEntity: IconEntity) => ({
...iconEntity,
externalLibrary: lib,
}));
if (iconDetails) {
newExternalIconNodes[lib] = Object.values(iconDetails).map((iconEntity: IconEntity) => {
return {
...iconEntity,
externalLibrary: lib,
};
});
}
}
}
@@ -34,7 +34,13 @@ export default function useScrollToCategory({
}
}
watch(selectedCategory, scrollToSelectedCategory);
watch(selectedCategory, (value) => {
if (value) {
scrollToSelectedCategory(value);
} else {
scrollTo(0);
}
});
onMounted(() => {
setTimeout(() => {
@@ -43,7 +49,11 @@ export default function useScrollToCategory({
});
watch(searchQueryDebounced, () => {
scrollTo(0);
if (selectedCategory.value) {
scrollToSelectedCategory(selectedCategory.value);
} else {
scrollTo(0);
}
});
watch(categories, (items) => {
@@ -20,16 +20,6 @@ const useSearch = <T>(
return index.value.search(query.value).map((result) => result.item);
}
if (keys.length !== 0) {
const mainKey = keys[0].name;
return collection.value.sort((a, b) => {
const aString = a[mainKey as keyof T] as string;
const bString = b[mainKey as keyof T] as string;
return aString.localeCompare(bString);
});
}
return collection.value;
});
@@ -1,5 +1,5 @@
import { useDebounce } from '@vueuse/core';
import { nextTick, onMounted, ref, watch } from 'vue';
import { onMounted, ref, watch } from 'vue';
const useSearchInput = () => {
const searchInput = ref();
@@ -13,11 +13,10 @@ const useSearchInput = () => {
newUrl.searchParams.delete('search');
} else {
newUrl.searchParams.set('search', searchString);
newUrl.hash = '';
}
nextTick(() => {
window.history.replaceState({}, '', newUrl);
});
window.history.replaceState({}, '', newUrl);
});
onMounted(() => {
+2 -2
View File
@@ -7,7 +7,6 @@ import IconsSidebarNavAfter from './layouts/IconsSidebarNavAfter.vue';
import HomeHeroIconsCard from './components/home/HomeHeroIconsCard.vue';
import HomeHeroAfter from './components/home/HomeHeroAfter.vue';
import HomeHeroInfoBefore from './components/home/HomeHeroInfoBefore.vue';
import LayoutTop from './components/base/LayoutTop.vue';
import { ICON_STYLE_CONTEXT, iconStyleContext } from './composables/useIconStyle';
import { CATEGORY_VIEW_CONTEXT, categoryViewContext } from './composables/useCategoryView';
import { EXTERNAL_LIBS_CONTEXT, externalLibContext } from './composables/useExternalLibs';
@@ -23,7 +22,8 @@ const theme: Partial<Theme> = {
'sidebar-nav-after': () => h(IconsSidebarNavAfter),
'home-hero-image': () => h(HomeHeroIconsCard),
'home-hero-actions-after': () => h(HomeHeroAfter),
'layout-top': () => h(LayoutTop),
// Keep this here for now, we might want to add more things to the top bar in the future
// 'layout-top': () => h(LayoutTop),
});
},
enhanceApp({ app }) {
+29
View File
@@ -67,6 +67,10 @@
animation: .3s transition 0s ease;
} */
html {
scrollbar-gutter: stable;
}
.VPHome {
overflow-x: hidden;
}
@@ -117,6 +121,10 @@
padding-left: 0;
}
.overview-container.icon-drawer-open {
padding-bottom: 288px;
}
.VPHomeHero .container {
flex-direction: column-reverse;
}
@@ -154,3 +162,24 @@
margin: 0 auto 48px;
max-width: 480px;
}
.VPSidebar {
/* Hide Scrollbar */
-ms-overflow-style: none;
scrollbar-width: none;
scrollbar-width: thin; /* can also be normal, or none, to not render scrollbar */
scrollbar-color: var(--vp-c-text-4) transparent; /* foreground background */
}
.VPSidebar::-webkit-scrollbar {
width: 0;
display: none;
}
.VPSidebar::-webkit-scrollbar-track {
background: transparent;
}
.VPSidebar::-webkit-scrollbar-thumb {
background: transparent;
border: none;
}
+1
View File
@@ -18,6 +18,7 @@ export interface IconEntity extends IconMetaData {
externalLibrary?: ExternalLibs;
createdRelease?: Release;
changedRelease?: Release;
popularity?: number;
}
export interface Category {
+79
View File
@@ -0,0 +1,79 @@
import { type PageData } from 'vitepress';
import getStructuredData from './getStructuredData';
import { createGeneralOGImage, createIconOGImage } from './createOGImage';
export async function transformPageData(pageData: PageData) {
pageData.frontmatter.head ??= [];
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);
const ogPath = await createIconOGImage(iconName, pageData.params?.tags || []);
if (ogPath) {
const content = `https://lucide.dev${ogPath}`;
pageData.frontmatter.head.push(
[
'meta',
{
property: 'og:image',
content,
},
],
[
'meta',
{
property: 'twitter:image',
content,
},
],
);
}
pageData.frontmatter.head.push([
'script',
{ type: 'application/ld+json' },
JSON.stringify(structuredData),
]);
}
if (pageData.relativePath.startsWith('guide/')) {
const ogPath = await createGeneralOGImage(pageData);
if (ogPath) {
const content = `https://lucide.dev${ogPath}`;
pageData.frontmatter.head.push(
[
'meta',
{
property: 'og:image',
content,
},
],
[
'meta',
{
property: 'twitter:image',
content,
},
],
);
}
}
}
+38
View File
@@ -46,5 +46,43 @@ declare global {
*/
append(container: Element): void;
};
Tally: {
// From https://tally.so/help/developer-resources#2f676e40530a460ea6a634b8441f6001
openPopup: (
formId: string,
options?: {
key?: string; // This is used as a unique identifier used for the "Show only once" and "Don't show after submit" functionality
layout?: 'default' | 'modal';
width?: number;
alignLeft?: boolean;
hideTitle?: boolean;
overlay?: boolean;
emoji?: {
text: string;
animation:
| 'none'
| 'wave'
| 'tada'
| 'heart-beat'
| 'spin'
| 'flash'
| 'bounce'
| 'rubber-band'
| 'head-shake';
};
autoClose?: number; // in milliseconds
showOnce?: boolean;
doNotShowAfterSubmit?: boolean;
customFormUrl?: string; // when you want to load the form via it's custom domain URL
hiddenFields?: {
[key: string]: any;
};
onOpen?: () => void;
onClose?: () => void;
onPageView?: (page: number) => void;
onSubmit?: (payload: SubmissionPayload) => void;
},
) => void;
};
}
}
+1 -1
View File
@@ -158,7 +158,7 @@ For each icon these attributes are applied, corresponding to the above rules.
### Minify paths
The code of paths can sometimes get quite large. To reduce file size we like to minify the code.
We recommend to use [Lucide Studio](https://studio.lucide.dev/) to tidy paths to 3 points of precision.
We recommend to use [Lucide Studio](https://studio.lucide.dev/?utm_source=lucide.dev&utm_medium=design-guide) to tidy paths to 3 points of precision.
### Allowed elements
@@ -12,6 +12,10 @@ import Sandpack from '~/.vitepress/theme/components/editors/SandpackAngular.vue'
While they aren't provided as standalone components, they can be still be passed to the `LucideIcon` component the same way as official icons:
::: info Limitation
Only custom icons that follow Lucide's [code conventions](../../../contribute/icon-design-guide.md#code-conventions) are supported.
:::
### Directly as LucideIconData
::: sandpack {template=angular showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="@lucide/angular,@lucide/lab"}
+1 -1
View File
@@ -30,7 +30,7 @@ However, not everyone can understand them easily. Read more about [how to use Lu
## Official Packages
Lucide's official packages are designed to work on different platforms, making it easier for users to integrate icons into their projects. The packages are available for various technologies, including [Web (Vanilla)](https://lucide.dev/guide/packages/lucide), [React](https://lucide.dev/guide/packages/lucide-react), [React Native](https://lucide.dev/guide/packages/lucide-react-native), [Vue](https://lucide.dev/guide/packages/lucide-vue), [Vue 3](https://lucide.dev/guide/packages/lucide-vue-next), [Svelte](https://lucide.dev/guide/packages/lucide-svelte), [Preact](https://lucide.dev/guide/packages/lucide-preact), [Solid](https://lucide.dev/guide/packages/lucide-solid), [Angular](https://lucide.dev/guide/packages/angular), [Astro](https://lucide.dev/guide/packages/lucide-astro), and [NodeJS](https://lucide.dev/guide/packages/lucide-static#nodejs).
Lucide's official packages are designed to work on different platforms, making it easier for users to integrate icons into their projects. The packages are available for various technologies, including [Web (Vanilla)](./lucide/index.md), [React](./react/index.md), [React Native](./react-native/index.md), [Vue](./vue/index.md), [Svelte](./svelte/index.md), [Preact](./preact/index.md), [Solid](./solid/index.md), [Angular](./angular/index.md), [Astro](./astro/index.md), and [Static](./static/index.md).
## Community
+64 -28
View File
@@ -12,19 +12,23 @@ Implementation of the Lucide icon library for web applications.
::: code-group
```sh [pnpm]
pnpm add lucide@next
pnpm add lucide
```
```sh [yarn]
yarn add lucide@next
yarn add lucide
```
```sh [npm]
npm install lucide@next
npm install lucide
```
```sh [bun]
bun add lucide@next
bun add lucide
```
```sh [deno]
deno add lucide
```
:::
@@ -38,19 +42,23 @@ Implementation of the Lucide icon library for React applications.
::: code-group
```sh [pnpm]
pnpm add lucide-react@next
pnpm add lucide-react
```
```sh [yarn]
yarn add lucide-react@next
yarn add lucide-react
```
```sh [npm]
npm install lucide-react@next
npm install lucide-react
```
```sh [bun]
bun add lucide-react@next
bun add lucide-react
```
```sh [deno]
deno add lucide-react
```
:::
@@ -80,6 +88,10 @@ npm install @lucide/vue
bun add @lucide/vue
```
```sh [deno]
deno add @lucide/vue
```
:::
For more details, see the [documentation](./vue/index.md).
@@ -91,19 +103,23 @@ Implementation of the Lucide icon library for Svelte applications.
::: code-group
```sh [pnpm]
pnpm add @lucide/svelte@next
pnpm add @lucide/svelte
```
```sh [yarn]
yarn add @lucide/svelte@next
yarn add @lucide/svelte
```
```sh [npm]
npm install @lucide/svelte@next
npm install @lucide/svelte
```
```sh [bun]
bun add @lucide/svelte@next
bun add @lucide/svelte
```
```sh [deno]
deno add @lucide/svelte
```
:::
> `@lucide/svelte` is only for Svelte 5, for Svelte 4 use the `lucide-svelte` package.
@@ -117,19 +133,23 @@ Implementation of the Lucide icon library for Solid applications.
::: code-group
```sh [pnpm]
pnpm add lucide-solid@next
pnpm add lucide-solid
```
```sh [yarn]
yarn add lucide-solid@next
yarn add lucide-solid
```
```sh [npm]
npm install lucide-solid@next
npm install lucide-solid
```
```sh [bun]
bun add lucide-solid@next
bun add lucide-solid
```
```sh [deno]
deno add lucide-solid
```
:::
@@ -158,6 +178,10 @@ npm install @lucide/angular
bun add @lucide/angular
```
```sh [deno]
deno add @lucide/angular
```
:::
For more details, see the [documentation](./angular/index.md).
@@ -169,19 +193,23 @@ Implementation of the Lucide icon library for preact applications.
::: code-group
```sh [pnpm]
pnpm add lucide-preact@next
pnpm add lucide-preact
```
```sh [yarn]
yarn add lucide-preact@next
yarn add lucide-preact
```
```sh [npm]
npm install lucide-preact@next
npm install lucide-preact
```
```sh [bun]
bun add lucide-preact@next
bun add lucide-preact
```
```sh [deno]
deno add lucide-preact
```
@@ -196,19 +224,23 @@ Implementation of the Lucide icon library for Astro applications.
::: code-group
```sh [pnpm]
pnpm add @lucide/astro@next
pnpm add @lucide/astro
```
```sh [yarn]
yarn add @lucide/astro@next
yarn add @lucide/astro
```
```sh [npm]
npm install @lucide/astro@next
npm install @lucide/astro
```
```sh [bun]
bun add @lucide/astro@next
bun add @lucide/astro
```
```sh [deno]
deno add @lucide/astro
```
:::
@@ -222,19 +254,23 @@ Implementation of the Lucide icon library for multiple usages that like to use:
::: code-group
```sh [pnpm]
pnpm add lucide-static@next
pnpm add lucide-static
```
```sh [yarn]
yarn add lucide-static@next
yarn add lucide-static
```
```sh [npm]
npm install lucide-static@next
npm install lucide-static
```
```sh [bun]
bun add lucide-static@next
bun add lucide-static
```
```sh [deno]
deno add lucide-static
```
:::
+10 -1
View File
@@ -3,12 +3,13 @@
::: warning
This documentation is for `@lucide/angular`.
To learn about our legacy package for Angular, please refer to [`lucide-angular`](./lucide-angular).
To learn about our legacy package for Angular, please refer to [`lucide-angular`](https://v0.lucide.dev/guide/packages/lucide-angular).
:::
A standalone, signal-based, zoneless implementation of Lucide icons for Angular.
**What you can accomplish:**
- Use icons as standalone Angular components with full dependency injection support
- Configure icons globally through modern Angular providers
- Integrate with Angular's reactive forms and data binding
@@ -118,6 +119,7 @@ Alternatively, the component also accepts string inputs.
To use icons this way, first, you have to provide icons via `provideLucideIcons`:
:::code-group
```ts{7-10} [app.config.ts]
import { ApplicationConfig } from '@angular/core';
import { provideLucideIcons, LucideCircleCheck, LucideCircleX } from '@lucide/angular';
@@ -148,6 +150,7 @@ import { LucideIcon } from '@lucide/angular';
})
export class Foobar { }
```
:::
::: tip
@@ -259,19 +262,25 @@ export class Foobar {
## Troubleshooting
### The icon is not being displayed
If using per-icon-components:
1. Ensure that the icon component is being imported, if using per-icon-components
2. Check that the icon name matches exactly (case-sensitive)
If using the dynamic component:
1. Ensure the icon is provided via `provideLucideIcons()` if using string names
2. Verify the icon is imported from `@lucide/angular` and not the legacy package
### TypeScript errors?
Make sure you're importing from `@lucide/angular` and not `lucide-angular`.
### Icons render with wrong defaults
Ensure `provideLucideConfig()` is used at the right level.
## Migration guide
Migrating from `lucide-angular`? Read our [comprehensive migration guide](https://github.com/lucide-icons/lucide/blob/main/packages/angular/MIGRATION.md).
-187
View File
@@ -1,187 +0,0 @@
# Lucide Angular
::: warning
This documentation is for our legacy package for Angular.
For our modern, standalone-first implementation, please refer to [`@lucide/angular`](./angular).
:::
Angular components and services for Lucide icons that integrate with Angular's dependency injection and component system. Provides both traditional module-based and modern standalone component approaches for maximum flexibility in Angular applications.
**What you can accomplish:**
- Use icons as Angular components with full dependency injection support
- Configure icons globally through Angular services and providers
- Choose from multiple component selectors (lucide-angular, lucide-icon, i-lucide, span-lucide)
- Integrate with Angular's reactive forms and data binding
- Build scalable applications with tree-shaken icon bundles and lazy loading support
## Installation
::: code-group
```sh [pnpm]
pnpm add lucide-angular
```
```sh [yarn]
yarn add lucide-angular
```
```sh [npm]
npm install lucide-angular
```
```sh [bun]
bun add lucide-angular
```
:::
## How to use
### Step 1: Import `LucideAngularModule`
In any Angular module you wish to use Lucide icons in, you have to import `LucideAngularModule`, and pick any icons you wish to use:
```js
import { LucideAngularModule, File, House, Menu, UserCheck } from 'lucide-angular';
@NgModule({
imports: [
LucideAngularModule.pick({File, House, Menu, UserCheck})
]
})
export class AppModule { }
```
or using standalone version:
```js
import { Component } from '@angular/core';
import { LucideAngularModule, FileIcon } from 'lucide-angular';
@Component({
standalone: true,
selector: 'app-root',
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
imports: [LucideAngularModule]
})
export class AppComponent {
readonly FileIcon = FileIcon;
}
```
### Step 2: Use the icons in templates
Within your templates you may now use one of the following component tags to insert an icon:
```html
<lucide-angular name="file" class="my-icon"></lucide-angular>
<lucide-icon name="house" class="my-icon"></lucide-icon>
<i-lucide name="menu" class="my-icon"></i-lucide>
<span-lucide name="user-check" class="my-icon"></span-lucide>
```
for standalone
```html
<lucide-angular [img]="FileIcon" class="my-icon"></lucide-angular>
<lucide-icon [img]="FileIcon" class="my-icon"></lucide-icon>
<i-lucide [img]="FileIcon" class="my-icon"></i-lucide>
<span-lucide [img]="FileIcon" class="my-icon"></span-lucide>
```
### Props
You can pass additional props to adjust the icon appearance.
| name | type | default |
| --------------------- | --------- | ------------ |
| `size` | *number* | 24 |
| `color` | *string* | currentColor |
| `strokeWidth` | *number* | 2 |
| `absoluteStrokeWidth` | *boolean* | false |
```html
<i-lucide name="house" [size]="48" color="red" [strokeWidth]="1"></i-lucide>
```
### Global configuration
You can inject the `LucideIconConfig` service in your root component to globally configure the default property values as defined above.
### Styling using a custom CSS class
Any extra HTML attribute is ignored, but the `class` attribute
is passed onto the internal SVG image element and it can be used to style it:
```css
svg.my-icon {
width: 12px;
height: 12px;
stroke-width: 3;
}
```
## Injecting multiple icon providers
You may provide additional icons using the `LUCIDE_ICONS` injection token,
which accepts multiple providers of the interface `LucideIconsProviderInterface`
with the utility class `LucideIconsProvider` available for easier usage:
```js
import { LUCIDE_ICONS, LucideIconProvider } from 'lucide-angular';
import { MyIcon } from './icons/my-icon';
const myIcons = {MyIcon};
@NgModule({
providers: [
{provide: LUCIDE_ICONS, multi: true, useValue: new LucideIconProvider(myIcons)},
]
})
export class AppModule { }
```
To add custom icons, you will first need to convert them to an [svgson format](https://github.com/elrumordelaluz/svgson).
## Loading all icons
::: danger
You may also opt to import all icons if necessary using the following format but be aware that this will significantly increase your application build size.
:::
```js
import { icons } from 'lucide-angular';
...
LucideAngularModule.pick(icons)
```
## With Lucide Lab or custom icons
[Lucide Lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.
They can be used in the same way as the official icons.
```js
import { LucideAngularModule } from 'lucide-angular';
import { coconut } from '@lucide/lab';
@NgModule({
imports: [
LucideAngularModule.pick({ coconut })
]
})
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](../accessibility.md).
+2 -1
View File
@@ -3,6 +3,7 @@
Vue 2 components for Lucide icons that integrate with Vue's Options API and template system. Each icon is a Vue component that renders as an inline SVG, providing familiar Vue development patterns for legacy applications still using Vue 2.
**What you can accomplish:**
- Use icons as Vue 2 components with Options API integration
- Maintain legacy Vue 2 applications with modern icon components
- Integrate with Vue 2's template system and component lifecycle
@@ -155,7 +156,7 @@ You can add accessibility attributes using aria-labels.
```vue
<script setup>
import { Check } from 'lucide-vue-next';
import { Check } from '@lucide/vue';
</script>
<template>
@@ -9,7 +9,7 @@ import Sandpack from '~/.vitepress/theme/components/editors/SandpackPreact.vue'
# Combining icons
You can combine multiple icons into a single icon by nesting SVG elements.
This is useful if you want to create custom icons icons by combining existing ones.
This is useful if you want to create custom icons by combining existing ones.
::: sandpack {showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="lucide-preact"}
@@ -6,7 +6,7 @@ description: Learn how to combine multiple icons into a single icon nested SVG e
# Combining icons
You can combine multiple icons into a single icon by nesting SVG elements.
This is useful if you want to create custom icons icons by combining existing ones.
This is useful if you want to create custom icons by combining existing ones.
```SnackPlayer name=State&ext=js&dependencies=react-native-svg,lucide-react-native
import React, {useState, useEffect} from 'react';
@@ -0,0 +1,56 @@
---
title: Optimizations - React Native
description: Learn how to optimize the bundle size of your React Native and Expo web exports by tree-shaking Lucide icons.
---
# Optimizations
By default you import icons from the `lucide-react-native` entry point:
```jsx
import { Camera } from 'lucide-react-native';
```
This is convenient, but it relies on the bundler to _tree-shake_ the entry point (a "barrel" file that re-exports every icon) so that only the icons you actually use end up in your bundle.
On native platforms this is usually fine. On **web exports** it can be a problem, because the Metro bundler is currently not very good at tree-shaking barrel imports and may include **all** icons in your final bundle.
## The Metro tree-shaking limitation
When you build for web with Expo (`expo export --platform web`), Metro is used to bundle your JavaScript. Metro bundles modules on-demand and, by default, does not remove unused exports from a barrel file.
This means an import like the one below can pull in the entire icon set, even though only a single icon is rendered:
```jsx
// May bundle every Lucide icon on web exports
import { Camera } from 'lucide-react-native';
```
Expo documents an experimental optimization for [React Native web imports](https://docs.expo.dev/guides/tree-shaking/#react-native-web-imports) and for [removing unused imports and exports](https://docs.expo.dev/guides/tree-shaking/#remove-unused-imports-and-exports). In practice this tree-shaking does **not** currently work reliably for `lucide-react-native` barrel imports, so the unused icons are not removed from web exports.
## Recommended: import icons individually
To guarantee that only the icons you use are bundled — regardless of the bundler's tree-shaking capabilities — import each icon directly from its own module:
```jsx
import Camera from 'lucide-react-native/icons/camera';
// Usage
const App = () => {
return <Camera />;
};
export default App;
```
Because each icon lives in its own file, the bundler only ever includes the icons you explicitly import. This keeps your web export small without depending on Metro's experimental tree-shaking.
The icon module name is the [kebab-case](https://developer.mozilla.org/en-US/docs/Glossary/Kebab_case) version of the icon name. For example, the `ArrowRight` icon is imported from `lucide-react-native/icons/arrow-right`:
```jsx
import ArrowRight from 'lucide-react-native/icons/arrow-right';
```
::: tip
Individual icon imports work identically on native and web, so you can safely use this style across your whole project to keep bundles as small as possible on every platform.
:::
+1 -1
View File
@@ -9,7 +9,7 @@ import Sandpack from '~/.vitepress/theme/components/editors/Sandpack.vue'
# Combining icons
You can combine multiple icons into a single icon by nesting SVG elements.
This is useful if you want to create custom icons icons by combining existing ones.
This is useful if you want to create custom icons by combining existing ones.
::: sandpack {template=react showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="lucide-react"}
+1 -1
View File
@@ -5,7 +5,7 @@ description: Learn about the different types exported by the `lucide-react` pack
# TypeScript Support
List of exported types from the `lucide-react` package.
These can be used to type your components when using Lucide icons in a TypeScript React project
These can be used to type your components when using Lucide icons in a TypeScript React project.
## `LucideProps`
+1 -1
View File
@@ -10,7 +10,7 @@ import Sandpack from '~/.vitepress/theme/components/editors/Sandpack.vue'
# Combining icons
You can combine multiple icons into a single icon by nesting SVG elements.
This is useful if you want to create custom icons icons by combining existing ones.
This is useful if you want to create custom icons by combining existing ones.
::: sandpack {template=vite-solid showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="lucide-solid"}
@@ -9,7 +9,7 @@ import Sandpack from '~/.vitepress/theme/components/editors/SandpackSvelte.vue';
# Combining icons
You can combine multiple icons into a single icon by nesting SVG elements.
This is useful if you want to create custom icons icons by combining existing ones.
This is useful if you want to create custom icons by combining existing ones.
::: sandpack {template=vite-svelte showTabs=false editorHeight=400 editorWidthPercentage=60}
+4 -6
View File
@@ -15,24 +15,22 @@ Make sure you have a Svelte environment set up. If you don't have one yet, you c
## Installation
<!-- TODO: v1 Remove After full release -->
::: code-group
```sh [pnpm]
pnpm install @lucide/svelte@next
pnpm install @lucide/svelte
```
```sh [yarn]
yarn add @lucide/svelte@next
yarn add @lucide/svelte
```
```sh [npm]
npm install @lucide/svelte@next
npm install @lucide/svelte
```
```sh [bun]
bun add @lucide/svelte@next
bun add @lucide/svelte
```
:::
+1 -1
View File
@@ -9,7 +9,7 @@ import Sandpack from '~/.vitepress/theme/components/editors/SandpackVue.vue'
# Combining icons
You can combine multiple icons into a single icon by nesting SVG elements.
This is useful if you want to create custom icons icons by combining existing ones.
This is useful if you want to create custom icons by combining existing ones.
::: sandpack {template=vue showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="@lucide/vue"}
+12 -2
View File
@@ -1,9 +1,19 @@
import iconNodes from '../.vitepress/data/iconNodes';
import * as iconDetails from '../.vitepress/data/iconDetails';
export default {
async load() {
return {
icons: Object.entries(iconNodes).map(([name, iconNode]) => ({ name, iconNode })),
icons: Object.entries(iconDetails).map(
([, { name, iconNode, popularity, createdRelease, aliases = [] }]) => ({
name,
iconNode,
popularity: popularity?.count ?? 0,
aliases: aliases
.map((alias) => (typeof alias === 'string' ? alias : alias?.name))
.filter((alias): alias is string => Boolean(alias)),
createdRelease,
}),
),
};
},
};
+19 -17
View File
@@ -1,24 +1,26 @@
import { IconEntity } from '../../.vitepress/theme/types';
import iconNodes from '../../.vitepress/data/lab/iconNodes';
import iconPopularity from '../../.vitepress/data/lab/iconPopularity';
import iconMetaData from '../../.vitepress/data/lab/iconMetaData';
import { type IconEntity } from '../../.vitepress/theme/types';
export default {
paths: async () => {
try {
const iconDetailsResponse = await fetch('https://lab.lucide.dev/api/icon-details');
const iconDetails = (await iconDetailsResponse.json()) as Record<string, IconEntity>;
return (Object.entries(iconNodes) as unknown as IconEntity[]).map(([name, iconNode]) => {
const iconDetails = iconMetaData[name];
return Object.values(iconDetails).map((iconEntity) => {
const params = {
externalLibrary: 'lab',
...iconEntity,
};
delete iconDetails['$schema'];
return {
params,
};
});
} catch (error) {
console.error('Error fetching icon details:', error);
return [];
}
const params = {
name,
iconNode,
externalLibrary: 'lab',
popularity: iconPopularity[name]?.count ?? 0,
...iconDetails,
};
return {
params,
};
});
},
};
+35 -31
View File
@@ -8,18 +8,21 @@
"docs:dev": "pnpm run /^prebuild:.*/ && vitepress dev",
"docs:build": "pnpm run /^prebuild:.*/ && vitepress build",
"docs:preview": "vitepress preview",
"build:docs": "vitepress build",
"prebuild:iconNodes": "node ./scripts/writeIconNodes.mjs",
"prebuild:metaJson": "node ./scripts/writeIconMetaIndex.mjs",
"prebuild:releaseJson": "node ./scripts/writeReleaseMetadata.mjs",
"prebuild:categoriesJson": "node ./scripts/writeCategoriesMetadata.mjs",
"prebuild:relatedIcons": "node ./scripts/writeIconRelatedIcons.mjs",
"prebuild:iconDetails": "node ./scripts/writeIconDetails.mjs",
"prebuild:brandStopwords": "node ./scripts/writeBrandStopwords.mjs",
"postbuild:vercelJson": "node ./scripts/writeVercelOutput.mjs",
"dev": "npx nitropack dev",
"prebuild:api": "npx nitropack prepare",
"build:api": "npx nitropack build",
"build:docs": "NODE_OPTIONS=--max-old-space-size=8192 vitepress build",
"prebuild:iconNodes": "node ./scripts/writeIconNodes.mts",
"prebuild:metaJson": "node ./scripts/writeIconMetaIndex.mts",
"prebuild:releaseJson": "node ./scripts/writeReleaseMetadata.mts",
"prebuild:categoriesJson": "node ./scripts/writeCategoriesMetadata.mts",
"prebuild:relatedIcons": "node ./scripts/writeIconRelatedIcons.mts",
"prebuild:iconDetails": "node ./scripts/writeIconDetails.mts",
"prebuild:iconPopularity": "node ./scripts/writeiconPopularity.mts && node ./scripts/writeiconPopularityIndex.mts",
"prebuild:brandStopwords": "node ./scripts/writeBrandStopwords.mts",
"prebuild:writeLabIconNodes": "node ./scripts/writeLabIconNodes.mts",
"prebuild:writeLabIconMetaIndex": "node ./scripts/writeLabIconMetaIndex.mts",
"postbuild:vercelJson": "node ./scripts/writeVercelOutput.mts",
"dev": "nitropack dev",
"prebuild:api": "nitropack prepare",
"build:api": "NODE_OPTIONS=--max-old-space-size=8192 nitropack build",
"build": "pnpm run /^prebuild:.*/ && pnpm run build:api && pnpm run build:docs && pnpm postbuild:vercelJson",
"preview": "node .output/server/index.mjs"
},
@@ -31,39 +34,40 @@
"@lucide/shared": "workspace:*",
"@rollup/plugin-replace": "^6.0.3",
"@types/semver": "^7.7.1",
"h3": "^1.15.9",
"nitropack": "^2.12.4",
"rollup-plugin-copy": "^3.5.0",
"svg-path-commander": "^2.1.11",
"vitepress": "^1.6.4",
"vitepress-plugin-group-icons": "^1.6.5",
"vitepress-plugin-llms": "^1.11.1",
"markdown-it": "^14.1.0",
"h3": "^1.15.11",
"markdown-it": "^14.3.0",
"markdown-it-container": "^4.0.0",
"semver": "^7.7.3",
"nitropack": "^2.13.4",
"rollup-plugin-copy": "^3.5.0",
"semver": "^7.8.5",
"sharp": "^0.34.5",
"shiki": "^3.15.0",
"simple-git": "^3.32.3",
"sitemap": "^7.1.2",
"shiki": "^3.23.0",
"simple-git": "^3.36.0",
"sitemap": "^7.1.3",
"svg-path-commander": "^2.2.1",
"svg-pathdata": "^6.0.3",
"svgson": "^5.3.1"
"svgson": "^5.3.1",
"vitepress": "^1.6.4",
"vitepress-plugin-group-icons": "^1.7.5",
"vitepress-plugin-llms": "^1.13.3"
},
"dependencies": {
"@floating-ui/vue": "^1.1.9",
"@floating-ui/vue": "^1.1.11",
"@headlessui/vue": "^1.7.23",
"@lucide/vue": "workspace:*",
"@vueuse/components": "^14.0.0",
"@vueuse/core": "^14.0.0",
"@vueuse/components": "^14.3.0",
"@vueuse/core": "^14.3.0",
"@vueuse/integrations": "^14.3.0",
"element-to-path": "^1.2.1",
"fuse.js": "^7.1.0",
"fuse.js": "^7.5.0",
"jszip": "^3.10.1",
"lodash-es": "^4.17.23",
"lodash-es": "^4.18.1",
"lucide": "workspace:*",
"lucide-react": "workspace:*",
"motion-v": "1.10.3",
"react": "18.2.0",
"react-dom": "18.2.0",
"sandpack-vue3": "3.1.12",
"vue": "^3.5.24"
"vue": "^3.5.39"
}
}
+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 200" fill="none">
<path fill="#00e8ff" d="M40 120l20-60l90 90l-30 50l-40-40h-20" />
<path fill="#283198" d="M80 160 L80 80 L120 40 L 120 120 M0 160 L40 200 L40 120 L20 120" />
<path fill="#324fff" d="M40 120v-80l40-40v80M120 200v-80l40-40v80M0 160v-80l40 40" />
<path fill="#0ff" d="M40 200v-80l40 40" />
</svg>

After

Width:  |  Height:  |  Size: 377 B

+15
View File
@@ -0,0 +1,15 @@
<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 4a4 4 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="url(#a)" fill-rule="evenodd" d="M16 27.6a6.6 6.6 0 0 0 5.5-10.4l4.3-4.3c.3-.3.1-1-.4-1a29 29 0 0 1-4.8-1.4h-.1l-.6-.3A11.4 11.4 0 0 0 5.1 24.5c.2.6 1 .9 1.5.6q.7-.6.5-1.4a9.3 9.3 0 0 1 14.6-10l-2 1.8q-1.6-1-3.7-1.1a6.6 6.6 0 0 0-5.4 10.4L6.3 29c-.4.3-.2 1 .3 1a29 29 0 0 1 4.8 1.4h.1l.6.3a11 11 0 0 0 12-2.7 11 11 0 0 0 2.8-11.6c-.2-.6-1-.9-1.5-.6q-.6.6-.5 1.4a9.3 9.3 0 0 1-14.6 10l2-1.8q1.6 1 3.7 1.1m4.4-6.6a4.5 4.5 0 0 1-6.7 4l6.2-6.1q.5.9.5 2.1m-9 0a4.5 4.5 0 0 1 6.8-3.9L12 23.3q-.6-1-.6-2.3" clip-rule="evenodd"/>
<path fill="url(#b)" d="M57.7 19.3q3.5.1 3.5 4 0 3.6-3.5 3.8-2.3 0-2.8-1.9h-.3l.2 1.4v3.7h-1.4V19.5h1.4l-.2 1.7h.3q.6-1.9 2.8-1.9m16.6 7.4h.3l2-7.2h1.5l-2.5 8.3q-.4 2-2.4 2.2l-2.2.2v-1.4h2.5q.5.1.5-.4l.5-1.5H73l-2.2-7.4h1.4zm-26-7.4q3.3 0 3.3 3.7H46c0 1.7.5 3 2.5 3q2 0 2-2.1H52q-.4 3.1-3.5 3.2-3.8-.1-3.9-3.9 0-3.7 3.7-3.9m46.1-3q4 0 4.4 4.2h-1.5q-.2-3-3-3-3 0-3 4.2t3.3 4.2q3 0 3.2-3h1.4q-.3 4.3-4.6 4.2-4.7 0-4.7-5.4t4.5-5.4m16 3q3.6.1 3.8 4-.2 3.6-3.9 3.8-3.7-.1-3.8-3.9.1-3.7 3.8-3.9m6.4 4.6q0 2 2 2 2.3-.2 2.3-2.4v-4h1.4v5.8q-.1.6.4.4l.9-.1v1.3h-.8q-1.6 0-1.7-1.6h-.3q-.5 1.8-2.6 1.8-2.9 0-2.8-3v-4.6h1.5zm15.6 1.4q-.1.6.4.4l.9-.1v1.3h-.8q-1.7-.1-1.8-1.7h-.3q-.4 1.9-2.8 2-3.4-.2-3.5-4 .1-3.7 3.5-3.9 2.4 0 2.8 2h.3l-.1-1.4v-4h1.4zm-89-5.7L36 25.4v.3h7.8v1.2h-8v-3l7.5-5.8v-.3H36v-1.2h7.4zm21 .3L64 21h.3q.5-1.8 2.7-1.8 2.8 0 2.7 3v4.6h-1.5l.3-4.4q0-2-2-2-2.3.1-2.3 2.5v4H63V15.7h1.4zM80.5 21h.3q.4-1.7 2.2-1.6h1.3V21l-1.6-.2q-2 0-2 2.3v4h-1.5v-7.5h1.4zm20.9-5.3q2 0 2 2v8h2.2v1.1h-6v-1.2h2.4v-8.4q.1-.6-.5-.4l-1.4.3v-1.4zm8.8 4.7q-2.4 0-2.4 2.7t2.4 2.7q2.4 0 2.5-2.7 0-2.6-2.5-2.7m-52.8 0q-2.6 0-2.6 2.7.1 2.6 2.6 2.7 2.3 0 2.3-2.7 0-2.6-2.3-2.7m70.8 0q-2.4 0-2.4 2.7 0 2.6 2.4 2.7 2.7 0 2.6-2.7-.1-2.6-2.6-2.7m-80 0q-1.8 0-2.1 1.5h4q0-1.4-1.9-1.5"/>
<defs>
<linearGradient id="a" x1="4.6" x2="27.4" y1="21" y2="21" gradientUnits="userSpaceOnUse">
<stop stop-color="#010101"/>
<stop offset="1" stop-color="#949494"/>
</linearGradient>
<linearGradient id="b" x1="35.7" x2="133.7" y1="23.1" y2="23.1" gradientUnits="userSpaceOnUse">
<stop stop-color="#010101"/>
<stop offset="1" stop-color="#646464"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -23,11 +23,12 @@ const writeIconFiles = icons.map(async (iconFileName) => {
const location = path.resolve(iconDetailsDirectory, `${iconName}.ts`);
const contents = `\
import iconNode from '../iconNodes/${iconName}.node.json'
import metaData from '../../../../icons/${iconName}.json'
import releaseData from '../releaseMetadata/${iconName}.json'
import iconNode from '../iconNodes/${iconName}.node.json' with { type: 'json' };
import metaData from '../../../../icons/${iconName}.json' with { type: 'json' };
import releaseData from '../releaseMetadata/${iconName}.json' with { type: 'json' };
import popularity from '../iconPopularity/${iconName}.json' with { type: 'json' };
const { tags, categories, contributors, aliases, deprecated, deprecationReason, toBeRemovedInVersion } = metaData
const { tags, categories, contributors, aliases, deprecated, deprecationReason, toBeRemovedInVersion } = metaData;
const iconDetails = {
name: '${iconName}',
@@ -37,12 +38,13 @@ const iconDetails = {
categories,
aliases,
deprecated,
popularity,
deprecationReason,
toBeRemovedInVersion,
...releaseData,
}
};
export default iconDetails
export default iconDetails;
`;
await fs.promises.writeFile(location, contents, 'utf-8');
@@ -42,7 +42,7 @@ const getRelatedIcons = (currentIcon, icons) => {
};
const iconsMetaDataPromises = svgFiles.map(async (iconName) => {
const metaDataFileContent = await fs.promises.readFile(`../icons/${iconName}`);
const metaDataFileContent = await fs.promises.readFile(`../icons/${iconName}`, 'utf-8');
const metaData = JSON.parse(metaDataFileContent);
const name = iconName.replace('.json', '');
+49
View File
@@ -0,0 +1,49 @@
import fs from 'fs';
import path from 'path';
import { readSvgDirectory, toCamelCase } from '@lucide/helpers';
const currentDir = process.cwd();
const ICONS_DIR = path.resolve(currentDir, '../lab');
const iconJsonFiles = await readSvgDirectory(ICONS_DIR, '.json');
const labDirectory = path.resolve(currentDir, '.vitepress/data/lab');
const location = path.resolve(currentDir, labDirectory, 'iconMetaData.ts');
if (fs.existsSync(location)) {
fs.unlinkSync(location);
}
if (!fs.existsSync(labDirectory)) {
fs.mkdirSync(labDirectory);
}
const iconMetaIndexFileImports = [];
const iconMetaIndexFileExports = [];
iconJsonFiles.forEach((iconJsonFile) => {
const iconName = path.basename(iconJsonFile, '.json');
iconMetaIndexFileImports.push(
`import ${toCamelCase(iconName)}Metadata from '../../../../lab/${iconName}.json';`,
);
iconMetaIndexFileExports.push(` '${iconName}': ${toCamelCase(iconName)}Metadata,`);
});
try {
await fs.promises.writeFile(
location,
`\
${iconMetaIndexFileImports.join('\n')}
export default {
${iconMetaIndexFileExports.join('\n')}
}
`,
'utf-8',
);
console.log('Successfully write icon json file index');
} catch (error) {
throw new Error(`Something went wrong generating icon json file index file,\n ${error}`);
}
+62
View File
@@ -0,0 +1,62 @@
import fs from 'fs';
import path from 'path';
import { renderIconsObject } from '@lucide/build-icons';
import { readSvgDirectory, toCamelCase } from '@lucide/helpers';
const currentDir = process.cwd();
const ICONS_DIR = path.resolve(currentDir, '../lab');
const svgFiles = await readSvgDirectory(ICONS_DIR);
const icons = await renderIconsObject(svgFiles, ICONS_DIR, true);
const iconNodesDirectory = path.resolve(currentDir, '.vitepress/data/lab', 'iconNodes');
if (fs.existsSync(iconNodesDirectory)) {
fs.rmSync(iconNodesDirectory, { recursive: true, force: true });
}
if (!fs.existsSync(iconNodesDirectory)) {
fs.mkdirSync(iconNodesDirectory);
}
const iconIndexFile = path.resolve(iconNodesDirectory, `index.ts`);
const iconIndexFileImports: string[] = [];
const iconIndexFileExports: string[] = [];
const iconIndexFileDefaultExports: string[] = [];
const writeIconFiles = Object.entries(icons).map(async ([iconName, { children }]) => {
// We need to use .node.json because the there is a file called package, which is a reserved word for packages.
const location = path.resolve(iconNodesDirectory, `${iconName}.node.json`);
const iconNode = children.map(({ name, attributes }) => [name, attributes]);
const output = JSON.stringify(iconNode, null, 2);
await fs.promises.writeFile(location, output, 'utf-8');
iconIndexFileImports.push(
`import ${toCamelCase(iconName)}Node from './${iconName}.node.json' with { type: "json" };`,
);
iconIndexFileExports.push(` ${toCamelCase(iconName)}Node as ${toCamelCase(iconName)},`);
iconIndexFileDefaultExports.push(` '${iconName}': ${toCamelCase(iconName)}Node,`);
});
try {
await Promise.all(writeIconFiles);
await fs.promises.writeFile(
iconIndexFile,
`\
${iconIndexFileImports.join('\n')}
export {
${iconIndexFileExports.join('\n')}
}
export default {
${iconIndexFileDefaultExports.join('\n')}
}
`,
'utf-8',
);
console.log('Successfully write', writeIconFiles.length, 'iconNodes.');
} catch (error) {
throw new Error(`Something went wrong generating iconNode files,\n ${error}`);
}
@@ -70,10 +70,10 @@ const comparisonsPromises = tags.map(async (tag, index) => {
};
});
const comparisons = await Promise.all(comparisonsPromises);
const comparisons = (await Promise.all(comparisonsPromises)).filter((comparison) => comparison != null && Object.keys(comparison.iconFiles).length > 0);
const newReleaseMetaData = {};
comparisons.forEach(({ tag, iconFiles, date } = {}) => {
comparisons.forEach(({ tag, iconFiles, date }) => {
if (tag == null) return;
iconFiles.forEach(({ status, file, renamedFile }) => {

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