Compare commits

..
1 Commits
Author SHA1 Message Date
Eric Fennis 63353ad207 Setup solid 2 2026-07-10 11:51:42 +02:00
888 changed files with 10527 additions and 23285 deletions
-1
View File
@@ -9,4 +9,3 @@ strikethrough
touchpad
ungroup
toc
sunlounger
-2
View File
@@ -47,9 +47,7 @@ Common scopes: icons, docs, studio, site, dev
### Design <!-- ONLY for new icons -->
<!-- All of these requirements must be fulfilled. -->
- [ ] 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.
+4
View File
@@ -27,6 +27,10 @@ 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' &&
@@ -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.](https://github.com/lucide-icons/lucide/blob/main/BRAND_LOGOS_STATEMENT.md)
[Click here to read our official statement about brand logos in Lucide.](./BRAND_LOGOS_STATEMENT.md)
You can [search for similar issues.](https://github.com/lucide-icons/lucide/issues?q=is%3Aissue+${VALUE})
+3 -1
View File
@@ -1,7 +1,9 @@
name: Linting PR code
name: Linting PR
on:
pull_request:
paths-ignore:
- icons/*.svg
jobs:
lint-code:
+1 -1
View File
@@ -1,4 +1,4 @@
name: Linting PR title
name: Linting PR
on:
pull_request:
+1 -29
View File
@@ -7,7 +7,6 @@ on:
pull_request:
paths:
- 'icons/*'
- 'lab/*'
jobs:
lint-filenames:
@@ -18,47 +17,20 @@ 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/*
lab/*
files: icons/*
- 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
+2 -2
View File
@@ -1,6 +1,6 @@
name: Request Review
name: 'Request Review'
on:
pull_request:
pull_request_target:
types: [opened]
paths:
- icons/*.svg
-3
View File
@@ -54,9 +54,6 @@ 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/**
+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/?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.
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.
#### Editor guides
+5 -4
View File
@@ -56,6 +56,7 @@
"kubernetes": "Kubernetes",
"leetcode": "LeetCode",
"leet-code": "LeetCode",
"line": "LINE",
"linkedin": "LinkedIn",
"lua": "Lua",
"mariadb": "MariaDB",
@@ -68,7 +69,7 @@
"nestjs": "NestJS",
"netflix": "Netflix",
"netlify": "Netlify",
"nextjs": "Next.js",
"next": "Next.js",
"nodejs": "Node.js",
"notion": "Notion",
"nostr": "Nostr",
@@ -104,8 +105,7 @@
"shopify": "Shopify",
"skype": "Skype",
"slack": "Slack",
"snapchat": "Snapchat",
"solidjs": "SolidJS",
"solid": "SolidJS",
"soundcloud": "SoundCloud",
"spotify": "Spotify",
"sqlite": "SQLite",
@@ -144,5 +144,6 @@
"xbox": "Xbox",
"yarn": "Yarn",
"youtube": "YouTube",
"zig": "Zig"
"zig": "Zig",
"zoom": "Zoom"
}
@@ -1,25 +0,0 @@
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,
},
];
}),
);
});
@@ -1,14 +0,0 @@
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;
});
@@ -1,30 +0,0 @@
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;
}, {});
});
View File
@@ -13,21 +13,23 @@ const { go } = useRouter()
<HomeSectionTitle>Available For:</HomeSectionTitle>
<div class="packages-list">
<a
v-for="{ name, label, path, logo, logoDark } in data.packages"
:href="path"
v-for="{ name, logo, logoDark } in data.packages"
:href="`/guide/packages/${name}`"
class="package-logo"
@click.prevent="go(path)"
:aria-label="`Read more about: ${name} package`"
@click.prevent="go(`/guide/packages/${name}`)"
>
<img
:src="logo"
:class="{ light: logoDark, 'image-logo': true }"
:alt="label"
:alt="`${name} logo`"
loading="lazy"
/>
<img
v-if="logoDark"
:src="logoDark"
:alt="label"
:alt="`${name} logo`"
class="image-logo dark"
loading="lazy"
/>
@@ -3,7 +3,6 @@ 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'];
@@ -20,31 +19,6 @@ 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>
@@ -83,16 +57,6 @@ const base64InnerSvg = 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>
@@ -111,8 +75,6 @@ const base64InnerSvg = 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%;
@@ -123,34 +85,6 @@ const base64InnerSvg = 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);
@@ -44,12 +44,8 @@ function setActiveIconName(name: string) {
activeIconName.value = name;
}
const { execute: fetchTags, data: tags, isFetching: isFetchingTags } = useFetchTags();
const {
execute: fetchCategories,
data: categoriesMap,
isFetching: isFetchingCategories,
} = useFetchCategories();
const { execute: fetchTags, data: tags } = useFetchTags();
const { execute: fetchCategories, data: categoriesMap } = useFetchCategories();
const overviewEl = ref<HTMLElement | null>(null);
const { width: containerWidth } = useElementSize(overviewEl);
@@ -121,9 +117,6 @@ 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,
@@ -142,21 +135,15 @@ onMounted(() => {
useEventListener(window, 'scroll', containerProps.onScroll);
});
function loadSearchMetadata() {
if (tags.value == null && !isFetchingTags.value) {
void fetchTags();
function onFocusSearchInput() {
if (tags.value == null) {
fetchTags();
}
if (categoriesMap.value == null && !isFetchingCategories.value) {
void fetchCategories();
if (categoriesMap.value == null) {
fetchCategories();
}
}
watch(searchQuery, (searchString) => {
if (searchString !== '') {
loadSearchMetadata();
}
});
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
@@ -191,11 +178,11 @@ function handleCloseDrawer() {
:shortcut="kbdSearchShortcut"
class="input-wrapper"
ref="searchInput"
@focus="loadSearchMetadata"
@focus="onFocusSearchInput"
/>
</StickyBar>
<NoResults
v-if="searchPlaceholder.isNoResults && !isSearchMetadataLoading"
v-if="searchPlaceholder.isNoResults"
:searchQuery="searchPlaceholder.query"
:isBrandSearch="searchPlaceholder.isBrand"
@clear="searchQuery = ''"
@@ -52,12 +52,8 @@ const props = defineProps<{
const activeIconName = ref(null);
const selectedSort = ref(SORTING[0])
const { execute: fetchTags, data: tags, isFetching: isFetchingTags } = useFetchTags();
const {
execute: fetchCategories,
data: categories,
isFetching: isFetchingCategories,
} = useFetchCategories();
const { execute: fetchTags, data: tags } = useFetchTags();
const { execute: fetchCategories, data: categories } = useFetchCategories();
const overviewEl = ref<HTMLElement | null>(null);
const { width: containerWidth } = useElementSize(overviewEl);
@@ -114,9 +110,6 @@ const searchResults = useSearch(searchQueryDebounced, mappedIcons, [
]);
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);
@@ -142,21 +135,15 @@ function setActiveIconName(name: string) {
activeIconName.value = name;
}
function loadSearchMetadata() {
if (tags.value == null && !isFetchingTags.value) {
void fetchTags();
function onFocusSearchInput() {
if (tags.value == null) {
fetchTags();
}
if (categories.value == null && !isFetchingCategories.value) {
void fetchCategories();
if (categories.value == null) {
fetchCategories();
}
}
watch(searchQuery, (searchString) => {
if (searchString !== '') {
loadSearchMetadata();
}
});
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
@@ -192,7 +179,7 @@ function handleCloseDrawer() {
ref="searchInput"
:shortcut="kbdSearchShortcut"
class="input-wrapper"
@focus="loadSearchMetadata"
@focus="onFocusSearchInput"
/>
<Select
@@ -210,7 +197,7 @@ function handleCloseDrawer() {
</Select>
</StickyBar>
<NoResults
v-if="searchPlaceholder.isNoResults && !isSearchMetadataLoading"
v-if="searchPlaceholder.isNoResults"
:searchQuery="searchPlaceholder.query"
:isBrandSearch="searchPlaceholder.isBrand"
@clear="searchQuery = ''"
@@ -16,7 +16,7 @@ export const externalLibContext = {
};
const externalLibIconNodesAPI = {
lab: `${import.meta.env.DEV ? 'http://localhost:3000' : ''}/api/lab/icon-details`,
lab: 'https://lab.lucide.dev/api/icon-details',
};
export function useExternalLibs(): ExternalLibContext {
@@ -32,15 +32,13 @@ export function useExternalLibs(): ExternalLibContext {
newExternalIconNodes[lib] = savedIconNodes[lib];
} else {
const response = await fetch(externalLibIconNodesAPI[lib]);
const iconDetails = await response.json();
const iconNodes = await response.json();
if (iconDetails) {
newExternalIconNodes[lib] = Object.values(iconDetails).map((iconEntity: IconEntity) => {
return {
...iconEntity,
externalLibrary: lib,
};
});
if (iconNodes) {
newExternalIconNodes[lib] = Object.values(iconNodes).map((iconEntity: IconEntity) => ({
...iconEntity,
externalLibrary: lib,
}));
}
}
}
+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/?utm_source=lucide.dev&utm_medium=design-guide) to tidy paths to 3 points of precision.
We recommend to use [Lucide Studio](https://studio.lucide.dev/) to tidy paths to 3 points of precision.
### Allowed elements
@@ -12,10 +12,6 @@ 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"}
+17 -19
View File
@@ -1,26 +1,24 @@
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';
import { IconEntity } from '../../.vitepress/theme/types';
export default {
paths: async () => {
return (Object.entries(iconNodes) as unknown as IconEntity[]).map(([name, iconNode]) => {
const iconDetails = iconMetaData[name];
try {
const iconDetailsResponse = await fetch('https://lab.lucide.dev/api/icon-details');
const iconDetails = (await iconDetailsResponse.json()) as Record<string, IconEntity>;
delete iconDetails['$schema'];
return Object.values(iconDetails).map((iconEntity) => {
const params = {
externalLibrary: 'lab',
...iconEntity,
};
const params = {
name,
iconNode,
externalLibrary: 'lab',
popularity: iconPopularity[name]?.count ?? 0,
...iconDetails,
};
return {
params,
};
});
return {
params,
};
});
} catch (error) {
console.error('Error fetching icon details:', error);
return [];
}
},
};
+23 -26
View File
@@ -8,21 +8,19 @@
"docs:dev": "pnpm run /^prebuild:.*/ && vitepress dev",
"docs:build": "pnpm run /^prebuild:.*/ && vitepress build",
"docs:preview": "vitepress preview",
"build:docs": "NODE_OPTIONS=--max-old-space-size=8192 vitepress build",
"build:docs": "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:iconPopularity": "node ./scripts/writeiconPopularity.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",
"dev": "npx nitropack dev",
"prebuild:api": "npx nitropack prepare",
"build:api": "npx nitropack build",
"build": "pnpm run /^prebuild:.*/ && pnpm run build:api && pnpm run build:docs && pnpm postbuild:vercelJson",
"preview": "node .output/server/index.mjs"
},
@@ -34,32 +32,31 @@
"@lucide/shared": "workspace:*",
"@rollup/plugin-replace": "^6.0.3",
"@types/semver": "^7.7.1",
"h3": "^1.15.11",
"markdown-it": "^14.3.0",
"markdown-it-container": "^4.0.0",
"h3": "^1.15.9",
"nitropack": "^2.13.4",
"rollup-plugin-copy": "^3.5.0",
"semver": "^7.8.5",
"sharp": "^0.34.5",
"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",
"svg-path-commander": "^2.1.11",
"vitepress": "^1.6.4",
"vitepress-plugin-group-icons": "^1.7.5",
"vitepress-plugin-llms": "^1.13.3"
"vitepress-plugin-group-icons": "^1.6.5",
"vitepress-plugin-llms": "^1.11.1",
"markdown-it": "^14.2.0",
"markdown-it-container": "^4.0.0",
"semver": "^7.7.3",
"sharp": "^0.34.5",
"shiki": "^3.15.0",
"simple-git": "^3.36.0",
"sitemap": "^7.1.2",
"svg-pathdata": "^6.0.3",
"svgson": "^5.3.1"
},
"dependencies": {
"@floating-ui/vue": "^1.1.11",
"@floating-ui/vue": "^1.1.9",
"@headlessui/vue": "^1.7.23",
"@lucide/vue": "workspace:*",
"@vueuse/components": "^14.3.0",
"@vueuse/core": "^14.3.0",
"@vueuse/integrations": "^14.3.0",
"@vueuse/components": "^14.0.0",
"@vueuse/core": "^14.0.0",
"element-to-path": "^1.2.1",
"fuse.js": "^7.5.0",
"fuse.js": "^7.1.0",
"jszip": "^3.10.1",
"lodash-es": "^4.18.1",
"lucide": "workspace:*",
@@ -68,6 +65,6 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"sandpack-vue3": "3.1.12",
"vue": "^3.5.39"
"vue": "^3.5.24"
}
}
+7 -7
View File
@@ -23,12 +23,12 @@ const writeIconFiles = icons.map(async (iconFileName) => {
const location = path.resolve(iconDetailsDirectory, `${iconName}.ts`);
const contents = `\
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' };
import iconNode from '../iconNodes/${iconName}.node.json'
import metaData from '../../../../icons/${iconName}.json'
import releaseData from '../releaseMetadata/${iconName}.json'
import popularity from '../iconPopularity/${iconName}.json'
const { tags, categories, contributors, aliases, deprecated, deprecationReason, toBeRemovedInVersion } = metaData;
const { tags, categories, contributors, aliases, deprecated, deprecationReason, toBeRemovedInVersion } = metaData
const iconDetails = {
name: '${iconName}',
@@ -42,9 +42,9 @@ const iconDetails = {
deprecationReason,
toBeRemovedInVersion,
...releaseData,
};
}
export default iconDetails;
export default iconDetails
`;
await fs.promises.writeFile(location, contents, 'utf-8');
-49
View File
@@ -1,49 +0,0 @@
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
@@ -1,62 +0,0 @@
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}`);
}
+28 -76
View File
@@ -5,59 +5,27 @@ import { loadEnvFile } from 'node:process';
import { readSvgDirectory } from '@lucide/helpers';
const currentDir = process.cwd();
const dataDirectory = path.resolve(currentDir, '.vitepress/data');
const ICONS_DIR = path.resolve(currentDir, '../icons');
const iconPopularityDirectory = path.resolve(currentDir, '.vitepress/data', 'iconPopularity');
try {
// Load environment variables from .env file, if it exists.
loadEnvFile(`${currentDir}/.env`);
} catch (error) {}
interface IconCollection {
/** Human readable name, used for logging. */
name: string;
/** Directory containing the icon `.json` files. */
iconsDir: string;
/** Directory the `${iconName}.json` popularity files are written to. */
outputDir: string;
/** Matches an analytics route and captures the icon name in group 1. */
routePattern: RegExp;
if (fs.existsSync(iconPopularityDirectory)) {
fs.rmSync(iconPopularityDirectory, { recursive: true, force: true });
}
// Lab must come before the default collection because `/icons/lab/foo` also
// matches the default `/icons/(...)` pattern; the first match wins per route.
const iconCollections: IconCollection[] = [
{
name: 'lab',
iconsDir: path.resolve(currentDir, '../lab'),
outputDir: path.resolve(dataDirectory, 'lab', 'iconPopularity'),
// e.g. /icons/lab/burger, /icons/lab/burger/ or /icons/lab/burger?ref=homepage
routePattern: /^\/icons\/lab\/([^\/\?]+)(?:[\/\?]|$)/,
},
{
name: 'default',
iconsDir: path.resolve(currentDir, '../icons'),
outputDir: path.resolve(dataDirectory, 'iconPopularity'),
// e.g. /icons/activity, /icons/activity/ or /icons/activity?ref=homepage
routePattern: /^\/icons\/([^\/\?]+)(?:[\/\?]|$)/,
},
];
interface CollectionData extends IconCollection {
iconNames: string[];
counts: Record<string, number>;
if (!fs.existsSync(iconPopularityDirectory)) {
fs.mkdirSync(iconPopularityDirectory);
}
const collections: CollectionData[] = await Promise.all(
iconCollections.map(async (collection) => {
const iconJsonFiles = await readSvgDirectory(collection.iconsDir, '.json');
const iconNames = iconJsonFiles.map((file) => path.basename(file, '.json'));
const iconJsonFiles = await readSvgDirectory(ICONS_DIR, '.json');
const iconNames = iconJsonFiles.map((file) => path.basename(file, '.json'));
return {
...collection,
iconNames,
counts: Object.fromEntries(iconNames.map((iconName) => [iconName, 0])),
};
}),
const defaultIconNamePopularity: Record<string, number> = Object.fromEntries(
iconNames.map((iconName) => [iconName, 0])
);
interface AnalyticsResponse {
@@ -67,30 +35,19 @@ interface AnalyticsResponse {
}[];
}
const writeIconPopularity = async ({ name, outputDir, counts }: CollectionData) => {
if (fs.existsSync(outputDir)) {
fs.rmSync(outputDir, { recursive: true, force: true });
}
fs.mkdirSync(outputDir, { recursive: true });
const writePopularityPromises = Object.entries(counts).map(([iconName, count]) => {
const location = path.resolve(outputDir, `${iconName}.json`);
const writeIconPopularity = async (iconVisitCounts: Record<string, number>) => {
const writePopularityPromises = Object.entries(iconVisitCounts).map(([iconName, count]) => {
const location = path.resolve(iconPopularityDirectory, `${iconName}.json`);
return fs.promises.writeFile(location, JSON.stringify({ count }, null, 2), 'utf-8');
});
await Promise.all(writePopularityPromises);
console.log(
'Successfully written icon popularity data for',
writePopularityPromises.length,
`${name} icons.`,
);
console.log('Successfully written icon popularity data for', writePopularityPromises.length, 'icons.');
};
const writeAllIconPopularity = () => Promise.all(collections.map(writeIconPopularity));
if (process.env.LUCIDE_ANALYTICS_TOKEN === undefined) {
console.warn('LUCIDE_ANALYTICS_TOKEN environment variable is not set. Writing default icon popularity data.');
await writeAllIconPopularity();
await writeIconPopularity(defaultIconNamePopularity);
process.exit(0);
}
@@ -119,34 +76,29 @@ try {
const analyticsData: AnalyticsResponse = await response.json();
for (const { dimensions, metrics } of analyticsData.results) {
const iconVisitCounts = analyticsData.results.reduce((acc, { dimensions, metrics }) => {
const [route] = dimensions;
const [count] = metrics;
if (!route.startsWith('/icons')) {
continue;
return acc
}
// Route each visit to the first collection whose pattern matches. Lab is
// checked first so `/icons/lab/foo` is not swallowed by the default pattern.
for (const collection of collections) {
const match = route.match(collection.routePattern);
if (!match) {
continue;
}
// Only match routes that start with /icons/ and end with an icon name, e.g. /icons/activity, /icons/activity/ or /icons/activity?ref=homepage
const match = route.match(/^\/icons\/([^\/\?]+)(?:[\/\?]|$)/);
if (match) {
const iconName = match[1];
if (collection.iconNames.includes(iconName)) {
collection.counts[iconName] += count;
if (iconNames.includes(iconName)) {
acc[iconName] = (acc[iconName] || 0) + count;
}
break;
}
}
await writeAllIconPopularity();
return acc;
}, defaultIconNamePopularity);
await writeIconPopularity(iconVisitCounts);
} catch (error) {
console.error('Error fetching analytics data:', error);
await writeAllIconPopularity();
await writeIconPopularity(defaultIconNamePopularity);
}
-49
View File
@@ -1,49 +0,0 @@
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 labIconPopularityDirectory = path.resolve(currentDir, '.vitepress/data/lab/iconPopularity');
const location = path.resolve(currentDir, labIconPopularityDirectory, 'index.ts');
if (fs.existsSync(location)) {
fs.unlinkSync(location);
}
if (!fs.existsSync(labIconPopularityDirectory)) {
fs.mkdirSync(labIconPopularityDirectory);
}
const iconMetaIndexFileImports = [];
const iconMetaIndexFileExports = [];
iconJsonFiles.forEach((iconJsonFile) => {
const iconName = path.basename(iconJsonFile, '.json');
iconMetaIndexFileImports.push(
`import ${toCamelCase(iconName)}Popularity from './${iconName}.json' with { type: 'json' };`,
);
iconMetaIndexFileExports.push(` '${iconName}': ${toCamelCase(iconName)}Popularity,`);
});
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}`);
}
+1 -1
View File
@@ -13,4 +13,4 @@
<path d="M15.697 14h5.606" />
<path d="m2 16 4.039-9.69a.5.5 0 0 1 .923 0L11 16" />
<path d="M3.304 13h6.392" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 391 B

After

Width:  |  Height:  |  Size: 390 B

+1 -6
View File
@@ -21,15 +21,10 @@
"paid",
"partner",
"promo",
"sponsor",
"audio description",
"video description",
"described video",
"visual description"
"sponsor"
],
"categories": [
"multimedia",
"accessibility",
"notifications"
]
}
+3 -2
View File
@@ -11,9 +11,10 @@
>
<path d="M10 10H6" />
<path d="M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2" />
<path d="M19 18h2a1 1 0 0 0 1-1v-3.28a1 1 0 0 0-.684-.948l-1.923-.641a1 1 0 0 1-.578-.502l-1.539-3.076A1 1 0 0 0 16.382 8H14" />
<path
d="M19 18h2a1 1 0 0 0 1-1v-3.28a1 1 0 0 0-.684-.948l-1.923-.641a1 1 0 0 1-.578-.502l-1.539-3.076A1 1 0 0 0 16.382 8H14" />
<path d="M8 8v4" />
<path d="M9 18h6" />
<circle cx="17" cy="18" r="2" />
<circle cx="7" cy="18" r="2" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 550 B

After

Width:  |  Height:  |  Size: 553 B

+5 -5
View File
@@ -9,9 +9,9 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M10 3a41 41 0 000 18" />
<path d="M14 3a41 41 0 010 18" />
<path d="M16.997 21a2 2 0 001.68-.92 15.25 15.25 0 000-16.16 2 2 0 00-1.68-.92h-10a2 2 0 00-1.681.92 15.25 15.25 0 000 16.16 2 2 0 001.681.92z" />
<path d="M3.54 16h16.914" />
<path d="M3.54 8h16.914" />
<path d="M10 3a41 41 0 0 0 0 18" />
<path d="M14 3a41 41 0 0 1 0 18" />
<path d="M17 3a2 2 0 0 1 1.68.92 15.25 15.25 0 0 1 0 16.16A2 2 0 0 1 17 21H7a2 2 0 0 1-1.68-.92 15.25 15.25 0 0 1 0-16.16A2 2 0 0 1 7 3z" />
<path d="M3.84 17h16.32" />
<path d="M3.84 7h16.32" />
</svg>

Before

Width:  |  Height:  |  Size: 490 B

After

Width:  |  Height:  |  Size: 486 B

+1 -1
View File
@@ -15,4 +15,4 @@
<path d="m4 8 2 1" />
<path d="m8 4 1 2" />
<path d="M9.698 14.19a.15.15 0 0 0 .112.112l2.074.489a.15.15 0 0 1 .072.252L10 17c-.7.7 0 1.69 0 2.5a1 1 0 0 1-5 0 .495.495 0 0 0-.5-.5 1 1 0 0 1 0-5c.81 0 1.8.7 2.5 0l1.956-1.957a.15.15 0 0 1 .252.072z" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 733 B

After

Width:  |  Height:  |  Size: 732 B

+2 -2
View File
@@ -9,7 +9,7 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 5v16" />
<path d="M12 21V7" />
<path d="m16 12 2 2 4-4" />
<path d="M22 6V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2h4.001A2 2 0 0022 17v-1.344" />
<path d="M22 6V4a1 1 0 0 0-1-1h-5a4 4 0 0 0-4 4 4 4 0 0 0-4-4H3a1 1 0 0 0-1 1v13a1 1 0 0 0 1 1h6a3 3 0 0 1 3 3 3 3 0 0 1 3-3h6a1 1 0 0 0 1-1v-1.3" />
</svg>

Before

Width:  |  Height:  |  Size: 424 B

After

Width:  |  Height:  |  Size: 414 B

+1 -2
View File
@@ -1,8 +1,7 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"danielbayley",
"karsa-mistmere"
"danielbayley"
],
"use-cases": [],
"tags": [
+6 -6
View File
@@ -9,10 +9,10 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 5v16" />
<path d="M16 13h2" />
<path d="M16 9h2" />
<path d="M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z" />
<path d="M6 13h2" />
<path d="M6 9h2" />
<path d="M12 7v14" />
<path d="M16 12h2" />
<path d="M16 8h2" />
<path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" />
<path d="M6 12h2" />
<path d="M6 8h2" />
</svg>

Before

Width:  |  Height:  |  Size: 479 B

After

Width:  |  Height:  |  Size: 470 B

+1 -2
View File
@@ -3,8 +3,7 @@
"contributors": [
"colebemis",
"csandman",
"ericfennis",
"karsa-mistmere"
"ericfennis"
],
"use-cases": [],
"tags": [
+2 -2
View File
@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 5v16" />
<path d="M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z" />
<path d="M12 7v14" />
<path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" />
</svg>

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 378 B

+1 -1
View File
@@ -16,4 +16,4 @@
<path d="M8 8H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 1.414-.586" />
<path d="M9 13v2" />
<path d="M9.67 4H12v2.33" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 457 B

After

Width:  |  Height:  |  Size: 456 B

+1 -1
View File
@@ -11,4 +11,4 @@
>
<rect width="18" height="14" x="3" y="5" rx="2" ry="2" />
<path d="M7 15h4M15 15h2M7 11h2M13 11h4" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 314 B

After

Width:  |  Height:  |  Size: 313 B

+3 -12
View File
@@ -7,18 +7,9 @@
],
"use-cases": [],
"tags": [
"stream",
"streaming",
"screen",
"display",
"wireless",
"broadcast",
"transmit",
"media",
"receiver",
"remote display",
"screen sharing",
"media streaming"
"chromecast",
"airplay",
"screen"
],
"categories": [
"devices",
+4
View File
@@ -8,6 +8,10 @@
"tags": [
"stories",
"social media",
"instagram",
"facebook",
"meta",
"snapchat",
"sharing",
"content"
],
+1 -1
View File
@@ -16,4 +16,4 @@
<path d="M2.83 16a10 10 0 0 0 2.43 3.4" />
<path d="M4.636 5.235a10 10 0 0 1 .891-.857" />
<path d="M8.644 21.42a10 10 0 0 0 7.631-.38" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 487 B

After

Width:  |  Height:  |  Size: 486 B

+1 -2
View File
@@ -3,8 +3,7 @@
"contributors": [
"irvineacosta",
"danielbayley",
"karsa-mistmere",
"kamilasw"
"karsa-mistmere"
],
"use-cases": [],
"tags": [
+11 -11
View File
@@ -9,16 +9,16 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M10.6 21H5a2 2 0 01-2-2V5a2 2 0 012-2h14a2 2 0 012 2v5.6" />
<path d="m14.305 19.53.923-.382" />
<path d="M15 3v7.6" />
<path d="m15.229 16.852-.924-.383" />
<path d="m16.852 15.228-.383-.923" />
<path d="m16.852 20.772-.383.924" />
<path d="m19.148 15.228.383-.923" />
<path d="m19.53 21.696-.382-.924" />
<path d="m20.773 16.852.922-.383" />
<path d="m20.773 19.148.922.383" />
<path d="M10.5 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v5.5" />
<path d="m14.3 19.6 1-.4" />
<path d="M15 3v7.5" />
<path d="m15.2 16.9-.9-.3" />
<path d="m16.6 21.7.3-.9" />
<path d="m16.8 15.3-.4-1" />
<path d="m19.1 15.2.3-.9" />
<path d="m19.6 21.7-.4-1" />
<path d="m20.7 16.8 1-.4" />
<path d="m21.7 19.4-.9-.3" />
<path d="M9 3v18" />
<circle cx="18" cy="18" r="3" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 675 B

After

Width:  |  Height:  |  Size: 617 B

+1
View File
@@ -11,6 +11,7 @@
"east",
"south",
"west",
"safari",
"browser"
],
"categories": [
+2 -1
View File
@@ -7,7 +7,8 @@
"tags": [
"pc",
"chassis",
"codespaces"
"codespaces",
"github"
],
"categories": [
"devices",
+1
View File
@@ -9,6 +9,7 @@
"shipping",
"freight",
"supply chain",
"docker",
"environment",
"devops",
"code",
+1 -1
View File
@@ -11,4 +11,4 @@
>
<path d="M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41L13.7 2.71a2.41 2.41 0 0 0-3.41 0z" />
<path d="M8 12h8" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 379 B

After

Width:  |  Height:  |  Size: 378 B

+1 -1
View File
@@ -12,4 +12,4 @@
<path d="M12 8v8" />
<path d="M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41L13.7 2.71a2.41 2.41 0 0 0-3.41 0z" />
<path d="M8 12h8" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 402 B

After

Width:  |  Height:  |  Size: 401 B

+1 -2
View File
@@ -1,8 +1,7 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"ericfennis",
"karsa-mistmere"
"ericfennis"
],
"use-cases": [],
"tags": [
+2 -2
View File
@@ -9,9 +9,9 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m15 20 3-3h2a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h2l3 3z" />
<path d="M6 8v1" />
<path d="M10 8v1" />
<path d="M14 8v1" />
<path d="M18 8v1" />
<path d="M19 17a2 2 0 00-1.765 1.059l-.47.882A2 2 0 0115 20H9a2 2 0 01-1.765-1.059l-.47-.882A2 2 0 005 17H4a2 2 0 01-2-2V6a2 2 0 012-2h16a2 2 0 012 2v9a2 2 0 01-2 2z" />
<path d="M6 8v1" />
</svg>

Before

Width:  |  Height:  |  Size: 471 B

After

Width:  |  Height:  |  Size: 396 B

+4 -24
View File
@@ -3,33 +3,13 @@
"contributors": [
"colebemis",
"csandman",
"ericfennis",
"karsa-mistmere"
],
"use-cases": [
"Representing writing, authorship, or creative composition",
"Representing literature, poetry, publishing, or editorial content",
"Representing quills, manuscripts, or historical writing",
"Representing birds, plumage, wildlife, or nature",
"Representing lightness, softness, delicacy, or weight"
"ericfennis"
],
"use-cases": [],
"tags": [
"quill",
"plume",
"writing",
"author",
"literature",
"poetry",
"manuscript",
"bird",
"plumage",
"lightweight",
"soft"
"logo"
],
"categories": [
"nature",
"animals",
"gaming",
"text"
"gaming"
]
}
+2 -2
View File
@@ -9,7 +9,7 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M14.086 18.412A2 2 0 0112.67 19H5v-7.672a2 2 0 01.586-1.414L11.75 3.75a6 6 0 118.49 8.49z" />
<path d="M12.67 19a2 2 0 0 0 1.416-.588l6.154-6.172a6 6 0 0 0-8.49-8.49L5.586 9.914A2 2 0 0 0 5 11.328V18a1 1 0 0 0 1 1z" />
<path d="M16 8 2 22" />
<path d="M17.488 15H9" />
<path d="M17.5 15H9" />
</svg>

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 387 B

+3 -26
View File
@@ -4,36 +4,13 @@
"karsa-mistmere",
"danielbayley"
],
"use-cases": [
"representing 3D model files such as OBJ, STL, FBX, or GLTF",
"indicating CAD and engineering model documents",
"showing printable or manufacturable 3D assets",
"identifying files containing digital product models"
],
"use-cases": [],
"tags": [
"document",
"page",
"sheet",
"cube",
"box",
"3d",
"model",
"asset",
"object",
"geometry",
"mesh",
"ar",
"augmented reality",
"cad",
"design",
"blueprint",
"draft",
"package",
"scene"
"model"
],
"categories": [
"files",
"design",
"development"
"files"
]
}
+5 -5
View File
@@ -9,9 +9,9 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M14 2v5a1 1 0 001 1h5" />
<path d="M14.692 22H18a2 2 0 002-2V8a2.4 2.4 0 00-.706-1.706l-3.588-3.588A2.4 2.4 0 0014 2H6a2 2 0 00-2 2v3.804" />
<path d="M2.264 13.752 7 16.5l4.737-2.748" />
<path d="M2.995 13.014A2 2 0 002 14.744v3.516a2 2 0 00.996 1.73l3 1.74a2 2 0 002.008 0l3-1.74A2 2 0 0012 18.26v-3.517a2 2 0 00-.995-1.73l-3-1.742a2 2 0 00-1.892-.064z" />
<path d="M7 16.5V22" />
<path d="M14.5 22H18a2 2 0 0 0 2-2V8a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 14 2H6a2 2 0 0 0-2 2v3.8" />
<path d="M14 2v5a1 1 0 0 0 1 1h5" />
<path d="M11.7 14.2 7 17l-4.7-2.8" />
<path d="M3 13.1a2 2 0 0 0-.999 1.76v3.24a2 2 0 0 0 .969 1.78L6 21.7a2 2 0 0 0 2.03.01L11 19.9a2 2 0 0 0 1-1.76V14.9a2 2 0 0 0-.97-1.78L8 11.3a2 2 0 0 0-2.03-.01z" />
<path d="M7 17v5" />
</svg>

Before

Width:  |  Height:  |  Size: 610 B

After

Width:  |  Height:  |  Size: 599 B

+1 -1
View File
@@ -10,4 +10,4 @@
stroke-linejoin="round"
>
<path d="M18 22V2.8a.8.8 0 0 0-1.17-.71L5.45 7.78a.8.8 0 0 0 0 1.44L18 15.5" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 289 B

+8 -4
View File
@@ -9,8 +9,12 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M11.146 15.854a1.207 1.207 0 0 1 1.708 0l1.56 1.56A2 2 0 0 1 15 18.828V21a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1v-2.172a2 2 0 0 1 .586-1.414z" />
<path d="M18.828 15a2 2 0 0 1-1.414-.586l-1.56-1.56a1.207 1.207 0 0 1 0-1.708l1.56-1.56A2 2 0 0 1 18.828 9H21a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1z" />
<path d="M6.586 14.414A2 2 0 0 1 5.172 15H3a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h2.172a2 2 0 0 1 1.414.586l1.56 1.56a1.207 1.207 0 0 1 0 1.708z" />
<path d="M9 3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2.172a2 2 0 0 1-.586 1.414l-1.56 1.56a1.207 1.207 0 0 1-1.708 0l-1.56-1.56A2 2 0 0 1 9 5.172z" />
<path
d="M11.146 15.854a1.207 1.207 0 0 1 1.708 0l1.56 1.56A2 2 0 0 1 15 18.828V21a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1v-2.172a2 2 0 0 1 .586-1.414z" />
<path
d="M18.828 15a2 2 0 0 1-1.414-.586l-1.56-1.56a1.207 1.207 0 0 1 0-1.708l1.56-1.56A2 2 0 0 1 18.828 9H21a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1z" />
<path
d="M6.586 14.414A2 2 0 0 1 5.172 15H3a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h2.172a2 2 0 0 1 1.414.586l1.56 1.56a1.207 1.207 0 0 1 0 1.708z" />
<path
d="M9 3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2.172a2 2 0 0 1-.586 1.414l-1.56 1.56a1.207 1.207 0 0 1-1.708 0l-1.56-1.56A2 2 0 0 1 9 5.172z" />
</svg>

Before

Width:  |  Height:  |  Size: 792 B

After

Width:  |  Height:  |  Size: 808 B

+1 -1
View File
@@ -14,4 +14,4 @@
<path d="M9 3 3 9" />
<path d="M9 9 3 3" />
<circle cx="18" cy="18" r="3" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 353 B

After

Width:  |  Height:  |  Size: 352 B

+1 -2
View File
@@ -1,8 +1,7 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"danielbayley",
"karsa-mistmere"
"danielbayley"
],
"use-cases": [],
"tags": [
+2 -2
View File
@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M22 9a1 1 0 00-1-1H3a1 1 0 00-1 1v4a1 1 0 001 1h.5a2 2 0 011.6.8l.3.4A2 2 0 007 16h10a2 2 0 001.6-.8l.3-.4a2 2 0 011.6-.8h.5a1 1 0 001-1z" />
<path d="M8 12h8" />
<path d="M22 9a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1h1l2 2h12l2-2h1a1 1 0 0 0 1-1Z" />
<path d="M7.5 12h9" />
</svg>

Before

Width:  |  Height:  |  Size: 384 B

After

Width:  |  Height:  |  Size: 330 B

+26
View File
@@ -0,0 +1,26 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"ericfennis",
"danielbayley",
"jguddas",
"karsa-mistmere"
],
"use-cases": [],
"tags": [
"time",
"redo",
"undo",
"rewind",
"timeline",
"version",
"time machine",
"backup",
"rotate",
"ccw"
],
"categories": [
"arrows",
"time"
]
}

Before

Width:  |  Height:  |  Size: 324 B

After

Width:  |  Height:  |  Size: 324 B

+1 -1
View File
@@ -14,4 +14,4 @@
<path d="M16.899 22A5 5 0 0 0 7.1 22" />
<path d="m9 2 3 6" />
<circle cx="12" cy="15" r="3" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 428 B

After

Width:  |  Height:  |  Size: 427 B

+1 -1
View File
@@ -19,4 +19,4 @@
<path d="M20 20H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2" />
<path d="M6 8h.01" />
<path d="M8 12h.01" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 519 B

After

Width:  |  Height:  |  Size: 518 B

+1 -1
View File
@@ -14,4 +14,4 @@
<path d="M19 14v6" />
<path d="M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 .825.178" />
<path d="M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l2.116-.962" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 540 B

After

Width:  |  Height:  |  Size: 539 B

-31
View File
@@ -1,31 +0,0 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"samuelalake"
],
"use-cases": [
"turning off auto layout in a design inspector",
"switching a dashboard section to free drag-and-drop placement",
"selecting freeform arrangement in a page builder",
"indicating unstructured layout mode in a whiteboard or canvas app",
"representing elements not aligned to a grid"
],
"tags": [
"layout",
"freeform",
"free",
"absolute",
"position",
"auto layout",
"unaligned",
"scattered",
"arrange",
"blocks",
"canvas",
"frame"
],
"categories": [
"design",
"layout"
]
}
-15
View File
@@ -1,15 +0,0 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect width="7" height="7" x="3" y="3" rx="1" />
<rect width="7" height="7" x="14" y="4" rx="1" />
<rect width="7" height="7" x="4" y="14" rx="1" />
</svg>

Before

Width:  |  Height:  |  Size: 363 B

+2 -1
View File
@@ -9,5 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M13.433 2a1 1 0 0 1 .824.448 18 18 0 0 1 0 19.104 1 1 0 0 1-.824.448h-2.866a1 1 0 0 1-.824-.448 18 18 0 0 1 0-19.104A1 1 0 0 1 10.567 2z" />
<path
d="M13.433 2a1 1 0 0 1 .824.448 18 18 0 0 1 0 19.104 1 1 0 0 1-.824.448h-2.866a1 1 0 0 1-.824-.448 18 18 0 0 1 0-19.104A1 1 0 0 1 10.567 2z" />
</svg>

Before

Width:  |  Height:  |  Size: 360 B

After

Width:  |  Height:  |  Size: 364 B

+1 -1
View File
@@ -10,4 +10,4 @@
stroke-linejoin="round"
>
<path d="M7 3.5c5-2 7 2.5 3 4C1.5 10 2 15 5 16c5 2 9-10 14-7s.5 13.5-4 12c-5-2.5.5-11 6-2" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 303 B

-36
View File
@@ -1,36 +0,0 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"karsa-mistmere",
"jguddas"
],
"use-cases": [
"representing recorded speech with visible audio activity",
"indicating podcast, voice note, or narration recording tools",
"showing voice input for transcription, dictation, or AI assistants",
"marking features that analyze, clean up, or enhance microphone audio",
"identifying controls for speech capture and sound processing workflows"
],
"tags": [
"podcast",
"audio",
"waveform",
"sound waves",
"microphone",
"talk",
"voice",
"speech",
"stream",
"recording",
"transcription",
"dictation",
"voice assistant",
"noise cancellation",
"sound processing"
],
"categories": [
"devices",
"communication",
"multimedia"
]
}
-21
View File
@@ -1,21 +0,0 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M10 3v2.341" />
<path d="M12 17v4" />
<path d="M14 5v.341" />
<path d="M18 5v13" />
<path d="M2 10v3" />
<path d="M22 10v3" />
<path d="M6 6v11" />
<path d="M9 21h6" />
<rect width="4" height="8" x="10" y="9" rx="2" />
</svg>

Before

Width:  |  Height:  |  Size: 454 B

-46
View File
@@ -1,46 +0,0 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"karsa-mistmere",
"jguddas"
],
"use-cases": [
"representing a microphone actively broadcasting or transmitting voice",
"indicating live podcast, radio, streaming, or voice channel features",
"showing wireless microphone connections or remote audio capture",
"marking push-to-talk, voice chat, or walkie-talkie communication controls",
"identifying features that send spoken audio across a network or airwaves"
],
"tags": [
"podcast",
"audio",
"broadcast",
"signal",
"wireless",
"radio",
"airwaves",
"microphone",
"talk",
"voice",
"speech",
"stream",
"live",
"voice chat",
"push to talk",
"transmission"
],
"categories": [
"devices",
"communication",
"connectivity",
"multimedia"
],
"aliases": [
{
"name": "podcast",
"deprecated": true,
"deprecationReason": "alias.name",
"toBeRemovedInVersion": "v1.0"
}
]
}
-19
View File
@@ -1,19 +0,0 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 17v4" />
<path d="M18 11a6 6 0 00-3-5.197" />
<path d="M2 11a10 10 0 015-8.662" />
<path d="M22 11a10 10 0 00-5-8.662" />
<path d="M6 11a6 6 0 013-5.197" />
<path d="M9 21h6" />
<rect x="10" y="9" width="4" height="8" rx="2" />
</svg>

Before

Width:  |  Height:  |  Size: 463 B

+1 -1
View File
@@ -12,4 +12,4 @@
<path d="M11 6 8 9" />
<path d="m16 7-8 8" />
<rect x="4" y="2" width="16" height="20" rx="2" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 311 B

After

Width:  |  Height:  |  Size: 310 B

+1 -1
View File
@@ -14,4 +14,4 @@
<path d="M15 7.5 9.5 13" />
<path d="M7 22h10" />
<circle cx="12" cy="10" r="8" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 350 B

After

Width:  |  Height:  |  Size: 349 B

-40
View File
@@ -1,40 +0,0 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"rrod497",
"iskepr"
],
"use-cases": [
"Representing a mosque as a building type or place of worship",
"Categorizing religious and spiritual points of interest on a map"
],
"tags": [
"mosque",
"masjid",
"islam",
"muslim",
"ramadan",
"eid",
"prayer",
"worship",
"building",
"minaret",
"dome",
"architecture",
"faith",
"religion",
"holy",
"sacred",
"landmark",
"community",
"spiritual",
"tourism",
"map",
"heritage"
],
"categories": [
"buildings",
"navigation",
"travel"
]
}
-18
View File
@@ -1,18 +0,0 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12.268 2a2 2 0 003.465 2" />
<path d="M14 5 L14 8" />
<path d="M16 22v-3a2 2 0 00-4 0v3" />
<path d="M21 13c-.662-1.497-1.666-2.753-2.9-3.63C16.825 8.47 15.422 8 14 8s-2.826.47-4.1 1.37C8.668 10.248 7.663 11.504 7 13z" />
<path d="M3 9h4" />
<path d="M7 22V6a5 5 0 00-2-4 5 5 0 00-2 4v14a2 2 0 002 2h14a2 2 0 002-2v-7" />
</svg>

Before

Width:  |  Height:  |  Size: 552 B

+1 -1
View File
@@ -14,4 +14,4 @@
<path d="M14 3v11" />
<path d="m18 14 4 4H2" />
<path d="m22 18-4 4" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 349 B

After

Width:  |  Height:  |  Size: 348 B

+24
View File
@@ -0,0 +1,24 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"iiaishwarya",
"ericfennis",
"karsa-mistmere",
"jguddas"
],
"use-cases": [],
"tags": [
"audio",
"music",
"mic",
"talk",
"voice",
"subscribe",
"subscription",
"stream"
],
"categories": [
"multimedia",
"social"
]
}
+16
View File
@@ -0,0 +1,16 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M13 17a1 1 0 1 0-2 0l.5 4.5a0.5 0.5 0 0 0 1 0z" fill="currentColor" />
<path d="M16.85 18.58a9 9 0 1 0-9.7 0" />
<path d="M8 14a5 5 0 1 1 8 0" />
<circle cx="12" cy="11" r="1" fill="currentColor" />
</svg>

After

Width:  |  Height:  |  Size: 424 B

-38
View File
@@ -1,38 +0,0 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"ericfennis",
"danielbayley",
"jguddas",
"karsa-mistmere"
],
"use-cases": [
"To view the activity history of an account or document.",
"To browse past events in a log or audit trail.",
"To show recent actions, such as recently visited pages.",
"To restore an earlier version of a file."
],
"tags": [
"history",
"time",
"redo",
"undo",
"rewind",
"timeline",
"version",
"time machine",
"backup",
"ccw"
],
"categories": [
"arrows",
"time"
],
"aliases": [
{
"name": "history",
"deprecated": true,
"deprecationReason": "alias.name"
}
]
}
-24
View File
@@ -1,24 +0,0 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"NielsLazaroms"
],
"use-cases": [
"To indicate when you need to process items.",
"To indicate that a process is happening"
],
"tags": [
"clock",
"waiting",
"schedule",
"hourglass",
"loading",
"pause",
"pending",
"time",
"watch"
],
"categories": [
"time"
]
}
-22
View File
@@ -1,22 +0,0 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 3a9.75 9.75 0 0 1 6.74 2.74" />
<path d="M18.74 5.74 21 8" />
<path d="M21 8V3" />
<path d="M7.5 19.794c-6-3.464-6-12.124 0-15.588" />
<path d="M7.5 4.206A9 9 0 0 1 12 3" />
<path d="M12 7v5l4 2" />
<path d="M14 20.775A9 9 0 0 1 12 21" />
<path d="M19 17.656a9 9 0 0 1-1.5 1.456" />
<path d="M21 12a9 9 0 0 1-.228 2" />
<path d="M21 8h-5" />
</svg>

Before

Width:  |  Height:  |  Size: 583 B

-46
View File
@@ -1,46 +0,0 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"wojtekmaj",
"ericfennis",
"karsa-mistmere"
],
"use-cases": [
"starting an augmented reality scan",
"placing virtual 3D objects in a real-world scene",
"indicating spatial mapping or room scanning",
"previewing products with virtual try-on",
"recognizing the surrounding environment for AR experiences",
"scanning an object to create a 3D model",
"measuring room dimensions for interior planning",
"calibrating depth sensors or LiDAR",
"placing furniture or decor in a room using AR"
],
"tags": [
"ar",
"augmented reality",
"3d",
"object detection",
"object recognition",
"tracking",
"spatial computing",
"capture",
"cube",
"bounding box",
"camera",
"frame",
"shape",
"boundary",
"lidar",
"depth",
"scanning",
"mapping",
"placement"
],
"categories": [
"design",
"devices",
"shopping",
"gaming"
]
}
-19
View File
@@ -1,19 +0,0 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 12v5.5" />
<path d="M17 3h2a2 2 0 012 2v2" />
<path d="M21 17v2a2 2 0 01-2 2h-2" />
<path d="M3 7V5a2 2 0 012-2h2" />
<path d="M7 21H5a2 2 0 01-2-2v-2" />
<path d="M7.264 9.252 12 12l4.737-2.748" />
<path d="M7.995 8.514A2 2 0 007 10.244v3.516a2 2 0 00.996 1.73l3 1.74a2 2 0 002.008 0l3-1.74A2 2 0 0017 13.76v-3.517a2 2 0 00-.995-1.73l-3-1.742a2 2 0 00-1.892-.064z" />
</svg>

Before

Width:  |  Height:  |  Size: 604 B

-39
View File
@@ -1,39 +0,0 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"samuelalake"
],
"use-cases": [
"detecting or selecting a shape or object inside a camera or AR viewfinder",
"a 'select shape' or region-detection control in a design or image editor",
"indicating camera scan mode or live scanning area",
"marking the crop area for creating square thumbnails",
"representing a region-of-interest for OCR or barcode capture",
"visualizing detected objects in an augmented reality overlay",
"toggling a scanning control in a camera or scanner app"
],
"tags": [
"scan",
"square",
"detect",
"recognition",
"select",
"frame",
"object",
"viewfinder",
"capture",
"shape",
"boundary",
"camera",
"scanner",
"overlay",
"focus",
"crop",
"marker"
],
"categories": [
"photography",
"design",
"development"
]
}
-17
View File
@@ -1,17 +0,0 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M3 7V5a2 2 0 0 1 2-2h2" />
<path d="M17 3h2a2 2 0 0 1 2 2v2" />
<path d="M21 17v2a2 2 0 0 1-2 2h-2" />
<path d="M7 21H5a2 2 0 0 1-2-2v-2" />
<rect width="8" height="8" x="8" y="8" rx="1" />
</svg>

Before

Width:  |  Height:  |  Size: 417 B

+1 -1
View File
@@ -13,4 +13,4 @@
<path d="M6.95 17h5.142c.523 0 .95-.406 1.063-.916a6.5 6.5 0 0 1 5.345-5.009" />
<circle cx="19.5" cy="17.5" r="2.5" />
<circle cx="4.5" cy="17.5" r="2.5" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 405 B

+1 -1
View File
@@ -13,4 +13,4 @@
<path d="m21 21-4.3-4.3" />
<path d="M11 7v4" />
<path d="M11 15h.01" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 322 B

After

Width:  |  Height:  |  Size: 321 B

-54
View File
@@ -1,54 +0,0 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"karsa-mistmere"
],
"use-cases": [
"Indicating that a resource or area is protected and requires authorized access",
"Representing access control and permission management settings",
"Showing security options for accounts, applications, or protected systems",
"Indicating content or functionality restricted to authenticated users",
"Representing authentication and secure sign-in features",
"Showing protected credentials, secrets, or other sensitive information",
"Representing identity and account protection features",
"Indicating security policies or authorization requirements"
],
"tags": [
"cybersecurity",
"secure",
"safety",
"protection",
"defense",
"defence",
"defender",
"block",
"threat",
"prevention",
"antivirus",
"vigilance",
"vigilant",
"detection",
"scan",
"find",
"strength",
"strong",
"tough",
"invincible",
"invincibility",
"invulnerable",
"undamaged",
"audit",
"admin",
"verification",
"crest",
"bravery",
"trooper",
"pawn"
],
"categories": [
"account",
"security",
"development",
"files"
]
}
-15
View File
@@ -1,15 +0,0 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 13v3" />
<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 01-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 011-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 011.52 0C14.51 3.81 17 5 19 5a1 1 0 011 1z" />
<circle cx="12" cy="11" r="2" />
</svg>

Before

Width:  |  Height:  |  Size: 438 B

+1 -1
View File
@@ -13,4 +13,4 @@
<path d="M5 17A12 12 0 0 1 17 5" />
<circle cx="19" cy="5" r="2" />
<circle cx="5" cy="19" r="2" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 459 B

After

Width:  |  Height:  |  Size: 458 B

+1 -1
View File
@@ -12,4 +12,4 @@
<path d="m10 16 4-4-4-4" />
<path d="M3 12h11" />
<path d="M3 8V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-3" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 351 B

After

Width:  |  Height:  |  Size: 350 B

+1 -1
View File
@@ -12,4 +12,4 @@
<path d="M10 12h11" />
<path d="m17 16 4-4-4-4" />
<path d="M21 6.344V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-1.344" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 361 B

After

Width:  |  Height:  |  Size: 360 B

+13 -7
View File
@@ -9,12 +9,18 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M14 21h1" />
<path d="m17 17-2.18-2.18" />
<path d="M5 21a2 2 0 01-2-2V5a2 2 0 012-2h14a2 2 0 012 2v14a2 2 0 01-2 2" />
<path d="M9 21h1" />
<path d="M9.56 14.44 17 7" />
<path d="M9.56 9.56 12 12" />
<circle cx="8.5" cy="15.5" r="1.5" />
<line x1="5" y1="3" x2="19" y2="3" />
<line x1="3" y1="5" x2="3" y2="19" />
<line x1="21" y1="5" x2="21" y2="19" />
<line x1="9" y1="21" x2="10" y2="21" />
<line x1="14" y1="21" x2="15" y2="21" />
<path d="M 3 5 A2 2 0 0 1 5 3" />
<path d="M 19 3 A2 2 0 0 1 21 5" />
<path d="M 5 21 A2 2 0 0 1 3 19" />
<path d="M 21 19 A2 2 0 0 1 19 21" />
<circle cx="8.5" cy="8.5" r="1.5" />
<line x1="9.56066" y1="9.56066" x2="12" y2="12" />
<line x1="17" y1="17" x2="14.82" y2="14.82" />
<circle cx="8.5" cy="15.5" r="1.5" />
<line x1="9.56066" y1="14.43934" x2="17" y2="7" />
</svg>

Before

Width:  |  Height:  |  Size: 509 B

After

Width:  |  Height:  |  Size: 801 B

-38
View File
@@ -1,38 +0,0 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"colebemis",
"ericfennis",
"october-learns"
],
"tags": [
"/",
"not",
"slash",
"off",
"disabled",
"inactive",
"cancel",
"none",
"block",
"forbidden",
"unavailable",
"stopped",
"checkbox",
"unchecked",
"toggle",
"negation",
"form",
"ui"
],
"categories": [
"shapes",
"design"
],
"use-cases": [
"indicating a disabled or unavailable state",
"marking something as blocked or prohibited",
"showing a deactivated interface element",
"representing a closed or inactive component"
]
}
-15
View File
@@ -1,15 +0,0 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M20.4 20.4a2 2 0 01-1.4.6H5a2 2 0 01-2-2V5a2 2 0 01.59-1.41" />
<path d="M21 15.3V5a2 2 0 00-2-2H8.7" />
<path d="M22 22 2 2" />
</svg>

Before

Width:  |  Height:  |  Size: 352 B

+5 -5
View File
@@ -9,10 +9,10 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m17 17-2.18-2.18" />
<path d="M9.56 14.44 17 7" />
<path d="M9.56 9.56 12 12" />
<circle cx="8.5" cy="15.5" r="1.5" />
<rect width="18" height="18" x="3" y="3" rx="2" />
<circle cx="8.5" cy="8.5" r="1.5" />
<rect x="3" y="3" width="18" height="18" rx="2" />
<line x1="9.56066" y1="9.56066" x2="12" y2="12" />
<line x1="17" y1="17" x2="14.82" y2="14.82" />
<circle cx="8.5" cy="15.5" r="1.5" />
<line x1="9.56066" y1="14.43934" x2="17" y2="7" />
</svg>

Before

Width:  |  Height:  |  Size: 436 B

After

Width:  |  Height:  |  Size: 495 B

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