mirror of
https://github.com/lucide-icons/lucide.git
synced 2026-11-10 13:18:25 +00:00
Compare commits
29
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4aec3f892f | ||
|
|
dbfe130652 | ||
|
|
d29db5e98e | ||
|
|
bb26580cfb | ||
|
|
74c46711c7 | ||
|
|
c3b6795394 | ||
|
|
33342b8790 | ||
|
|
9ecaafbc4d | ||
|
|
1d578ab536 | ||
|
|
c757cb9d4b | ||
|
|
5d36179bf4 | ||
|
|
357df0d660 | ||
|
|
5a06f7cb1d | ||
|
|
63d0ef6664 | ||
|
|
0adb963d07 | ||
|
|
89147bbecc | ||
|
|
0ad5aaf323 | ||
|
|
50f9af4ed2 | ||
|
|
4c61dc4826 | ||
|
|
99a8602c5d | ||
|
|
75b6ac1969 | ||
|
|
138ce8e748 | ||
|
|
87ec1a0587 | ||
|
|
02eaf471a9 | ||
|
|
3035ed309e | ||
|
|
4e50f0d759 | ||
|
|
a924c01b8e | ||
|
|
37f32cb73a | ||
|
|
4e2efb9350 |
@@ -9,3 +9,4 @@ strikethrough
|
||||
touchpad
|
||||
ungroup
|
||||
toc
|
||||
sunlounger
|
||||
|
||||
@@ -47,7 +47,9 @@ 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.
|
||||
|
||||
@@ -27,10 +27,6 @@ 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' &&
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
name: Linting PR
|
||||
name: Linting PR code
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- icons/*.svg
|
||||
|
||||
jobs:
|
||||
lint-code:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Linting PR
|
||||
name: Linting PR title
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: 'Request Review'
|
||||
name: Request Review
|
||||
on:
|
||||
pull_request_target:
|
||||
pull_request:
|
||||
types: [opened]
|
||||
paths:
|
||||
- icons/*.svg
|
||||
|
||||
@@ -54,6 +54,9 @@ 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
@@ -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
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
"kubernetes": "Kubernetes",
|
||||
"leetcode": "LeetCode",
|
||||
"leet-code": "LeetCode",
|
||||
"line": "LINE",
|
||||
"linkedin": "LinkedIn",
|
||||
"lua": "Lua",
|
||||
"mariadb": "MariaDB",
|
||||
@@ -69,7 +68,7 @@
|
||||
"nestjs": "NestJS",
|
||||
"netflix": "Netflix",
|
||||
"netlify": "Netlify",
|
||||
"next": "Next.js",
|
||||
"nextjs": "Next.js",
|
||||
"nodejs": "Node.js",
|
||||
"notion": "Notion",
|
||||
"nostr": "Nostr",
|
||||
@@ -105,7 +104,8 @@
|
||||
"shopify": "Shopify",
|
||||
"skype": "Skype",
|
||||
"slack": "Slack",
|
||||
"solid": "SolidJS",
|
||||
"snapchat": "Snapchat",
|
||||
"solidjs": "SolidJS",
|
||||
"soundcloud": "SoundCloud",
|
||||
"spotify": "Spotify",
|
||||
"sqlite": "SQLite",
|
||||
@@ -144,6 +144,5 @@
|
||||
"xbox": "Xbox",
|
||||
"yarn": "Yarn",
|
||||
"youtube": "YouTube",
|
||||
"zig": "Zig",
|
||||
"zoom": "Zoom"
|
||||
"zig": "Zig"
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}, {});
|
||||
});
|
||||
@@ -84,7 +84,7 @@ const base64InnerSvg = computed(() => {
|
||||
</g>
|
||||
</svg>
|
||||
<a
|
||||
:href="`https://studio.lucide.dev/edit?value=${encodeURIComponent(base64InnerSvg)}&name=${name}`"
|
||||
: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"
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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,
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
+7
-5
@@ -8,19 +8,21 @@
|
||||
"docs:dev": "pnpm run /^prebuild:.*/ && vitepress dev",
|
||||
"docs:build": "pnpm run /^prebuild:.*/ && vitepress build",
|
||||
"docs:preview": "vitepress preview",
|
||||
"build:docs": "vitepress 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",
|
||||
"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": "npx nitropack dev",
|
||||
"prebuild:api": "npx nitropack prepare",
|
||||
"build:api": "npx nitropack build",
|
||||
"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"
|
||||
},
|
||||
|
||||
@@ -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'
|
||||
import metaData from '../../../../icons/${iconName}.json'
|
||||
import releaseData from '../releaseMetadata/${iconName}.json'
|
||||
import popularity from '../iconPopularity/${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}',
|
||||
@@ -42,9 +42,9 @@ const iconDetails = {
|
||||
deprecationReason,
|
||||
toBeRemovedInVersion,
|
||||
...releaseData,
|
||||
}
|
||||
};
|
||||
|
||||
export default iconDetails
|
||||
export default iconDetails;
|
||||
`;
|
||||
|
||||
await fs.promises.writeFile(location, contents, 'utf-8');
|
||||
|
||||
@@ -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}`);
|
||||
}
|
||||
@@ -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}`);
|
||||
}
|
||||
@@ -5,27 +5,59 @@ import { loadEnvFile } from 'node:process';
|
||||
import { readSvgDirectory } from '@lucide/helpers';
|
||||
|
||||
const currentDir = process.cwd();
|
||||
const ICONS_DIR = path.resolve(currentDir, '../icons');
|
||||
const iconPopularityDirectory = path.resolve(currentDir, '.vitepress/data', 'iconPopularity');
|
||||
const dataDirectory = path.resolve(currentDir, '.vitepress/data');
|
||||
|
||||
try {
|
||||
// Load environment variables from .env file, if it exists.
|
||||
loadEnvFile(`${currentDir}/.env`);
|
||||
} catch (error) {}
|
||||
|
||||
if (fs.existsSync(iconPopularityDirectory)) {
|
||||
fs.rmSync(iconPopularityDirectory, { recursive: true, force: true });
|
||||
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.mkdirSync(iconPopularityDirectory);
|
||||
// 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>;
|
||||
}
|
||||
|
||||
const iconJsonFiles = await readSvgDirectory(ICONS_DIR, '.json');
|
||||
const iconNames = iconJsonFiles.map((file) => path.basename(file, '.json'));
|
||||
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 defaultIconNamePopularity: Record<string, number> = Object.fromEntries(
|
||||
iconNames.map((iconName) => [iconName, 0])
|
||||
return {
|
||||
...collection,
|
||||
iconNames,
|
||||
counts: Object.fromEntries(iconNames.map((iconName) => [iconName, 0])),
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
interface AnalyticsResponse {
|
||||
@@ -35,19 +67,30 @@ interface AnalyticsResponse {
|
||||
}[];
|
||||
}
|
||||
|
||||
const writeIconPopularity = async (iconVisitCounts: Record<string, number>) => {
|
||||
const writePopularityPromises = Object.entries(iconVisitCounts).map(([iconName, count]) => {
|
||||
const location = path.resolve(iconPopularityDirectory, `${iconName}.json`);
|
||||
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`);
|
||||
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, 'icons.');
|
||||
console.log(
|
||||
'Successfully written icon popularity data for',
|
||||
writePopularityPromises.length,
|
||||
`${name} 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 writeIconPopularity(defaultIconNamePopularity);
|
||||
await writeAllIconPopularity();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -76,29 +119,34 @@ try {
|
||||
|
||||
const analyticsData: AnalyticsResponse = await response.json();
|
||||
|
||||
const iconVisitCounts = analyticsData.results.reduce((acc, { dimensions, metrics }) => {
|
||||
for (const { dimensions, metrics } of analyticsData.results) {
|
||||
const [route] = dimensions;
|
||||
const [count] = metrics;
|
||||
|
||||
if (!route.startsWith('/icons')) {
|
||||
return acc
|
||||
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 (iconNames.includes(iconName)) {
|
||||
acc[iconName] = (acc[iconName] || 0) + count;
|
||||
// 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;
|
||||
}
|
||||
|
||||
const iconName = match[1];
|
||||
if (collection.iconNames.includes(iconName)) {
|
||||
collection.counts[iconName] += count;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, defaultIconNamePopularity);
|
||||
|
||||
await writeIconPopularity(iconVisitCounts);
|
||||
await writeAllIconPopularity();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fetching analytics data:', error);
|
||||
await writeIconPopularity(defaultIconNamePopularity);
|
||||
await writeAllIconPopularity();
|
||||
}
|
||||
|
||||
@@ -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 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}`);
|
||||
}
|
||||
@@ -6,9 +6,7 @@
|
||||
"danielbayley",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Decreasing the font size in a text editor"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"letter",
|
||||
"font size",
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
"danielbayley",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Increasing the font size in a text editor"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"letter",
|
||||
"font size",
|
||||
|
||||
@@ -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: 390 B After Width: | Height: | Size: 391 B |
@@ -4,10 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing physical disability or accessibility assistance",
|
||||
"Marking wheelchair-accessible facilities or routes"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"disability",
|
||||
"disabled",
|
||||
|
||||
+1
-5
@@ -4,11 +4,7 @@
|
||||
"colebemis",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing an activity feed or recent actions",
|
||||
"Showing health metrics such as heart rate or vital signs",
|
||||
"Indicating live system activity or monitoring"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"pulse",
|
||||
"action",
|
||||
|
||||
+6
-1
@@ -21,10 +21,15 @@
|
||||
"paid",
|
||||
"partner",
|
||||
"promo",
|
||||
"sponsor"
|
||||
"sponsor",
|
||||
"audio description",
|
||||
"video description",
|
||||
"described video",
|
||||
"visual description"
|
||||
],
|
||||
"categories": [
|
||||
"multimedia",
|
||||
"accessibility",
|
||||
"notifications"
|
||||
]
|
||||
}
|
||||
|
||||
+1
-4
@@ -4,10 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing air conditioning or ventilation in smart home apps",
|
||||
"Indicating climate control amenities on hotel and booking platforms"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"air conditioner",
|
||||
"ac",
|
||||
|
||||
+1
-4
@@ -5,10 +5,7 @@
|
||||
"csandman",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Streaming or mirroring a screen to an external display",
|
||||
"Casting media to a TV or compatible device"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"stream",
|
||||
"cast",
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
"jguddas",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Confirming an alarm or scheduled reminder is set",
|
||||
"Marking a timed task as complete"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"done",
|
||||
"todo",
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
"jguddas",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Removing or deleting an alarm"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"remove"
|
||||
],
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Turning off or disabling an alarm"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"morning",
|
||||
"turn-off"
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
"jguddas",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Adding or creating a new alarm"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"add"
|
||||
],
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
"jguddas",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Setting an alarm or wake-up reminder"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"morning"
|
||||
],
|
||||
|
||||
@@ -5,10 +5,7 @@
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing a smoke or fire detector in smart home apps",
|
||||
"Indicating fire safety equipment or amenities in listings"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"fire",
|
||||
"alert",
|
||||
|
||||
+1
-4
@@ -5,10 +5,7 @@
|
||||
"csandman",
|
||||
"mittalyashu"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing a photo album or collection",
|
||||
"Indicating a music album"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"photo",
|
||||
"book"
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Aligning elements to the horizontal center in page builders and design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"items",
|
||||
"flex",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Aligning elements to the vertical center in page builders and design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"items",
|
||||
"flex",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Aligning elements to the horizontal end in page builders and design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"items",
|
||||
"bottom",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Aligning elements to the vertical end in page builders and design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"items",
|
||||
"right",
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"r4lv",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Distributing elements evenly around their horizontal centers in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"items",
|
||||
"flex",
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"r4lv",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Distributing elements by their right edges in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"right",
|
||||
"items",
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"r4lv",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Distributing elements by their left edges in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"left",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Justifying elements around the horizontal center in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"center",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Justifying elements to the horizontal end in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"right",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Justifying elements to the horizontal start in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"left",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Distributing elements with equal horizontal space around them in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"center",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Distributing elements with equal horizontal space between them in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"around",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Aligning elements to the horizontal start in page builders and design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"top",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Aligning elements to the vertical start in page builders and design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"left",
|
||||
"items",
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"ericfennis",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Distributing elements evenly around the vertical center in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"items",
|
||||
"flex",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Distributing elements toward the vertical end in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"bottom",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Distributing elements toward the vertical start in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"top",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Justifying elements around the vertical center in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"center",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Justifying elements to the vertical end in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"bottom",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Justifying elements to the vertical start in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"top",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Distributing elements with equal vertical space around them in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"center",
|
||||
"items",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Distributing elements with equal vertical space between them in design tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"center",
|
||||
"items",
|
||||
|
||||
@@ -11,10 +11,7 @@
|
||||
"karsa-mistmere",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [
|
||||
"Directing users to nearby emergency services in navigation apps",
|
||||
"Marking emergency contacts or medical transport services"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"ambulance",
|
||||
"emergency",
|
||||
|
||||
+2
-3
@@ -11,10 +11,9 @@
|
||||
>
|
||||
<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: 553 B After Width: | Height: | Size: 550 B |
@@ -5,10 +5,7 @@
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Inserting an ampersand in text editors",
|
||||
"Representing a join or concatenation operator in code"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"and",
|
||||
"typography",
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"danielbayley",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing a logical AND operator in code"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"and",
|
||||
"operator",
|
||||
|
||||
+1
-6
@@ -3,12 +3,7 @@
|
||||
"contributors": [
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing museological or archaeological artefacts",
|
||||
"Indicating pottery or ceramics",
|
||||
"Symbolizing Greek culture or antiquity",
|
||||
"Denoting amphora-aged wines"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"pottery",
|
||||
"artifact",
|
||||
|
||||
+1
-4
@@ -6,10 +6,7 @@
|
||||
"ericfennis",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing a ship's anchor or maritime context",
|
||||
"Linking to an anchor point or section within a page"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"ship"
|
||||
],
|
||||
|
||||
+1
-4
@@ -4,10 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Expressing strong dissatisfaction in feedback or rating scales",
|
||||
"Marking the lowest score on a contentment scale (very unhappy to very happy)"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"emoji",
|
||||
"anger",
|
||||
|
||||
+1
-4
@@ -3,10 +3,7 @@
|
||||
"contributors": [
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Expressing mild dissatisfaction in feedback or rating scales",
|
||||
"Marking an unhappy step on a contentment scale (very unhappy to very happy)"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"emoji",
|
||||
"nuisance",
|
||||
|
||||
+1
-5
@@ -3,11 +3,7 @@
|
||||
"contributors": [
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing signal reception or broadcast",
|
||||
"Indicating a TV antenna or terrestrial reception",
|
||||
"Showing connectivity or frequency tuning"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"signal",
|
||||
"connection",
|
||||
|
||||
+1
-3
@@ -4,9 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing construction, metalwork, or industrial tools"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"metal",
|
||||
"iron",
|
||||
|
||||
+1
-4
@@ -4,10 +4,7 @@
|
||||
"colebemis",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing camera aperture or exposure settings",
|
||||
"Indicating photography or capture features"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"camera",
|
||||
"photo",
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
"contributors": [
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing an application window on macOS",
|
||||
"Indicating a desktop app or pane"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"application",
|
||||
"menu bar",
|
||||
|
||||
@@ -4,10 +4,7 @@
|
||||
"danielbayley",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing an application window",
|
||||
"Indicating a desktop app or executable"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"application",
|
||||
"menu bar",
|
||||
|
||||
+1
-5
@@ -3,11 +3,7 @@
|
||||
"contributors": [
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing fruit or healthy eating",
|
||||
"Categorizing produce or groceries",
|
||||
"Symbolizing nutrition or a balanced diet"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"fruit",
|
||||
"food",
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
"ericfennis",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [
|
||||
"Restoring an item from the archive, reversing an archive action"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"unarchive",
|
||||
"index",
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
"contributors": [
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [
|
||||
"Removing an item from the archive",
|
||||
"Marking archived mail as junk"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"index",
|
||||
"backup",
|
||||
|
||||
+1
-4
@@ -6,10 +6,7 @@
|
||||
"karsa-mistmere",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [
|
||||
"Archiving items or moving them to storage",
|
||||
"Representing backups or stored records"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"index",
|
||||
"backup",
|
||||
|
||||
+1
-4
@@ -4,10 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Indicating a lounge or seating area in hotel and booking apps",
|
||||
"Representing living room furniture in smart home applications"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"sofa",
|
||||
"furniture",
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Moving down with emphasis, e.g. as a game control",
|
||||
"Indicating a download or a jump to the bottom"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"backwards",
|
||||
"reverse",
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Indicating a strong downward direction, e.g. as a game control"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"backwards",
|
||||
"reverse",
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Indicating a strong leftward direction or turn, e.g. as a game control"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"previous",
|
||||
"back",
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Indicating a strong leftward direction, e.g. as a game control"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"previous",
|
||||
"back",
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Indicating a strong rightward direction or turn, e.g. as a game control"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"next",
|
||||
"forward",
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Indicating a strong rightward direction, e.g. as a game control"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"next",
|
||||
"forward",
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing the Caps Lock key on a keyboard",
|
||||
"Indicating a speed boost or strong upward direction in games"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"caps lock",
|
||||
"capitals",
|
||||
|
||||
@@ -8,10 +8,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"Representing the Shift key on a keyboard",
|
||||
"Indicating a strong upward direction in games"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"shift",
|
||||
"keyboard",
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [
|
||||
"Sorting numerical values in ascending order"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"filter",
|
||||
"sort",
|
||||
@@ -28,7 +26,6 @@
|
||||
"name": "arrow-down-01",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true
|
||||
},
|
||||
"arrow-down-01"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [
|
||||
"Sorting numerical values in descending order"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"filter",
|
||||
"sort",
|
||||
@@ -28,7 +26,6 @@
|
||||
"name": "arrow-down-10",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true
|
||||
},
|
||||
"arrow-down-10"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [
|
||||
"Sorting items alphabetically from A to Z"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"filter",
|
||||
"sort",
|
||||
@@ -28,7 +26,6 @@
|
||||
"name": "arrow-down-az",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true
|
||||
},
|
||||
"arrow-down-az"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,10 +4,7 @@
|
||||
"danielbayley",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Downloading or moving content downward from a boundary",
|
||||
"Expanding a section downward"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"backwards",
|
||||
"reverse",
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"colebemis",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Indicating a downward-left diagonal direction"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"direction",
|
||||
"south-west",
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"contributors": [
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Sorting items from narrow to wide, e.g. smallest to largest"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"filter",
|
||||
"sort",
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"colebemis",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Indicating a downward-right diagonal direction"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"direction",
|
||||
"south-east",
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
"contributors": [
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [
|
||||
"Moving down to a specific point or waypoint",
|
||||
"Indicating a target or destination below"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"direction",
|
||||
"south",
|
||||
|
||||
@@ -4,10 +4,7 @@
|
||||
"danielbayley",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [
|
||||
"Downloading or saving content to a boundary",
|
||||
"Representing a git pull or collapsing a section"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"behind",
|
||||
"direction",
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
"contributors": [
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Indicating two-way data transfer or network traffic",
|
||||
"Sorting or reordering items"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"bidirectional",
|
||||
"two-way",
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
"csandman",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [
|
||||
"Sorting items from wide to narrow, e.g. largest to smallest"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"filter",
|
||||
"sort",
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [
|
||||
"Sorting items alphabetically from Z to A"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"filter",
|
||||
"sort",
|
||||
@@ -29,7 +27,6 @@
|
||||
"name": "arrow-down-za",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true
|
||||
},
|
||||
"arrow-down-za"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user