Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07744ea48f | ||
|
|
0846e2c6ef | ||
|
|
dea4936a72 | ||
|
|
b76860a2b8 | ||
|
|
de9b2d39b7 | ||
|
|
08488f4809 | ||
|
|
3574e224e0 | ||
|
|
9a8e023754 | ||
|
|
88fd3dadcb | ||
|
|
bc446a83b2 | ||
|
|
39fa345658 | ||
|
|
fb31e5f616 | ||
|
|
dcd95a3b90 | ||
|
|
a1a729555b | ||
|
|
a28631e2a4 | ||
|
|
cbaaf4e21e | ||
|
|
e9e060a851 | ||
|
|
0371baabcb | ||
|
|
67c0485457 | ||
|
|
c47876e5a6 | ||
|
|
96859ba947 | ||
|
|
7dfa7d9fc6 | ||
|
|
b6ed43d48c | ||
|
|
9b10d1d9bb | ||
|
|
442ddbc43c | ||
|
|
ce5cab371f | ||
|
|
69239462bb | ||
|
|
f8e04958d8 | ||
|
|
e466a104ff | ||
|
|
516917c527 | ||
|
|
3cec234405 | ||
|
|
a258509bbb | ||
|
|
10918eba1f | ||
|
|
5f4f58cba8 | ||
|
|
511d7fabf7 | ||
|
|
77a67819e4 | ||
|
|
edc588125f | ||
|
|
0c4ac91ba5 | ||
|
|
450acd617d | ||
|
|
d391bda369 | ||
|
|
69bf052ee5 | ||
|
|
6b4075b89b | ||
|
|
7a68e10b12 | ||
|
|
a4531a9985 | ||
|
|
3edcd9e0c3 | ||
|
|
0b8f99326c | ||
|
|
7abb61630e | ||
|
|
3b0d158ea1 | ||
|
|
124572c83b |
@@ -28,7 +28,7 @@ jobs:
|
||||
{ [ -n "$ICON_NAME_SECTION" ] && echo "$ICON_NAME_SECTION" | grep -iqE "$SAFE_KEY|$SAFE_VALUE"; }; then
|
||||
|
||||
gh issue close ${{ github.event.issue.number }} \
|
||||
--reason "not_planned" \
|
||||
--reason "not planned" \
|
||||
--comment "It looks like this request is about **${VALUE}**, which is a brand logo.
|
||||
|
||||
Lucide **does not accept** brand logos, and we do not plan to add them in the future. This is due to a combination of **legal restrictions**, **design consistency concerns**, and **practical maintenance reasons**.
|
||||
|
||||
@@ -41,3 +41,19 @@ jobs:
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter @lucide/svelte test
|
||||
|
||||
typecheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter @lucide/svelte typecheck
|
||||
|
||||
@@ -20,6 +20,8 @@ packages/**/src/icons/*.tsx
|
||||
packages/**/src/aliases/*.ts
|
||||
packages/**/src/aliases.ts
|
||||
!packages/**/src/aliases/index.ts
|
||||
packages/**/src/utils/*.ts
|
||||
!packages/shared/src/utils/*.ts
|
||||
packages/**/src/dynamicIconImports.ts
|
||||
packages/**/DynamicIcon.d.ts
|
||||
packages/**/dynamicIconImports.js
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2023 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2025.
|
||||
Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2026 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2026.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -18,7 +18,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
The MIT License (MIT) (for portions derived from Feather)
|
||||
|
||||
Copyright (c) 2013-2023 Cole Bemis
|
||||
Copyright (c) 2013-2026 Cole Bemis
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -88,7 +88,16 @@ Thank you to all the people who contributed to Lucide!
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="docs/public/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="docs/public/sponsors/pdfme.svg" width="180" alt="pdfme sponsor badge" /></a>
|
||||
<a href="https://www.fina.money/"><img src="docs/public/sponsors/fina-money.png" width="180" alt="Fina Money sponsor badge" /></a>
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="docs/public/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
<a href="https://www.paxhistoria.co/"><img src="docs/public/sponsors/paxhistoria.svg?" width="180" alt="Pax Historia – An alternate history sandbox game" /></a>
|
||||
|
||||
### Backers ☕
|
||||
|
||||
<a href="https://www.fina.money/"><img src="docs/public/sponsors/fina-money.png" width="180" alt="Fina Money – Modular Finance Tracker" /></a>
|
||||
|
||||
### Other contributors 💸
|
||||
|
||||
You can find all our past and non-recurring financial contributors at [our Open Collective page](https://opencollective.com/lucide-icons).
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"adobe": "Adobe",
|
||||
"airplay": "AirPlay",
|
||||
"amazon": "Amazon",
|
||||
"android": "Android",
|
||||
"angular": "Angular",
|
||||
"aws": "AWS",
|
||||
"azure": "Azure",
|
||||
|
||||
@@ -22,6 +22,7 @@ export default eventHandler((event) => {
|
||||
const height = getQuery(event).height || undefined;
|
||||
const color = getQuery(event).color || undefined;
|
||||
const strokeWidth = getQuery(event).strokeWidth || undefined;
|
||||
const background = getQuery(event).background || undefined;
|
||||
|
||||
const LucideIcon = createLucideIcon(params.iconName, iconNode);
|
||||
|
||||
@@ -32,6 +33,7 @@ export default eventHandler((event) => {
|
||||
height,
|
||||
color: color ? `#${color}` : undefined,
|
||||
strokeWidth,
|
||||
style: background ? { background } : undefined,
|
||||
}),
|
||||
),
|
||||
).toString('utf8');
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import { eventHandler, setResponseHeader } from 'h3';
|
||||
import releaseMeta from '../../data/releaseMetaData.json';
|
||||
|
||||
export default eventHandler((event) => {
|
||||
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400');
|
||||
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
|
||||
|
||||
return Object.fromEntries(
|
||||
Object.entries(releaseMeta).map(
|
||||
([name, { createdRelease }]) => [name, createdRelease.version]
|
||||
)
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,3 @@
|
||||
export default eventHandler(() => {
|
||||
return { nitro: 'Is Awesome! asda' };
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
import { fileURLToPath, URL } from 'node:url';
|
||||
import { defineConfig } from 'vitepress';
|
||||
import sidebar from './sidebar';
|
||||
import getStructuredData from './getStructuredData';
|
||||
|
||||
const title = 'Lucide';
|
||||
const socialTitle = 'Lucide Icons';
|
||||
@@ -9,6 +10,7 @@ const description = 'Beautiful & consistent icon toolkit made by the community.'
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
title,
|
||||
titleTemplate: ':title \u2013 Lucide',
|
||||
description,
|
||||
cleanUrls: true,
|
||||
outDir: '.vercel/output/static',
|
||||
@@ -150,8 +152,36 @@ export default defineConfig({
|
||||
},
|
||||
],
|
||||
],
|
||||
async transformPageData(pageData) {
|
||||
if (
|
||||
pageData.relativePath.startsWith('icons/') &&
|
||||
!pageData.relativePath.startsWith('icons/lab/') &&
|
||||
pageData.params?.name
|
||||
) {
|
||||
const iconName = pageData.params.name;
|
||||
pageData.title = `${iconName} icon details`;
|
||||
|
||||
const taggedAs = pageData.params?.tags?.length
|
||||
? `Tagged as: ${pageData.params.tags.join(', ')}.`
|
||||
: '';
|
||||
const categorizedIn = pageData.params?.category?.length
|
||||
? `Categorized in: ${pageData.params.category.join(', ')}.`
|
||||
: '';
|
||||
|
||||
pageData.description =
|
||||
`Details and related icons for ${iconName} icon. ${taggedAs} ${categorizedIn}`.trim();
|
||||
|
||||
const structuredData = await getStructuredData(iconName, pageData);
|
||||
|
||||
pageData.frontmatter.head ??= [];
|
||||
pageData.frontmatter.head.push([
|
||||
'script',
|
||||
{ type: 'application/ld+json' },
|
||||
JSON.stringify(structuredData),
|
||||
]);
|
||||
}
|
||||
},
|
||||
themeConfig: {
|
||||
// https://vitepress.dev/reference/default-theme-config
|
||||
logo: {
|
||||
light: '/logo.light.svg',
|
||||
dark: '/logo.dark.svg',
|
||||
|
||||
@@ -171,5 +171,24 @@
|
||||
],
|
||||
"source": "https://github.com/heyvito/lucide-rails",
|
||||
"documentation": "https://github.com/heyvito/lucide-rails/blob/master/README.md"
|
||||
},
|
||||
{
|
||||
"name": "lucide-web-components",
|
||||
"description": "Implementation of Lucide icons in Web Components custom elements.",
|
||||
"icon": "/framework-logos/web-components.svg",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "Latest Stable Version",
|
||||
"src": "https://img.shields.io/npm/v/@dile/iconlib",
|
||||
"href": "https://dile-components.com/icons/lucide-icons/"
|
||||
},
|
||||
{
|
||||
"alt": "Total Downloads",
|
||||
"src": "https://img.shields.io/npm/dt/@dile/iconlib",
|
||||
"href": "https://dile-components.com/icons/lucide-icons/"
|
||||
}
|
||||
],
|
||||
"source": "https://github.com/Polydile/dile-components",
|
||||
"documentation": "https://github.com/Polydile/dile-components/blob/master/packages/iconlib/README.md"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { PageData } from 'vitepress';
|
||||
|
||||
export default async function getStructuredData(iconName: string, pageData: PageData) {
|
||||
const url = `https://lucide.dev/icons/${iconName}`;
|
||||
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'WebPage',
|
||||
'@id': url,
|
||||
name: pageData.title,
|
||||
description: pageData.description,
|
||||
url,
|
||||
inLanguage: 'en',
|
||||
isPartOf: {
|
||||
'@type': 'WebSite',
|
||||
name: 'Lucide Icons',
|
||||
url: 'https://lucide.dev',
|
||||
},
|
||||
breadcrumb: {
|
||||
'@type': 'BreadcrumbList',
|
||||
itemListElement: [
|
||||
{ '@type': 'ListItem', position: 1, name: 'Icons', item: 'https://lucide.dev/icons' },
|
||||
{ '@type': 'ListItem', position: 2, name: iconName, item: url },
|
||||
],
|
||||
},
|
||||
mainEntity: {
|
||||
'@type': 'ImageObject',
|
||||
'@id': `${url}#icon`,
|
||||
name: iconName,
|
||||
// TODO: Add support for description extraction from icon metadata
|
||||
// description: 'An ...SVG icon from the Lucide icon set.',
|
||||
contentUrl: `https://lucide.dev/api/icons/${iconName}}?width=24&height=24&background=white`,
|
||||
thumbnailUrl: `https://lucide.dev/api/icons/${iconName}}?width=256&height=256&background=white`,
|
||||
encodingFormat: 'image/svg+xml',
|
||||
keywords: pageData.params?.tags,
|
||||
width: 24,
|
||||
height: 24,
|
||||
creator: {
|
||||
'@type': 'Organization',
|
||||
name: 'Lucide Icons',
|
||||
},
|
||||
datePublished: pageData?.params?.createdRelease?.date,
|
||||
dateModified: pageData?.params?.changedRelease?.date,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createLucideIcon } from 'lucide-react/src/lucide-react';
|
||||
import { type LucideProps, type IconNode } from 'lucide-react/src/createLucideIcon';
|
||||
import { type LucideProps, type IconNode } from 'lucide-react/src/types';
|
||||
import { IconEntity } from '../theme/types';
|
||||
import { renderToStaticMarkup } from 'react-dom/server';
|
||||
import { IconContent } from './generateZip';
|
||||
|
||||
@@ -1,23 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
import { useData } from 'vitepress';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: string
|
||||
id: string
|
||||
}>()
|
||||
modelValue: string;
|
||||
id: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { isDark } = useData();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const value = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val)
|
||||
})
|
||||
get: () => {
|
||||
if (props.modelValue == null || props.modelValue === 'currentColor') {
|
||||
return isDark.value ? '#ffffff' : '#000000';
|
||||
}
|
||||
|
||||
return props.modelValue;
|
||||
},
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="color-picker">
|
||||
<div class="color-input-wrapper">
|
||||
<!-- TODO: Add currentColor div if value is currentColor -->
|
||||
<input
|
||||
type="color"
|
||||
:id="id"
|
||||
@@ -33,6 +41,7 @@ const value = computed({
|
||||
class="color-input-text"
|
||||
aria-label="Color picker input"
|
||||
v-model="value"
|
||||
placeholder="[default]"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -45,27 +54,33 @@ const value = computed({
|
||||
top: -5px;
|
||||
left: -5px;
|
||||
}
|
||||
|
||||
.color-input-wrapper {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
border-radius: 12px;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.color-picker {
|
||||
background: var(--color-picker-bg, var(--vp-c-bg-alt));
|
||||
border-radius: 8px;
|
||||
color: var(--vp-c-text-2);
|
||||
padding: 4px 8px;
|
||||
padding: 3px 8px 3px 3px;
|
||||
height: auto;
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
text-align: left;
|
||||
border: 1px solid transparent;
|
||||
cursor: text;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
transition:
|
||||
color 0.25s,
|
||||
border-color 0.25s,
|
||||
background-color 0.25s;
|
||||
}
|
||||
|
||||
.color-input-text {
|
||||
@@ -75,19 +90,24 @@ const value = computed({
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--vp-c-text-1);
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
text-align: left;
|
||||
border-radius: 8px;
|
||||
cursor: text;
|
||||
transition: border-color 0.25s, background 0.4s ease;
|
||||
transition:
|
||||
border-color 0.25s,
|
||||
background 0.4s ease;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.color-picker:hover, .color-picker:focus {
|
||||
.color-picker:hover,
|
||||
.color-picker:focus-within {
|
||||
border-color: var(--vp-c-brand);
|
||||
background: var(--vp-c-bg-alt);
|
||||
}
|
||||
.color-picker:focus-within {
|
||||
background-color: var(--vp-c-bg);
|
||||
}
|
||||
|
||||
.color-input[value="currentColor"] {
|
||||
|
||||
.color-input[value='currentColor'] {
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
<script setup>
|
||||
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
|
||||
import { search } from '../../../data/iconNodes'
|
||||
|
||||
const SearchIcon = createLucideIcon('search', search)
|
||||
import Icon from 'lucide-vue-next/src/Icon';
|
||||
import { search } from '../../../data/iconNodes';
|
||||
|
||||
defineProps({
|
||||
shortcut: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
})
|
||||
required: false,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button class="fake-input">
|
||||
<component :is="SearchIcon" class="search-icon"/>
|
||||
<slot/>
|
||||
<kbd v-if="shortcut" class="shortcut">{{ shortcut }}</kbd>
|
||||
<Icon
|
||||
:iconNode="search"
|
||||
class="search-icon"
|
||||
/>
|
||||
<slot />
|
||||
<kbd
|
||||
v-if="shortcut"
|
||||
class="shortcut"
|
||||
>{{ shortcut }}</kbd
|
||||
>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
@@ -34,12 +39,15 @@ defineProps({
|
||||
cursor: text;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
transition: color 0.25s, border-color 0.25s, background-color 0.25s;
|
||||
transition:
|
||||
color 0.25s,
|
||||
border-color 0.25s,
|
||||
background-color 0.25s;
|
||||
}
|
||||
|
||||
.fake-input:hover, .fake-input:focus {
|
||||
.fake-input:hover,
|
||||
.fake-input:focus {
|
||||
border-color: var(--vp-c-brand);
|
||||
background: var(--vp-c-bg-alt);
|
||||
}
|
||||
|
||||
.shortcut {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.icon-button {
|
||||
display: inline-flex;
|
||||
border: 1px solid transparent;
|
||||
@@ -30,9 +29,9 @@
|
||||
}
|
||||
|
||||
.icon-button:active {
|
||||
border-color: var(--vp-button-alt-active-border);
|
||||
color: var(--vp-button-alt-active-text);
|
||||
background-color: var(--vp-button-alt-active-bg);
|
||||
border-color: var(--vp-button-alt-active-border);
|
||||
color: var(--vp-button-alt-active-text);
|
||||
background-color: var(--vp-button-alt-active-bg);
|
||||
}
|
||||
|
||||
.icon-button.active {
|
||||
|
||||
@@ -12,6 +12,9 @@ export interface InputProps {
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, nextTick, watch } from 'vue';
|
||||
import Icon from 'lucide-vue-next/src/Icon';
|
||||
import { x } from '../../../data/iconNodes';
|
||||
import IconButton from './IconButton.vue';
|
||||
|
||||
const props = withDefaults(defineProps<InputProps>(), {
|
||||
type: 'text',
|
||||
@@ -21,7 +24,7 @@ const input = ref();
|
||||
const wrapperEl = ref();
|
||||
const shortcutEl = ref();
|
||||
|
||||
defineEmits(['change', 'input', 'update:modelValue']);
|
||||
const emit = defineEmits(['change', 'input', 'update:modelValue']);
|
||||
|
||||
const updateShortcutSpacing = () => {
|
||||
nextTick(() => {
|
||||
@@ -32,9 +35,16 @@ const updateShortcutSpacing = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const isMac = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);
|
||||
|
||||
onMounted(updateShortcutSpacing);
|
||||
watch(() => props.shortcut, updateShortcutSpacing);
|
||||
|
||||
function onClear() {
|
||||
emit('update:modelValue', '');
|
||||
input.value.focus();
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
focus: () => {
|
||||
input.value.focus();
|
||||
@@ -60,6 +70,18 @@ defineExpose({
|
||||
v-bind="$attrs"
|
||||
@input="$emit('update:modelValue', $event.target.value)"
|
||||
/>
|
||||
<IconButton
|
||||
@click="onClear"
|
||||
v-if="type === 'search' && modelValue"
|
||||
class="clear-button"
|
||||
aria-label="Clear input"
|
||||
:style="{ right: isMac ? '50px' : '68px' }"
|
||||
>
|
||||
<Icon
|
||||
:iconNode="x"
|
||||
:size="20"
|
||||
/>
|
||||
</IconButton>
|
||||
<kbd
|
||||
v-if="shortcut"
|
||||
class="shortcut"
|
||||
@@ -73,6 +95,7 @@ defineExpose({
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.input {
|
||||
justify-content: flex-start;
|
||||
border: 1px solid transparent;
|
||||
@@ -82,7 +105,10 @@ defineExpose({
|
||||
height: 40px;
|
||||
background-color: var(--vp-c-bg-alt);
|
||||
font-size: 14px;
|
||||
transition: border-color 0.2s ease-in-out;
|
||||
transition:
|
||||
color 0.25s,
|
||||
border-color 0.25s,
|
||||
background-color 0.25s;
|
||||
}
|
||||
|
||||
.input.has-shortcut {
|
||||
@@ -92,13 +118,23 @@ defineExpose({
|
||||
.input:hover,
|
||||
.input:focus {
|
||||
border-color: var(--vp-c-brand);
|
||||
background: var(--vp-c-bg-alt);
|
||||
}
|
||||
.input:focus {
|
||||
background-color: var(--vp-c-bg);
|
||||
}
|
||||
|
||||
.input.has-icon {
|
||||
padding-left: 52px;
|
||||
}
|
||||
|
||||
.clear-button {
|
||||
position: absolute;
|
||||
right: 68px;
|
||||
top: 9px;
|
||||
padding: 4px;
|
||||
transition: background-color .25s;
|
||||
}
|
||||
|
||||
.shortcut {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
@@ -116,10 +152,32 @@ defineExpose({
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.input[type="search"]::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.input[type="search"]::-ms-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.input[type="search"]::-o-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.input[type="search"]::-moz-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (hover: none) {
|
||||
.shortcut {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.clear-button {
|
||||
right: 16px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -132,4 +190,7 @@ defineExpose({
|
||||
color: var(--vp-c-text-2);
|
||||
pointer-events: none;
|
||||
}
|
||||
.input-wrapper > svg:has(+ .input.has-icon:focus) {
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,11 +7,8 @@ export default {
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import Input from './Input.vue';
|
||||
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
|
||||
import { search, x } from '../../../data/iconNodes';
|
||||
|
||||
const SearchIcon = createLucideIcon('search', search);
|
||||
const XIcon = createLucideIcon('close', x);
|
||||
import Icon from 'lucide-vue-next/src/Icon';
|
||||
import { search } from '../../../data/iconNodes';
|
||||
|
||||
interface Props {
|
||||
modelValue: string;
|
||||
@@ -34,10 +31,6 @@ const value = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
});
|
||||
|
||||
const clear = () => {
|
||||
value.value = '';
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -50,26 +43,12 @@ const clear = () => {
|
||||
v-model="value"
|
||||
class="input-wrapper"
|
||||
>
|
||||
<template #startIcon>
|
||||
<component
|
||||
:is="SearchIcon"
|
||||
<template #icon>
|
||||
<Icon
|
||||
:iconNode="search"
|
||||
class="search-icon"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #endIcon>
|
||||
<button
|
||||
class="clear-button"
|
||||
type="button"
|
||||
v-if="value"
|
||||
>
|
||||
<component
|
||||
:is="XIcon"
|
||||
class="x-icon"
|
||||
@click="clear"
|
||||
/>
|
||||
</button>
|
||||
</template>
|
||||
</Input>
|
||||
</template>
|
||||
|
||||
@@ -81,9 +60,7 @@ const clear = () => {
|
||||
padding: 0 10px 0 12px;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
color: var(--vp-c-text-1);
|
||||
background-color: var(--vp-c-bg-alt);
|
||||
transition: border-color 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.input:hover,
|
||||
@@ -93,31 +70,9 @@ const clear = () => {
|
||||
}
|
||||
|
||||
.input-wrapper:deep(.input) {
|
||||
/* padding: 12px 24px; */
|
||||
padding-block: 12px;
|
||||
font-size: 14px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.clear-button {
|
||||
position: absolute;
|
||||
padding: 4px;
|
||||
right: 8px;
|
||||
top: 8px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: transparent;
|
||||
border-radius: 6px;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.clear-button:hover {
|
||||
background: var(--vp-button-alt-bg);
|
||||
}
|
||||
|
||||
.input-wrapper:deep(.input)::-webkit-search-decoration,
|
||||
.input-wrapper:deep(.input)::-webkit-search-cancel-button,
|
||||
.input-wrapper:deep(.input)::-webkit-search-results-button,
|
||||
.input-wrapper:deep(.input)::-webkit-search-results-decoration {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { rotateCw } from '../../../data/iconNodes'
|
||||
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
|
||||
import IconButton from "./IconButton.vue";
|
||||
|
||||
const RotateIcon = createLucideIcon('RotateIcon', rotateCw)
|
||||
import { rotateCw } from '../../../data/iconNodes';
|
||||
import Icon from 'lucide-vue-next/src/Icon';
|
||||
import IconButton from './IconButton.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<IconButton class="reset-button">
|
||||
<RotateIcon :size="20"/>
|
||||
<Icon
|
||||
:size="20"
|
||||
:iconNode="rotateCw"
|
||||
/>
|
||||
</IconButton>
|
||||
</template>
|
||||
|
||||
@@ -32,6 +33,7 @@ const RotateIcon = createLucideIcon('RotateIcon', rotateCw)
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
/* background-color: var(--vp-c-neutral); */
|
||||
box-shadow: var(--vp-shadow-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,16 +22,16 @@ export default {
|
||||
logo: '/framework-logos/svelte.svg',
|
||||
label: 'Lucide documentation for Svelte',
|
||||
},
|
||||
{
|
||||
name: 'lucide-preact',
|
||||
logo: '/framework-logos/preact.svg',
|
||||
label: 'Lucide documentation for Preact',
|
||||
},
|
||||
{
|
||||
name: 'lucide-solid',
|
||||
logo: '/framework-logos/solid.svg',
|
||||
label: 'Lucide documentation for Solid',
|
||||
},
|
||||
{
|
||||
name: 'lucide-preact',
|
||||
logo: '/framework-logos/preact.svg',
|
||||
label: 'Lucide documentation for Preact',
|
||||
},
|
||||
{
|
||||
name: 'lucide-angular',
|
||||
logo: '/framework-logos/angular.svg',
|
||||
@@ -48,11 +48,6 @@ export default {
|
||||
logo: '/framework-logos/react-native.svg',
|
||||
label: 'Lucide documentation for React Native',
|
||||
},
|
||||
{
|
||||
name: 'lucide-flutter',
|
||||
logo: '/framework-logos/flutter.svg',
|
||||
label: 'Lucide documentation for Flutter',
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
|
||||
@@ -2,45 +2,48 @@
|
||||
import { useData } from 'vitepress';
|
||||
import { useSessionStorage } from '@vueuse/core';
|
||||
import IconButton from '../base/IconButton.vue';
|
||||
// import VPDocAsideCarbonAds from 'vitepress/dist/client/theme-default/components/VPDocAsideCarbonAds.vue'
|
||||
import { x } from '../../../data/iconNodes'
|
||||
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
|
||||
import VPDocAsideCarbonAds from 'vitepress/dist/client/theme-default/components/VPDocAsideCarbonAds.vue';
|
||||
import { x } from '../../../data/iconNodes';
|
||||
import Icon from 'lucide-vue-next/src/Icon';
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
const { theme } = useData()
|
||||
const showAd = useSessionStorage('show-carbon-ads', true)
|
||||
const carbonLoaded = ref(true)
|
||||
const { theme } = useData();
|
||||
const showAd = useSessionStorage('show-carbon-ads', true);
|
||||
const carbonLoaded = ref(true);
|
||||
|
||||
defineProps<{
|
||||
drawerOpen: boolean
|
||||
}>()
|
||||
|
||||
const CloseIcon = createLucideIcon('Close', x)
|
||||
drawerOpen: boolean;
|
||||
}>();
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
if (window?._carbonads == null) {
|
||||
carbonLoaded.value = false
|
||||
carbonLoaded.value = false;
|
||||
}
|
||||
}, 5000)
|
||||
})
|
||||
}, 5000);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="{
|
||||
'drawer-open': drawerOpen,
|
||||
'hide-ad': !(showAd && carbonLoaded)
|
||||
'hide-ad': !(showAd && carbonLoaded),
|
||||
}"
|
||||
class="floating-ad"
|
||||
v-if="theme.carbonAds"
|
||||
>
|
||||
<IconButton @click="showAd = false" class="hide-button">
|
||||
<component :is="CloseIcon" :size="20" absoluteStrokeWidth />
|
||||
<IconButton
|
||||
@click="showAd = false"
|
||||
class="hide-button"
|
||||
>
|
||||
<Icon
|
||||
:iconNode="x"
|
||||
:size="20"
|
||||
absoluteStrokeWidth
|
||||
/>
|
||||
</IconButton>
|
||||
<VPDocAsideCarbonAds
|
||||
:carbon-ads="theme.carbonAds"
|
||||
/>
|
||||
<VPDocAsideCarbonAds :carbon-ads="theme.carbonAds" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -51,7 +54,9 @@ onMounted(() => {
|
||||
bottom: 32px;
|
||||
width: 224px;
|
||||
right: 32px;
|
||||
transition: opacity 0.5s, transform 0.25s ease;
|
||||
transition:
|
||||
opacity 0.5s,
|
||||
transform 0.25s ease;
|
||||
}
|
||||
|
||||
.floating-ad.drawer-open {
|
||||
@@ -67,8 +72,11 @@ onMounted(() => {
|
||||
transform: translateY(-288px) translateX(224px);
|
||||
}
|
||||
|
||||
.floating-ad.drawer-open, .floating-ad.hide-ad {
|
||||
transition: opacity 0.25s, transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
|
||||
.floating-ad.drawer-open,
|
||||
.floating-ad.hide-ad {
|
||||
transition:
|
||||
opacity 0.25s,
|
||||
transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
|
||||
@@ -1,70 +1,68 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import ButtonMenu from '../base/ButtonMenu.vue'
|
||||
import ButtonMenu from '../base/ButtonMenu.vue';
|
||||
import { useIconStyleContext } from '../../composables/useIconStyle';
|
||||
import useConfetti from '../../composables/useConfetti';
|
||||
import getSVGIcon from '../../utils/getSVGIcon';
|
||||
import downloadData from '../../utils/downloadData';
|
||||
|
||||
const downloadText = 'Download!'
|
||||
const copiedText = 'Copied!'
|
||||
const confettiText = ref(copiedText)
|
||||
const downloadText = 'Download!';
|
||||
const copiedText = 'Copied!';
|
||||
const confettiText = ref(copiedText);
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
popoverPosition?: 'top' | 'bottom'
|
||||
}>()
|
||||
name: string;
|
||||
popoverPosition?: 'top' | 'bottom';
|
||||
}>();
|
||||
|
||||
const { size } = useIconStyleContext()
|
||||
const { size } = useIconStyleContext();
|
||||
|
||||
const { animate, confetti } = useConfetti()
|
||||
const { animate, confetti } = useConfetti();
|
||||
|
||||
function copySVG() {
|
||||
confettiText.value = copiedText
|
||||
const svgString = getSVGIcon()
|
||||
confettiText.value = copiedText;
|
||||
const svgString = getSVGIcon();
|
||||
|
||||
navigator.clipboard.writeText(svgString)
|
||||
navigator.clipboard.writeText(svgString);
|
||||
|
||||
confetti()
|
||||
confetti();
|
||||
}
|
||||
|
||||
function copyDataUrl() {
|
||||
confettiText.value = copiedText
|
||||
const svgString = getSVGIcon()
|
||||
confettiText.value = copiedText;
|
||||
const svgString = getSVGIcon();
|
||||
|
||||
// Create SVG data url
|
||||
const dataUrl = `data:image/svg+xml;base64,${btoa(svgString)}`
|
||||
navigator.clipboard.writeText(dataUrl)
|
||||
const dataUrl = `data:image/svg+xml;base64,${btoa(svgString)}`;
|
||||
navigator.clipboard.writeText(dataUrl);
|
||||
|
||||
confetti()
|
||||
confetti();
|
||||
}
|
||||
|
||||
function downloadSVG() {
|
||||
confettiText.value = downloadText
|
||||
const svgString = getSVGIcon()
|
||||
confettiText.value = downloadText;
|
||||
const svgString = getSVGIcon();
|
||||
|
||||
downloadData(`${props.name}.svg`, `data:image/svg+xml;base64,${btoa(svgString)}`)
|
||||
confetti()
|
||||
downloadData(`${props.name}.svg`, `data:image/svg+xml;base64,${btoa(svgString)}`);
|
||||
confetti();
|
||||
}
|
||||
|
||||
function downloadPNG() {
|
||||
confettiText.value = downloadText
|
||||
const svgString = getSVGIcon()
|
||||
confettiText.value = downloadText;
|
||||
const svgString = getSVGIcon();
|
||||
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = size.value;
|
||||
canvas.height = size.value;
|
||||
const ctx = canvas.getContext("2d");
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
const image = new Image();
|
||||
image.src = `data:image/svg+xml;base64,${btoa(svgString)}`;
|
||||
image.onload = function() {
|
||||
image.onload = function () {
|
||||
ctx.drawImage(image, 0, 0);
|
||||
downloadData(`${props.name}.png`, canvas.toDataURL('image/png'))
|
||||
confetti()
|
||||
}
|
||||
downloadData(`${props.name}.png`, canvas.toDataURL('image/png'));
|
||||
confetti();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -75,10 +73,10 @@ function downloadPNG() {
|
||||
:data-confetti-text="confettiText"
|
||||
:popoverPosition="popoverPosition"
|
||||
:options="[
|
||||
{ text: 'Copy SVG' , onClick: copySVG },
|
||||
{ text: 'Copy Data URL' , onClick: copyDataUrl },
|
||||
{ text: 'Download SVG' , onClick: downloadSVG },
|
||||
{ text: 'Download PNG' , onClick: downloadPNG },
|
||||
{ text: 'Copy SVG', onClick: copySVG },
|
||||
{ text: 'Copy Data URL', onClick: copyDataUrl },
|
||||
{ text: 'Download SVG', onClick: downloadSVG },
|
||||
{ text: 'Download PNG', onClick: downloadPNG },
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -1,41 +1,44 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, useSlots } from 'vue';
|
||||
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
|
||||
import { copy } from '../../../data/iconNodes'
|
||||
import { copy } from '../../../data/iconNodes';
|
||||
import useConfetti from '../../composables/useConfetti';
|
||||
const { animate, confetti } = useConfetti()
|
||||
const slots = useSlots()
|
||||
import Icon from 'lucide-vue-next/src/Icon';
|
||||
const { animate, confetti } = useConfetti();
|
||||
const slots = useSlots();
|
||||
|
||||
const copiedText = computed(() => slots.default?.()[0].children)
|
||||
const copiedText = computed(() => slots.default?.()[0].children);
|
||||
|
||||
function copyText() {
|
||||
navigator.clipboard.writeText(copiedText.value)
|
||||
navigator.clipboard.writeText(copiedText.value);
|
||||
|
||||
confetti()
|
||||
confetti();
|
||||
}
|
||||
|
||||
const Copy = createLucideIcon('ChevronUp', copy)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1
|
||||
class="icon-name confetti-button"
|
||||
:class="{animate}"
|
||||
:class="{ animate }"
|
||||
data-confetti-text="Copied!"
|
||||
@click="copyText"
|
||||
>
|
||||
<slot />
|
||||
<Copy :size="20" class="copy-icon"/>
|
||||
<Icon
|
||||
:iconNode="copy"
|
||||
:size="20"
|
||||
class="copy-icon"
|
||||
/>
|
||||
</h1>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@import './confetti.css';
|
||||
|
||||
.icon-name {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
line-height: 32px;
|
||||
transition: background ease-in .15s;;
|
||||
transition: background ease-in 0.15s;
|
||||
padding: 2px 8px;
|
||||
border-radius: 8px;
|
||||
width: auto;
|
||||
@@ -48,7 +51,7 @@ const Copy = createLucideIcon('ChevronUp', copy)
|
||||
}
|
||||
|
||||
.icon-name:hover .copy-icon {
|
||||
opacity: .9;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.icon-name:before,
|
||||
@@ -65,10 +68,10 @@ const Copy = createLucideIcon('ChevronUp', copy)
|
||||
opacity: 0;
|
||||
margin-left: 12px;
|
||||
margin-top: 6px;
|
||||
transition:ease .3s opacity;
|
||||
transition: ease 0.3s opacity;
|
||||
}
|
||||
|
||||
.icon-name:hover .copy-icon:hover {
|
||||
opacity: .6;
|
||||
opacity: 0.6;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -153,7 +153,7 @@ function handleCloseDrawer() {
|
||||
>
|
||||
<StickyBar class="category-search">
|
||||
<InputSearch
|
||||
:placeholder="`Search ${icons.length} icons ...`"
|
||||
:placeholder="`Search ${icons.length} icons…`"
|
||||
v-model="searchQuery"
|
||||
:shortcut="kbdSearchShortcut"
|
||||
class="input-wrapper"
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import { getAllData } from '../../../lib/icons';
|
||||
import { getAllCategoryFiles, mapCategoryIconCount } from '../../../lib/categories';
|
||||
import iconsMetaData from '../../../data/iconMetaData';
|
||||
import { fetchAllReleases } from '../../../../scripts/writeReleaseMetadata.mts';
|
||||
import { satisfies } from 'semver';
|
||||
|
||||
export default {
|
||||
async load() {
|
||||
const versions = await fetchAllReleases();
|
||||
|
||||
const mappedVersions = versions
|
||||
.map((tag) => tag.replace('v', ''))
|
||||
.reverse()
|
||||
|
||||
mappedVersions.length = 100
|
||||
|
||||
return {
|
||||
versions: mappedVersions,
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, defineAsyncComponent, onMounted, watch, watchEffect } from 'vue';
|
||||
import { ref, computed, defineAsyncComponent, onMounted, watch } from 'vue';
|
||||
import type { IconEntity } from '../../types';
|
||||
import { useElementSize, useEventListener, useVirtualList } from '@vueuse/core';
|
||||
import { useRoute } from 'vitepress';
|
||||
@@ -11,13 +11,9 @@ import useSearchShortcut from '../../utils/useSearchShortcut';
|
||||
import StickyBar from './StickyBar.vue';
|
||||
import useFetchTags from '../../composables/useFetchTags';
|
||||
import useFetchCategories from '../../composables/useFetchCategories';
|
||||
import useFetchVersionIcons from '../../composables/useFetchVersionIcons';
|
||||
import chunkArray from '../../utils/chunkArray';
|
||||
import CarbonAdOverlay from './CarbonAdOverlay.vue';
|
||||
import VersionSelect from './VersionSelect.vue';
|
||||
import { sort, satisfies } from 'semver';
|
||||
import useSearchPlaceholder from '../../utils/useSearchPlaceholder.ts';
|
||||
import { data as versionData } from './IconsOverview.data';
|
||||
|
||||
const ICON_SIZE = 56;
|
||||
const ICON_GRID_GAP = 8;
|
||||
@@ -36,15 +32,9 @@ const props = defineProps<{
|
||||
}>();
|
||||
|
||||
const activeIconName = ref(null);
|
||||
const selectedVersion = ref();
|
||||
|
||||
const { execute: fetchTags, data: tags } = useFetchTags();
|
||||
const { execute: fetchCategories, data: categories } = useFetchCategories();
|
||||
const { execute: fetchVersionIcons, data: versionIcons } = useFetchVersionIcons(selectedVersion);
|
||||
|
||||
watch(selectedVersion, () => {
|
||||
fetchVersionIcons();
|
||||
});
|
||||
|
||||
const overviewEl = ref<HTMLElement | null>(null);
|
||||
const { width: containerWidth } = useElementSize(overviewEl);
|
||||
@@ -54,31 +44,20 @@ const columnSize = computed(() => {
|
||||
});
|
||||
|
||||
const mappedIcons = computed(() => {
|
||||
let icons = props.icons;
|
||||
|
||||
if (tags.value != null && categories.value != null) {
|
||||
icons = props.icons.map((icon) => {
|
||||
const iconTags = tags.value[icon.name];
|
||||
const iconCategories = categories.value?.[icon.name] ?? [];
|
||||
|
||||
return {
|
||||
...icon,
|
||||
tags: iconTags,
|
||||
categories: iconCategories,
|
||||
};
|
||||
});
|
||||
if (tags.value == null) {
|
||||
return props.icons;
|
||||
}
|
||||
|
||||
if (selectedVersion.value == null || versionIcons.value == null) {
|
||||
console.log('no release info');
|
||||
return props.icons.map((icon) => {
|
||||
const iconTags = tags.value[icon.name];
|
||||
const iconCategories = categories.value?.[icon.name] ?? [];
|
||||
|
||||
return icons;
|
||||
}
|
||||
|
||||
return Object.values(versionIcons.value).filter(([name, iconNode]) => ({
|
||||
name,
|
||||
iconNode,
|
||||
}));
|
||||
return {
|
||||
...icon,
|
||||
tags: iconTags,
|
||||
categories: iconCategories,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
|
||||
@@ -128,12 +107,6 @@ function onFocusSearchInput() {
|
||||
}
|
||||
}
|
||||
|
||||
// function onFocusVersionSelect() {
|
||||
// if (releaseInfo.value == null) {
|
||||
// fetchReleaseInfo();
|
||||
// }
|
||||
// }
|
||||
|
||||
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
|
||||
|
||||
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
|
||||
@@ -156,17 +129,13 @@ function handleCloseDrawer() {
|
||||
>
|
||||
<StickyBar>
|
||||
<InputSearch
|
||||
:placeholder="`Search ${mappedIcons.length} icons ...`"
|
||||
:placeholder="`Search ${icons.length} icons…`"
|
||||
v-model="searchQuery"
|
||||
ref="searchInput"
|
||||
:shortcut="kbdSearchShortcut"
|
||||
class="input-wrapper"
|
||||
@focus="onFocusSearchInput"
|
||||
/>
|
||||
<VersionSelect
|
||||
v-model="selectedVersion"
|
||||
:versions="versionData.versions"
|
||||
/>
|
||||
</StickyBar>
|
||||
<NoResults
|
||||
v-if="searchPlaceholder.isNoResults"
|
||||
|
||||
@@ -1,75 +1,72 @@
|
||||
<script setup lang="ts">
|
||||
import { shallowRef, type Ref, watch, computed } from 'vue'
|
||||
import { useCssVar, syncRef } from '@vueuse/core'
|
||||
import { STYLE_DEFAULTS, useIconStyleContext } from '../../composables/useIconStyle'
|
||||
import RangeSlider from '../base/RangeSlider.vue'
|
||||
import InputField from '../base/InputField.vue'
|
||||
import ColorPicker from '../base/ColorPicker.vue'
|
||||
import ResetButton from '../base/ResetButton.vue'
|
||||
import Switch from '../base/Switch.vue'
|
||||
import { shallowRef, type Ref, watch, computed } from 'vue';
|
||||
import { useCssVar, syncRef } from '@vueuse/core';
|
||||
import { STYLE_DEFAULTS, useIconStyleContext } from '../../composables/useIconStyle';
|
||||
import RangeSlider from '../base/RangeSlider.vue';
|
||||
import InputField from '../base/InputField.vue';
|
||||
import ColorPicker from '../base/ColorPicker.vue';
|
||||
import ResetButton from '../base/ResetButton.vue';
|
||||
import Switch from '../base/Switch.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
rootEl?: Ref<HTMLElement>
|
||||
}>()
|
||||
rootEl?: Ref<HTMLElement>;
|
||||
}>();
|
||||
|
||||
const { color, strokeWidth, size, absoluteStrokeWidth } = useIconStyleContext()
|
||||
const documentRef = shallowRef<HTMLElement | undefined>(typeof document !== 'undefined' ? document?.documentElement : undefined)
|
||||
const { color, strokeWidth, size, absoluteStrokeWidth } = useIconStyleContext();
|
||||
const documentRef = shallowRef<HTMLElement | undefined>(
|
||||
typeof document !== 'undefined' ? document?.documentElement : undefined,
|
||||
);
|
||||
|
||||
const colorCssVar = useCssVar(
|
||||
'--customize-color',
|
||||
props.rootEl?.value ?? documentRef.value,
|
||||
{
|
||||
initialValue: `${STYLE_DEFAULTS.color}`
|
||||
}
|
||||
)
|
||||
const colorCssVar = useCssVar('--customize-color', props.rootEl?.value ?? documentRef.value, {
|
||||
initialValue: `${STYLE_DEFAULTS.color}`,
|
||||
});
|
||||
|
||||
const strokeWidthCssVar = useCssVar(
|
||||
'--customize-strokeWidth',
|
||||
props.rootEl?.value ?? documentRef.value,
|
||||
{
|
||||
initialValue: `${STYLE_DEFAULTS.strokeWidth}`
|
||||
}
|
||||
)
|
||||
initialValue: `${STYLE_DEFAULTS.strokeWidth}`,
|
||||
},
|
||||
);
|
||||
|
||||
const sizeCssVar = useCssVar(
|
||||
'--customize-size',
|
||||
props.rootEl?.value ?? documentRef.value,
|
||||
{
|
||||
initialValue: `${STYLE_DEFAULTS.size}`
|
||||
}
|
||||
)
|
||||
const sizeCssVar = useCssVar('--customize-size', props.rootEl?.value ?? documentRef.value, {
|
||||
initialValue: `${STYLE_DEFAULTS.size}`,
|
||||
});
|
||||
|
||||
syncRef(color, colorCssVar, { direction: 'ltr' })
|
||||
syncRef(strokeWidth, strokeWidthCssVar, { direction: 'ltr' })
|
||||
syncRef(size, sizeCssVar, { direction: 'ltr' })
|
||||
syncRef(color, colorCssVar, { direction: 'ltr' });
|
||||
syncRef(strokeWidth, strokeWidthCssVar, { direction: 'ltr' });
|
||||
syncRef(size, sizeCssVar, { direction: 'ltr' });
|
||||
|
||||
function resetStyle () {
|
||||
color.value = STYLE_DEFAULTS.color
|
||||
strokeWidth.value = STYLE_DEFAULTS.strokeWidth
|
||||
size.value = STYLE_DEFAULTS.size
|
||||
absoluteStrokeWidth.value = STYLE_DEFAULTS.absoluteStrokeWidth
|
||||
function resetStyle() {
|
||||
color.value = STYLE_DEFAULTS.color;
|
||||
strokeWidth.value = STYLE_DEFAULTS.strokeWidth;
|
||||
size.value = STYLE_DEFAULTS.size;
|
||||
absoluteStrokeWidth.value = STYLE_DEFAULTS.absoluteStrokeWidth;
|
||||
}
|
||||
|
||||
watch(absoluteStrokeWidth, (enabled) => {
|
||||
const htmlEl = document.documentElement
|
||||
const htmlEl = document.documentElement;
|
||||
|
||||
htmlEl.classList.toggle('absolute-stroke-width', enabled)
|
||||
})
|
||||
htmlEl.classList.toggle('absolute-stroke-width', enabled);
|
||||
});
|
||||
|
||||
const customizingActive = computed(() => {
|
||||
return color.value !== STYLE_DEFAULTS.color
|
||||
|| strokeWidth.value !== STYLE_DEFAULTS.strokeWidth
|
||||
|| size.value !== STYLE_DEFAULTS.size
|
||||
|| absoluteStrokeWidth.value !== STYLE_DEFAULTS.absoluteStrokeWidth
|
||||
})
|
||||
return (
|
||||
color.value !== STYLE_DEFAULTS.color ||
|
||||
strokeWidth.value !== STYLE_DEFAULTS.strokeWidth ||
|
||||
size.value !== STYLE_DEFAULTS.size ||
|
||||
absoluteStrokeWidth.value !== STYLE_DEFAULTS.absoluteStrokeWidth
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="customizer-card" :class="{ customized: customizingActive }">
|
||||
<div
|
||||
class="customizer-card"
|
||||
:class="{ customized: customizingActive }"
|
||||
>
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">
|
||||
Customizer
|
||||
</h2>
|
||||
<h2 class="card-title">Customizer</h2>
|
||||
<ResetButton @click="resetStyle"></ResetButton>
|
||||
</div>
|
||||
<InputField
|
||||
@@ -77,7 +74,11 @@ const customizingActive = computed(() => {
|
||||
label="Color"
|
||||
>
|
||||
<template #display>
|
||||
<ColorPicker v-model="color" id="icon-color" class="color-picker"/>
|
||||
<ColorPicker
|
||||
v-model="color"
|
||||
id="icon-color"
|
||||
class="color-picker"
|
||||
/>
|
||||
</template>
|
||||
</InputField>
|
||||
|
||||
@@ -117,7 +118,7 @@ const customizingActive = computed(() => {
|
||||
|
||||
<InputField
|
||||
id="absolute-stroke-width"
|
||||
label="Absolute Stroke width"
|
||||
label="Absolute stroke width"
|
||||
>
|
||||
<Switch
|
||||
id="absolute-stroke-width"
|
||||
@@ -143,6 +144,7 @@ const customizingActive = computed(() => {
|
||||
font-size: 16px;
|
||||
/* margin-bottom: 12px; */
|
||||
}
|
||||
|
||||
.customizer-card {
|
||||
background: var(--vp-c-bg);
|
||||
padding: 12px 24px 24px;
|
||||
@@ -151,7 +153,7 @@ const customizingActive = computed(() => {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
border: 1px solid transparent;
|
||||
transition: border-color .4s ease-in-out;
|
||||
transition: border-color 0.4s ease-in-out;
|
||||
}
|
||||
|
||||
.customizer-card.customized {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
margin-top: -32px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
margin-bottom: 32px;
|
||||
background: var(--vp-c-bg);
|
||||
box-shadow: 0 16px 24px var(--vp-c-bg);
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue';
|
||||
import {
|
||||
Combobox,
|
||||
ComboboxInput,
|
||||
ComboboxButton,
|
||||
ComboboxOptions,
|
||||
ComboboxOption,
|
||||
} from '@headlessui/vue';
|
||||
|
||||
import { chevronsUpDown, check } from '../../../data/iconNodes';
|
||||
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
|
||||
|
||||
const model = defineModel<string | undefined>();
|
||||
const props = defineProps<{
|
||||
versions: string[];
|
||||
}>();
|
||||
|
||||
let query = ref('');
|
||||
|
||||
let filteredVersions = computed(() =>
|
||||
query.value === ''
|
||||
? [...props.versions]
|
||||
: props.versions.filter((version) =>
|
||||
version
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '')
|
||||
.includes(query.value.toLowerCase().replace(/\s+/g, '')),
|
||||
),
|
||||
);
|
||||
|
||||
const emit = defineEmits(['focus']);
|
||||
|
||||
const ChevronUpDown = createLucideIcon('ChevronUpDown', chevronsUpDown);
|
||||
const Check = createLucideIcon('Check', check);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Combobox v-model="model">
|
||||
<div class="combobox-container">
|
||||
<div class="combobox-input-container">
|
||||
<ComboboxInput
|
||||
class="combobox-input"
|
||||
placeholder="Latest version"
|
||||
@change="query = $event.target.value"
|
||||
@focus="emit('focus')"
|
||||
/>
|
||||
<ComboboxButton class="combobox-button">
|
||||
<ChevronUpDown
|
||||
class="icon-chevron"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</ComboboxButton>
|
||||
</div>
|
||||
|
||||
<ComboboxOptions class="combobox-options">
|
||||
<div
|
||||
v-if="versions.length === 0 && query !== ''"
|
||||
class="combobox-no-results"
|
||||
>
|
||||
No match!
|
||||
</div>
|
||||
|
||||
<ComboboxOption
|
||||
v-for="version in filteredVersions"
|
||||
as="template"
|
||||
:key="version"
|
||||
:value="version"
|
||||
v-slot="{ selected, active }"
|
||||
>
|
||||
<li
|
||||
class="combobox-option"
|
||||
:class="{ active: active }"
|
||||
>
|
||||
<span
|
||||
class="combobox-option-text"
|
||||
:class="{ selected: selected }"
|
||||
>
|
||||
{{ version }}
|
||||
</span>
|
||||
<span
|
||||
v-if="selected"
|
||||
class="combobox-option-icon"
|
||||
:class="{ active: active }"
|
||||
>
|
||||
<Check
|
||||
class="icon-check"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</span>
|
||||
</li>
|
||||
</ComboboxOption>
|
||||
</ComboboxOptions>
|
||||
</div>
|
||||
</Combobox>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.combobox-input-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
min-width: 160px;
|
||||
cursor: default;
|
||||
overflow: hidden;
|
||||
background-color: var(--vp-c-bg-alt);
|
||||
text-align: left;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.combobox-input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
color: var(--vp-c-text-1);
|
||||
border: 1px solid transparent;
|
||||
transition: border-color 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.combobox-input:hover,
|
||||
.combobox-input:focus {
|
||||
border-color: var(--vp-c-brand);
|
||||
background: var(--vp-c-bg-alt);
|
||||
}
|
||||
|
||||
.combobox-button {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
padding: 9px 8px;
|
||||
right: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 0.5rem;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.icon-chevron {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.combobox-options {
|
||||
position: absolute;
|
||||
margin-top: 0.25rem;
|
||||
width: 100%;
|
||||
max-width: 160px;
|
||||
padding: 12px;
|
||||
min-width: 128px;
|
||||
overflow-y: auto;
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
background-color: var(--vp-c-bg-elv);
|
||||
box-shadow: var(--vp-shadow-3);
|
||||
transition: background-color 0.5s;
|
||||
max-height: 240px;
|
||||
outline: none;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.combobox-no-results {
|
||||
position: relative;
|
||||
cursor: default;
|
||||
padding: 0.5rem 1rem;
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.combobox-option {
|
||||
position: relative;
|
||||
cursor: default;
|
||||
padding: 2px 8px;
|
||||
border-radius: 6px;
|
||||
color: var(--vp-c-text-1);
|
||||
line-height: 32px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
transition:
|
||||
background-color 0.25s,
|
||||
color 0.25s;
|
||||
}
|
||||
|
||||
.combobox-option.active {
|
||||
color: var(--vp-c-brand);
|
||||
background-color: var(--vp-c-default-soft);
|
||||
}
|
||||
|
||||
.combobox-option-text {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.combobox-option-text.selected {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.combobox-option-icon {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 0.75rem;
|
||||
color: var(--vp-c-brand) !important;
|
||||
}
|
||||
|
||||
.combobox-option-icon.active {
|
||||
color: var(--vp-c-brand) !important;
|
||||
}
|
||||
|
||||
.icon-check {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,17 +0,0 @@
|
||||
import { useFetch } from '@vueuse/core';
|
||||
import { computed, Ref } from 'vue';
|
||||
|
||||
const useFetchVersionIcons = (version: Ref<string | undefined>) =>{
|
||||
const fetchUrl = computed(() => {
|
||||
if(version.value == null ) return ''
|
||||
return `https://unpkg.com/lucide-static@${version.value}/icon-nodes.json`
|
||||
})
|
||||
return useFetch<Record<string, string>>(
|
||||
fetchUrl,
|
||||
{
|
||||
refetch: true
|
||||
}
|
||||
).json();
|
||||
}
|
||||
|
||||
export default useFetchVersionIcons;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IconNode } from 'lucide-vue-next/src/createLucideIcon';
|
||||
import { type IconNode } from 'lucide-vue-next/src/types';
|
||||
import Vue from 'vue';
|
||||
|
||||
declare module '*.vue' {
|
||||
@@ -20,5 +20,6 @@ declare module 'node:module' {
|
||||
}
|
||||
|
||||
declare module '*.node.json' {
|
||||
export default IconNode;
|
||||
const value: IconNode;
|
||||
export default value;
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
---
|
||||
aside: false
|
||||
title: Contributing to Lucide
|
||||
description: Guidelines and instructions for contributing to the Lucide project.
|
||||
---
|
||||
|
||||
<!--@include: ../CONTRIBUTING.md -->
|
||||
|
||||
@@ -10,6 +10,11 @@ because they can quickly give information.
|
||||
However, not everyone can understand them easily. When using icons it is very important to consider
|
||||
the following aspects of accessibility.
|
||||
|
||||
::: info
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
You can make them accessible yourself by following the guidelines below.
|
||||
:::
|
||||
|
||||
## Provide visible labels
|
||||
|
||||
Icons are a helpful tool to improve perception, but they aren't a replacement for text.
|
||||
|
||||
@@ -167,3 +167,15 @@ import { coconut } from '@lucide/lab';
|
||||
})
|
||||
export class AppModule { }
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```html
|
||||
<lucide-icon name="check" aria-label="Task completed"></lucide-icon>
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
|
||||
|
||||
@@ -192,3 +192,19 @@ import LucideIcon from './LucideIcon.astro';
|
||||
|
||||
<LucideIcon name="Menu" />
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```jsx
|
||||
---
|
||||
import { Check } from '@lucide/astro';
|
||||
---
|
||||
|
||||
<Check aria-label="Task completed" />
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
|
||||
|
||||
@@ -131,3 +131,19 @@ const App = () => {
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```jsx
|
||||
import { Check } from 'lucide-preact';
|
||||
|
||||
const App = () => {
|
||||
return <Check aria-label="Task completed" />;
|
||||
};
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
|
||||
|
||||
@@ -102,10 +102,16 @@ The example below imports all ES Modules, so exercise caution when using it. Imp
|
||||
|
||||
### Icon Component Example
|
||||
|
||||
```jsx
|
||||
import { icons } from 'lucide-react-native';
|
||||
```tsx
|
||||
import * as icons from 'lucide-react-native/icons';
|
||||
|
||||
const Icon = ({ name, color, size }) => {
|
||||
interface IconProps {
|
||||
name: keyof typeof icons;
|
||||
color?: string;
|
||||
size?: number;
|
||||
}
|
||||
|
||||
const Icon = ({ name, color, size }: IconProps) => {
|
||||
const LucideIcon = icons[name];
|
||||
|
||||
return <LucideIcon color={color} size={size} />;
|
||||
@@ -116,11 +122,11 @@ export default Icon;
|
||||
|
||||
#### Using the Icon Component
|
||||
|
||||
```jsx
|
||||
```tsx
|
||||
import Icon from './Icon';
|
||||
|
||||
const App = () => {
|
||||
return <Icon name="house" />;
|
||||
return <Icon name="House" />;
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -109,3 +109,19 @@ const App = () => (
|
||||
<DynamicIcon name="camera" color="red" size={48} />
|
||||
);
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```jsx
|
||||
import { Check } from 'lucide-react';
|
||||
|
||||
const App = () => {
|
||||
return <Check aria-label="Task completed" />;
|
||||
};
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
|
||||
|
||||
@@ -144,3 +144,19 @@ const App = () => {
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```jsx
|
||||
import { Check } from 'lucide-solid';
|
||||
|
||||
const App = () => {
|
||||
return <Check aria-label="Task completed" />;
|
||||
};
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
|
||||
|
||||
@@ -331,3 +331,19 @@ The example below imports all ES Modules, so exercise caution when using it. Imp
|
||||
|
||||
<LucideIcon name="Menu" />
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Check } from '@lucide/svelte';
|
||||
</script>
|
||||
|
||||
<Check aria-label="Task completed" />
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
|
||||
|
||||
@@ -146,3 +146,25 @@ All other props listed above also work on the `Icon` Component.
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { Check } from 'lucide-vue-next';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Check
|
||||
color="red"
|
||||
:size="32"
|
||||
aria-label="Task completed"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
|
||||
|
||||
@@ -62,6 +62,7 @@ Here is a complete example with unpkg
|
||||
</script>
|
||||
</body>
|
||||
```
|
||||
We strongly suggest you anchor to a specific version, such as `https://unpkg.com/lucide@x.xxx.x/dist/umd/lucide.min.js`, rather than using `@latest`.
|
||||
|
||||
### With ESModules
|
||||
|
||||
@@ -203,3 +204,23 @@ createIcons({
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<body>
|
||||
<i data-lucide="house" aria-label="Home icon"></i>
|
||||
|
||||
<script src="https://unpkg.com/lucide@latest"></script>
|
||||
<script>
|
||||
lucide.createIcons();
|
||||
</script>
|
||||
</body>
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../advanced/accessibility.md).
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
---
|
||||
title: Categories
|
||||
description: Explore Lucide icons organized into various categories for easier browsing.
|
||||
layout: page
|
||||
outline: 2
|
||||
outlineTitle: Categories
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
---
|
||||
title: Icons
|
||||
description: Browse all Lucide icons.
|
||||
layout: page
|
||||
outline: 2
|
||||
outlineTitle: Categories
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# https://vitepress.dev/reference/default-theme-home-page
|
||||
layout: home
|
||||
markdownStyles: false
|
||||
titleTemplate: false
|
||||
|
||||
head:
|
||||
- - link
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
---
|
||||
title: License
|
||||
description: Review the licensing terms for using Lucide icons and resources.
|
||||
aside: false
|
||||
editLink: false
|
||||
---
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
"docs:build": "pnpm run /^prebuild:.*/ && vitepress build",
|
||||
"docs:preview": "vitepress preview",
|
||||
"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:brandStopwords": "node ./scripts/writeBrandStopwords.mts",
|
||||
"postbuild:vercelJson": "node ./scripts/writeVercelOutput.mts",
|
||||
"prebuild:iconNodes": "node ./scripts/writeIconNodes.mjs",
|
||||
"prebuild:metaJson": "node ./scripts/writeIconMetaIndex.mjs",
|
||||
"prebuild:releaseJson": "node ./scripts/writeReleaseMetadata.mjs",
|
||||
"prebuild:categoriesJson": "node ./scripts/writeCategoriesMetadata.mjs",
|
||||
"prebuild:relatedIcons": "node ./scripts/writeIconRelatedIcons.mjs",
|
||||
"prebuild:iconDetails": "node ./scripts/writeIconDetails.mjs",
|
||||
"prebuild:brandStopwords": "node ./scripts/writeBrandStopwords.mjs",
|
||||
"postbuild:vercelJson": "node ./scripts/writeVercelOutput.mjs",
|
||||
"dev": "npx nitropack dev",
|
||||
"prebuild:api": "npx nitropack prepare",
|
||||
"build:api": "npx nitropack build",
|
||||
@@ -45,8 +45,8 @@
|
||||
"element-to-path": "^1.2.1",
|
||||
"fuse.js": "^7.1.0",
|
||||
"jszip": "^3.10.1",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lodash": "^4.17.23",
|
||||
"lodash-es": "^4.17.23",
|
||||
"lucide-react": "workspace:*",
|
||||
"lucide-vue-next": "workspace:*",
|
||||
"react": "^18.3.1",
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
---
|
||||
title: Packages
|
||||
description: Discover the various packages available in the Lucide ecosystem.
|
||||
layout: page
|
||||
outline: 2
|
||||
outlineTitle: Packages
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg width="161" height="132" viewBox="0 0 161 132" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="0%" y1="50%" y2="50%" id="a"><stop stop-color="#2A3B8F" offset="0%"/><stop stop-color="#29ABE2" offset="100%"/></linearGradient><linearGradient x1="100%" y1="50%" x2="0%" y2="50%" id="c"><stop stop-color="#B4D44E" offset="0%"/><stop stop-color="#E7F716" offset="100%"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><path fill="#166DA5" d="M160.6 65.9l-17.4 29.3-24.4-29.7 24.4-28.9z"/><path fill="#8FDB69" d="M141.3 100.2l-26.5-31.7-15.9 26.6 24.7 36.1z"/><path fill="#166DA5" d="M141 31.4l-26.2 31.8-15.9-26.6L123.6.9z"/><path fill="url(#a)" opacity=".95" d="M61.1 31.4H141L123.4.7H78.7z M114.8 63.3H159l-15.9-26.8H98.8"/><path fill="url(#c)" opacity=".95" d="M141.3 100.3H61l17.6 30.5h45z M114.8 68.4H159l-15.9 26.8H98.8"/><path fill="#010101" d="M78.6 130.8L41 65.8 79.1.8H37.9L.4 65.8l37.5 65z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 936 B |
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="138" height="42" fill="none" viewBox="0 0 138 42">
|
||||
<path fill="#fff" fill-rule="evenodd" d="M138 4a3.997 3.997 0 0 0-4-4H4a4 4 0 0 0-4 4v34a4 4 0 0 0 4 4h130a4 4 0 0 0 4-4z" clip-rule="evenodd"/>
|
||||
<path fill="#000" fill-rule="evenodd" d="M27.963 16.943q1.08 0 1.864.43.783.428 1.212 1.154v-1.454h3.653V27.53H31.04v-1.454q-.429.727-1.23 1.156-.783.43-1.846.43-1.248 0-2.274-.653-1.006-.653-1.603-1.864-.578-1.23-.578-2.852t.578-2.834q.597-1.211 1.604-1.863a4.15 4.15 0 0 1 2.273-.653m1.175 3.188q-.82 0-1.36.577-.542.56-.542 1.585 0 1.006.541 1.602.54.579 1.36.579.802 0 1.343-.579.558-.578.56-1.602-.001-1.007-.56-1.585a1.76 1.76 0 0 0-1.342-.577" clip-rule="evenodd"/>
|
||||
<path fill="#000" d="M75.361 16.943q2.05 0 3.225 1.006t1.361 2.648h-3.3q-.092-.504-.447-.765-.335-.28-.913-.28-.447 0-.69.169a.55.55 0 0 0-.223.465q0 .373.429.579.428.186 1.379.39 1.137.243 1.882.541.765.3 1.324.969.578.653.578 1.79 0 .914-.541 1.64-.522.727-1.51 1.156-.969.41-2.293.41-1.417 0-2.535-.466-1.1-.485-1.752-1.304a3.47 3.47 0 0 1-.708-1.883h3.542q.075.503.466.782.39.28.968.28.448 0 .71-.186a.57.57 0 0 0 .26-.485q0-.39-.428-.578-.43-.185-1.417-.41-1.12-.223-1.865-.503a3.25 3.25 0 0 1-1.304-.914q-.54-.633-.54-1.715 0-.93.502-1.677.504-.765 1.473-1.211.989-.448 2.367-.448"/>
|
||||
<path fill="#000" fill-rule="evenodd" d="M94.305 16.943q1.564 0 2.796.653a4.8 4.8 0 0 1 1.957 1.863q.726 1.212.727 2.834 0 1.621-.727 2.852a4.8 4.8 0 0 1-1.957 1.864q-1.25.652-2.815.652-1.566 0-2.814-.652a4.8 4.8 0 0 1-1.939-1.864q-.709-1.212-.709-2.852 0-1.622.71-2.834a4.95 4.95 0 0 1 1.956-1.863q1.248-.653 2.815-.653m0 3.168q-.746 0-1.25.56-.502.56-.502 1.622 0 1.08.484 1.64.485.559 1.25.56.763-.001 1.267-.56.52-.578.521-1.64 0-1.063-.521-1.622a1.61 1.61 0 0 0-1.25-.56M118.921 16.943q1.081 0 1.864.43.783.428 1.212 1.154v-1.454h3.653V27.53h-3.653v-1.454q-.429.727-1.23 1.156-.784.43-1.846.43-1.248 0-2.274-.653-1.006-.653-1.603-1.864-.577-1.23-.577-2.852t.577-2.834q.597-1.211 1.603-1.863a4.15 4.15 0 0 1 2.274-.653m1.175 3.188q-.82 0-1.361.577-.54.56-.541 1.585 0 1.006.541 1.602.541.579 1.361.579.8 0 1.342-.579.558-.578.559-1.602 0-1.007-.559-1.585a1.77 1.77 0 0 0-1.342-.577M17.81 14.39q1.584 0 2.683.558 1.119.56 1.678 1.548.56.988.56 2.274 0 1.193-.56 2.18-.54.97-1.66 1.567-1.099.577-2.701.577H16v4.436h-3.653V14.39zM16 20.186h1.454q1.548 0 1.547-1.416 0-1.436-1.547-1.436h-1.454z" clip-rule="evenodd"/>
|
||||
<path fill="#000" d="m41.658 19.702 1.51-2.629h4.008l-3.56 5.331 3.69 5.126h-4.1l-1.884-2.628-1.49 2.628h-4.009l3.487-5.424-3.635-5.033h4.1zM55.42 19.33h4.456v-4.94h3.653v13.14h-3.653v-5.274h-4.455v5.274h-3.653V14.39h3.653zM69.18 27.53h-3.654V17.073h3.654zM85.919 17.073h1.9v3.038h-1.9v3.505q0 .429.186.615.204.187.671.187h1.063v3.112h-1.585q-4.008 0-4.008-3.97v-3.449H80.96v-3.038h1.286v-2.535h3.673zM108.205 20.876h-1.024q-1.194 0-1.772.466-.577.465-.577 1.622v4.566h-3.654V17.073h3.654v1.846a4.76 4.76 0 0 1 1.491-1.417 3.6 3.6 0 0 1 1.882-.521zM113.075 27.53h-3.653V17.073h3.653zM67.372 12.339q.95 0 1.528.54.597.542.597 1.361 0 .801-.597 1.342-.577.523-1.528.523-.97 0-1.565-.523a1.76 1.76 0 0 1-.579-1.342q0-.82.579-1.36.596-.54 1.565-.541M111.268 12.339q.95 0 1.528.54.596.542.597 1.361 0 .801-.597 1.342-.578.522-1.528.523-.97 0-1.567-.523a1.76 1.76 0 0 1-.577-1.342q0-.82.577-1.36.597-.54 1.567-.541"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
@@ -42,7 +42,7 @@ const getRelatedIcons = (currentIcon, icons) => {
|
||||
};
|
||||
|
||||
const iconsMetaDataPromises = svgFiles.map(async (iconName) => {
|
||||
const metaDataFileContent = await fs.promises.readFile(`../icons/${iconName}`, 'utf-8');
|
||||
const metaDataFileContent = await fs.promises.readFile(`../icons/${iconName}`);
|
||||
const metaData = JSON.parse(metaDataFileContent);
|
||||
|
||||
const name = iconName.replace('.json', '');
|
||||
@@ -29,7 +29,7 @@ if (!fs.existsSync(releaseMetaDataDirectory)) {
|
||||
fs.mkdirSync(releaseMetaDataDirectory);
|
||||
}
|
||||
|
||||
export const fetchAllReleases = async () => {
|
||||
const fetchAllReleases = async () => {
|
||||
await git.fetch('https://github.com/lucide-icons/lucide.git', '--tags');
|
||||
|
||||
return Promise.all(
|
||||
@@ -73,7 +73,7 @@ const comparisonsPromises = tags.map(async (tag, index) => {
|
||||
const comparisons = await Promise.all(comparisonsPromises);
|
||||
const newReleaseMetaData = {};
|
||||
|
||||
comparisons.forEach(({ tag, iconFiles, date } = {} as typeof comparisons[number]) => {
|
||||
comparisons.forEach(({ tag, iconFiles, date } = {}) => {
|
||||
if (tag == null) return;
|
||||
|
||||
iconFiles.forEach(({ status, file, renamedFile }) => {
|
||||
@@ -11,7 +11,7 @@ const iconMetaData = await getIconMetaData(path.resolve(scriptDir, '../../icons'
|
||||
const iconAliasesRedirectRoutes = Object.entries(iconMetaData)
|
||||
.filter(([, { aliases }]) => aliases?.length)
|
||||
.map(([iconName, { aliases }]) => {
|
||||
const aliasRouteMatches = aliases.map((alias) => typeof alias === 'string' ? alias : alias.name).join('|');
|
||||
const aliasRouteMatches = aliases.map((alias) => alias.name).join('|');
|
||||
|
||||
return {
|
||||
src: `/icons/${aliasRouteMatches}`,
|
||||
@@ -1,4 +1,5 @@
|
||||
---
|
||||
title: Showcase
|
||||
layout: page
|
||||
outline: 2
|
||||
outlineTitle: Showcase
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"karsa-mistmere",
|
||||
"jamiemlaw"
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"plaster",
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<path d="M10 14.01h.01" />
|
||||
<path d="M14 10.01h.01" />
|
||||
<path d="M14 14.01h.01" />
|
||||
<path d="M18 6v11.5" />
|
||||
<path d="M18 6v12" />
|
||||
<path d="M6 6v12" />
|
||||
<rect x="2" y="6" width="20" height="12" rx="2" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 426 B After Width: | Height: | Size: 424 B |
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"danielbayley"
|
||||
"danielbayley",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"alarm",
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M10.268 21a2 2 0 0 0 3.464 0" />
|
||||
<path d="M13.916 2.314A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.74 7.327A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673 9 9 0 0 1-.585-.665" />
|
||||
<circle cx="18" cy="8" r="3" />
|
||||
<path d="M11.68 2.009A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673c-.824-.85-1.678-1.731-2.21-3.348" />
|
||||
<circle cx="18" cy="5" r="3" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 418 B After Width: | Height: | Size: 431 B |
@@ -9,9 +9,9 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="m19 3 1 1" />
|
||||
<path d="m20 2-4.5 4.5" />
|
||||
<path d="M20 7.898V21a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20" />
|
||||
<path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2h7.844" />
|
||||
<circle cx="14" cy="8" r="2" />
|
||||
<path d="M13 2H6.5A2.5 2.5 0 0 0 4 4.5v15" />
|
||||
<path d="M17 2v6" />
|
||||
<path d="M17 4h2" />
|
||||
<path d="M20 15.2V21a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20" />
|
||||
<circle cx="17" cy="10" r="2" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 412 B After Width: | Height: | Size: 399 B |
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"danielbayley"
|
||||
"danielbayley",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"read",
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2Z" />
|
||||
<path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z" />
|
||||
<path d="m9 10 2 2 4-4" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 301 B After Width: | Height: | Size: 371 B |
@@ -2,7 +2,8 @@
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"siarie",
|
||||
"ericfennis"
|
||||
"ericfennis",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"delete",
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z" />
|
||||
<line x1="15" x2="9" y1="10" y2="10" />
|
||||
<path d="M15 10H9" />
|
||||
<path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 317 B After Width: | Height: | Size: 366 B |
@@ -2,7 +2,8 @@
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"siarie",
|
||||
"ericfennis"
|
||||
"ericfennis",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"add"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z" />
|
||||
<line x1="12" x2="12" y1="7" y2="13" />
|
||||
<line x1="15" x2="9" y1="10" y2="10" />
|
||||
<path d="M12 7v6" />
|
||||
<path d="M15 10H9" />
|
||||
<path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 359 B After Width: | Height: | Size: 389 B |
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"danielbayley"
|
||||
"danielbayley",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"read",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2Z" />
|
||||
<path d="m14.5 7.5-5 5" />
|
||||
<path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z" />
|
||||
<path d="m9.5 7.5 5 5" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 329 B After Width: | Height: | Size: 399 B |
@@ -4,9 +4,18 @@
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"siarie",
|
||||
"ericfennis"
|
||||
"ericfennis",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"save",
|
||||
"favorite",
|
||||
"mark",
|
||||
"label",
|
||||
"attachment",
|
||||
"file",
|
||||
"stick",
|
||||
"pin",
|
||||
"read",
|
||||
"clip",
|
||||
"marker",
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z" />
|
||||
<path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 275 B After Width: | Height: | Size: 342 B |
@@ -2,7 +2,8 @@
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"danielbayley",
|
||||
"jamiemlaw"
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"issue",
|
||||
|
||||
@@ -10,13 +10,15 @@
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M12 20v-8" />
|
||||
<path d="M12.656 7H14a4 4 0 0 1 4 4v1.344" />
|
||||
<path d="M14.12 3.88 16 2" />
|
||||
<path d="M15 7.13V6a3 3 0 0 0-5.14-2.1L8 2" />
|
||||
<path d="M18 12.34V11a4 4 0 0 0-4-4h-1.3" />
|
||||
<path d="M17.123 17.123A6 6 0 0 1 6 14v-3a4 4 0 0 1 1.72-3.287" />
|
||||
<path d="m2 2 20 20" />
|
||||
<path d="M21 5a4 4 0 0 1-3.55 3.97" />
|
||||
<path d="M22 13h-3.34" />
|
||||
<path d="M22 13h-3.344" />
|
||||
<path d="M3 21a4 4 0 0 1 3.81-4" />
|
||||
<path d="M3 5a4 4 0 0 0 3.55 3.97" />
|
||||
<path d="M6 13H2" />
|
||||
<path d="M7.7 7.7A4 4 0 0 0 6 11v3a6 6 0 0 0 11.13 3.13" />
|
||||
<path d="m8 2 1.88 1.88" />
|
||||
<path d="M9.712 4.06A3 3 0 0 1 15 6v1.13" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 579 B After Width: | Height: | Size: 656 B |
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"nickveles"
|
||||
],
|
||||
"tags": [
|
||||
"cannabis",
|
||||
"weed",
|
||||
"leaf"
|
||||
],
|
||||
"categories": [
|
||||
"nature"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M12 22v-4c1.5 1.5 3.5 3 6 3 0-1.5-.5-3.5-2-5" />
|
||||
<path d="M13.988 8.327C13.902 6.054 13.365 3.82 12 2a9.3 9.3 0 0 0-1.445 2.9" />
|
||||
<path d="M17.375 11.725C18.882 10.53 21 7.841 21 6c-2.324 0-5.08 1.296-6.662 2.684" />
|
||||
<path d="m2 2 20 20" />
|
||||
<path d="M21.024 15.378A15 15 0 0 0 22 15c-.426-1.279-2.67-2.557-4.25-2.907" />
|
||||
<path d="M6.995 6.992C5.714 6.4 4.29 6 3 6c0 2 2.5 5 4 6-1.5 0-4.5 1.5-5 3 3.5 1.5 6 1 6 1-1.5 1.5-2 3.5-2 5 2.5 0 4.5-1.5 6-3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 681 B |
@@ -5,7 +5,8 @@
|
||||
"csandman",
|
||||
"ericfennis",
|
||||
"karsa-mistmere",
|
||||
"lscheibel"
|
||||
"lscheibel",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"weather",
|
||||
|
||||
@@ -11,5 +11,5 @@
|
||||
>
|
||||
<path d="M12 12v4" />
|
||||
<path d="M12 20h.01" />
|
||||
<path d="M17 18h.5a1 1 0 0 0 0-9h-1.79A7 7 0 1 0 7 17.708" />
|
||||
<path d="M8.128 16.949A7 7 0 1 1 15.71 8h1.79a1 1 0 0 1 0 9h-1.642" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 322 B After Width: | Height: | Size: 331 B |
@@ -10,5 +10,5 @@
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="m17 15-5.5 5.5L9 18" />
|
||||
<path d="M5 17.743A7 7 0 1 1 15.71 10h1.79a4.5 4.5 0 0 1 1.5 8.742" />
|
||||
<path d="M5.516 16.07A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 3.501 7.327" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 316 B After Width: | Height: | Size: 320 B |
@@ -9,7 +9,7 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M10.94 5.274A7 7 0 0 1 15.71 10h1.79a4.5 4.5 0 0 1 4.222 6.057" />
|
||||
<path d="M18.796 18.81A4.5 4.5 0 0 1 17.5 19H9A7 7 0 0 1 5.79 5.78" />
|
||||
<path d="m2 2 20 20" />
|
||||
<path d="M5.782 5.782A7 7 0 0 0 9 19h8.5a4.5 4.5 0 0 0 1.307-.193" />
|
||||
<path d="M21.532 16.5A4.5 4.5 0 0 0 17.5 10h-1.79A7.008 7.008 0 0 0 10 5.07" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 388 B After Width: | Height: | Size: 385 B |
@@ -2,7 +2,8 @@
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"ericfennis",
|
||||
"karsa-mistmere"
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"weather",
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M17.5 21H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z" />
|
||||
<path d="M22 10a3 3 0 0 0-3-3h-2.207a5.502 5.502 0 0 0-10.702.5" />
|
||||
<path d="M17.5 12a1 1 0 1 1 0 9H9.006a7 7 0 1 1 6.702-9z" />
|
||||
<path d="M21.832 9A3 3 0 0 0 19 7h-2.207a5.5 5.5 0 0 0-10.72.61" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 345 B After Width: | Height: | Size: 341 B |
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"jguddas",
|
||||
"Spleefies"
|
||||
],
|
||||
"tags": [
|
||||
"storage",
|
||||
"memory",
|
||||
"container",
|
||||
"tin",
|
||||
"pot",
|
||||
"bytes",
|
||||
"servers"
|
||||
],
|
||||
"categories": [
|
||||
"devices",
|
||||
"development"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M21 11.693V5" />
|
||||
<path d="m22 22-1.875-1.875" />
|
||||
<path d="M3 12a9 3 0 0 0 8.697 2.998" />
|
||||
<path d="M3 5v14a9 3 0 0 0 9.28 2.999" />
|
||||
<circle cx="18" cy="18" r="3" />
|
||||
<ellipse cx="12" cy="5" rx="9" ry="3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 435 B |
@@ -9,9 +9,10 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M13.85 22H18a2 2 0 0 0 2-2V8a2 2 0 0 0-.586-1.414l-4-4A2 2 0 0 0 14 2H6a2 2 0 0 0-2 2v6.6" />
|
||||
<path d="M14 2v5a1 1 0 0 0 1 1h5" />
|
||||
<path d="M15 8a1 1 0 0 1-1-1V2a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8z" />
|
||||
<path d="M20 8v12a2 2 0 0 1-2 2h-4.182" />
|
||||
<path d="m3.305 19.53.923-.382" />
|
||||
<path d="M4 10.592V4a2 2 0 0 1 2-2h8" />
|
||||
<path d="m4.228 16.852-.924-.383" />
|
||||
<path d="m5.852 15.228-.383-.923" />
|
||||
<path d="m5.852 20.772-.383.924" />
|
||||
|
||||
|
Before Width: | Height: | Size: 690 B After Width: | Height: | Size: 727 B |
@@ -9,9 +9,9 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M10.65 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 2v10.1" />
|
||||
<path d="M14 2v5a1 1 0 0 0 1 1h5" />
|
||||
<path d="m10 15 1 1" />
|
||||
<path d="m11 14-4.586 4.586" />
|
||||
<circle cx="5" cy="20" r="2" />
|
||||
<path d="M4 12v6" />
|
||||
<path d="M4 14h2" />
|
||||
<path d="M9.65 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 2v4" />
|
||||
<circle cx="4" cy="20" r="2" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 463 B After Width: | Height: | Size: 445 B |
@@ -9,8 +9,8 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<circle cx="16" cy="20" r="2" />
|
||||
<path d="M10 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v2" />
|
||||
<path d="m22 14-4.5 4.5" />
|
||||
<path d="m21 15 1 1" />
|
||||
<path d="M13 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v1.36" />
|
||||
<path d="M19 12v6" />
|
||||
<path d="M19 14h2" />
|
||||
<circle cx="19" cy="20" r="2" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 418 B After Width: | Height: | Size: 413 B |
@@ -1,9 +1,18 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
"ericfennis",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"machinery",
|
||||
"industrial",
|
||||
"warehouse",
|
||||
"lifting",
|
||||
"storage",
|
||||
"equipment",
|
||||
"heavy-duty",
|
||||
"moving",
|
||||
"vehicle",
|
||||
"transport",
|
||||
"logistics"
|
||||
|
||||
@@ -10,7 +10,10 @@
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M12 12H5a2 2 0 0 0-2 2v5" />
|
||||
<path d="M15 19h7" />
|
||||
<path d="M16 19V2" />
|
||||
<path d="M6 12V7a2 2 0 0 1 2-2h2.172a2 2 0 0 1 1.414.586l3.828 3.828A2 2 0 0 1 16 10.828" />
|
||||
<path d="M7 19h4" />
|
||||
<circle cx="13" cy="19" r="2" />
|
||||
<circle cx="5" cy="19" r="2" />
|
||||
<path d="M8 19h3m5-17v17h6M6 12V7c0-1.1.9-2 2-2h3l5 5" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 377 B After Width: | Height: | Size: 483 B |
@@ -3,7 +3,8 @@
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"ericfennis"
|
||||
"ericfennis",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"code",
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<line x1="6" x2="6" y1="3" y2="15" />
|
||||
<path d="M15 6a9 9 0 0 0-9 9V3" />
|
||||
<circle cx="18" cy="6" r="3" />
|
||||
<circle cx="6" cy="18" r="3" />
|
||||
<path d="M18 9a9 9 0 0 1-9 9" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 351 B After Width: | Height: | Size: 313 B |
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"TimNekk",
|
||||
"karsa-mistmere",
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"ericfennis"
|
||||
],
|
||||
"tags": [
|
||||
"globe",
|
||||
"earth",
|
||||
"planet",
|
||||
"disable",
|
||||
"mute",
|
||||
"off",
|
||||
"hide",
|
||||
"avoid",
|
||||
"world",
|
||||
"browser",
|
||||
"language",
|
||||
"translate",
|
||||
"internet",
|
||||
"offline",
|
||||
"disconnected",
|
||||
"network",
|
||||
"connection",
|
||||
"no connection",
|
||||
"network failure",
|
||||
"signal off"
|
||||
],
|
||||
"categories": [
|
||||
"navigation",
|
||||
"connectivity",
|
||||
"devices"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<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.114 4.462A14.5 14.5 0 0 1 12 2a10 10 0 0 1 9.313 13.643" />
|
||||
<path d="M15.557 15.556A14.5 14.5 0 0 1 12 22 10 10 0 0 1 4.929 4.929" />
|
||||
<path d="M15.892 10.234A14.5 14.5 0 0 0 12 2a10 10 0 0 0-3.643.687" />
|
||||
<path d="M17.656 12H22" />
|
||||
<path d="M19.071 19.071A10 10 0 0 1 12 22 14.5 14.5 0 0 1 8.44 8.45" />
|
||||
<path d="M2 12h10" />
|
||||
<path d="m2 2 20 20" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 585 B |
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"karsa-mistmere",
|
||||
"Muhammad-Aqib-Bashir"
|
||||
],
|
||||
"tags": [
|
||||
"globe",
|
||||
"internet",
|
||||
"offline",
|
||||
"disconnected",
|
||||
"network",
|
||||
"connection",
|
||||
"world",
|
||||
"no connection",
|
||||
"network failure",
|
||||
"signal off"
|
||||
],
|
||||
"categories": [
|
||||
"connectivity",
|
||||
"devices",
|
||||
"navigation"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<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="m16 3 5 5" />
|
||||
<path d="M2 12h20A10 10 0 1 1 12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 4-10" />
|
||||
<path d="m21 3-5 5" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 341 B |