Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/lucide-icons/lucide into cl…
Browse files Browse the repository at this point in the history
…eanup
  • Loading branch information
ericfennis committed Jun 21, 2024
2 parents 997f636 + f4d451d commit 881221c
Show file tree
Hide file tree
Showing 211 changed files with 1,852 additions and 408 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ jobs:
# input: +++ b/icons/accessibility.json%0A@@ -2,0 +3 @@%0A+ "contributors": ["hi"],%0A@@ -13 +14 @@%0A+}%0A
# output: ::$ANNOTATION_SEVERITY file=icons/accessibility.json,line=2,endLine=3,title=$ANNOTATION_TITLE::$ANNOTATION_DESCRIPTION%0A%0A+ "contributors": ["hi"],%0A@@ -13 +14 @@%0A+}%0A
lint-aliases:
name: Check Uniqueness of Aliases
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Check Uniqueness of Aliases
run: ! cat <(printf "%s\\n" icons/*.json | while read -r name; do basename "$name" .json; done) <(jq -cr 'select(.aliases) | .aliases[] | if type=="string" then . else .name end' icons/*.json) | sort | uniq -c | grep -ve '^ 1 '

generate-changed-icons-comment:
runs-on: ubuntu-latest
permissions:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ docs/.vitepress/data/iconNodes
docs/.vitepress/data/iconMetaData.ts
docs/.vitepress/data/releaseMetaData.json
docs/.vitepress/data/releaseMetaData
docs/.vitepress/data/categoriesData.json
docs/.vitepress/data/iconDetails
docs/.vitepress/data/relatedIcons.json
docs/.vercel
Expand Down
1 change: 0 additions & 1 deletion docs/.vitepress/api/categories/index.get.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { eventHandler, setResponseHeader } from 'h3';
import iconMetaData from '../../data/iconMetaData';

export default eventHandler((event) => {
Expand Down
40 changes: 40 additions & 0 deletions docs/.vitepress/api/figma/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import iconNodes from '../../data/iconNodes/index.ts';
import { IconNodeWithKeys } from '../../theme/types';
import iconMetaData from '../../data/iconMetaData';
import releaseMeta from '../../data/releaseMetaData.json';
import categories from '../../data/categoriesData.json';

const dataResponse = {
icons: Object.entries(iconNodes).reduce((acc, [name, iconNode]) => {
const newIconNode = (iconNode as IconNodeWithKeys).map(([name, { key, ...attrs }]) => {
return [name, attrs];
});

acc[name] = {
iconNode: newIconNode,
aliases: (iconMetaData[name]?.aliases ?? []).map((alias) =>
typeof alias === 'string' ? alias : alias.name,
),
tags: iconMetaData[name].tags ?? [],
categories: iconMetaData[name].categories ?? [],
...releaseMeta[name],
};

return acc;
}, {}),
aliases: Object.entries(iconNodes).reduce((acc, [name]) => {
for (const alias of iconMetaData[name]?.aliases ?? []) {
acc[typeof alias === 'string' ? alias : alias.name] = name;
}

return acc;
}, {}),
categories,
};

export default eventHandler((event) => {
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400');
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');

return dataResponse;
});
1 change: 0 additions & 1 deletion docs/.vitepress/api/tags/index.get.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { eventHandler, setResponseHeader } from 'h3';
import iconMetaData from '../../data/iconMetaData';

export default eventHandler((event) => {
Expand Down
4 changes: 2 additions & 2 deletions docs/.vitepress/data/teamData.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
]
},
{
"name": "jguddas",
"title": "Maintainer of Lucide & Software engineer @lego",
"name": "Jakob Guddas",
"title": "Maintainer of Lucide & Software engineer @LEGO",
"image": "https://github.com/jguddas.png?size=192",
"socialLinks": [
{
Expand Down
8 changes: 4 additions & 4 deletions docs/.vitepress/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ const sidebar: UserConfig<DefaultTheme.Config>['themeConfig']['sidebar'] = {
{
text: 'Advanced',
items: [
// {
// text: 'Accessibility',
// link: '/guide/advanced/accessibility'
// },
{
text: 'Accessibility',
link: '/guide/advanced/accessibility',
},
{
text: 'Global styling',
link: '/guide/advanced/global-styling',
Expand Down
27 changes: 20 additions & 7 deletions docs/.vitepress/theme/components/home/HomeSponsorCard.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
<script setup lang="ts">
import Card from '../base/Card.vue'
import HomeSectionTitle from './HomeSectionTitle.vue'
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue'
import Card from '../base/Card.vue';
import HomeSectionTitle from './HomeSectionTitle.vue';
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
</script>

<template>
<HomeSectionTitle :headingLevel="3">
Sponsor the Lucide maintainers
</HomeSectionTitle>
<HomeSectionTitle :headingLevel="3"> Sponsor the Lucide maintainers </HomeSectionTitle>
<Card class="sponsor-card">
<img
src="/open-collective.png"
src="/company-logos/open-collective-light.svg"
alt="Open Collective logo"
class="logo light"
width="242"
height="42"
/>
<img
src="/company-logos/open-collective-dark.svg"
alt="Open Collective logo"
class="logo dark"
width="242"
height="42"
/>
Expand All @@ -37,6 +43,13 @@ import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vu
margin: auto 0;
}
html.dark .logo.dark {
display: none;
}
html:not(.dark) .logo.light {
display: none;
}
@media (min-width: 640px) {
.sponsor-card {
flex-direction: row;
Expand Down
7 changes: 7 additions & 0 deletions docs/.vitepress/theme/components/icons/CopyCodeButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ function copyJSX() {
navigator.clipboard.writeText(code)
}
function copyComponentName() {
const code = componentName.value
navigator.clipboard.writeText(code)
}
function copyVue() {
let attrs = ['']
Expand Down Expand Up @@ -101,6 +107,7 @@ function copyAngular() {
:popoverPosition="popoverPosition"
:options="[
{ text: 'Copy JSX' , onClick: copyJSX },
{ text: 'Copy Component Name' , onClick: copyComponentName },
{ text: 'Copy Vue' , onClick: copyVue },
{ text: 'Copy Svelte' , onClick: copyJSX },
{ text: 'Copy Angular' , onClick: copyAngular },
Expand Down
215 changes: 213 additions & 2 deletions docs/guide/advanced/accessibility.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,215 @@
---
title: Accessibility
---

# Accessibility

<!-- Description how you should use svg icons keeping web accessible -->
<!-- See @JanTrichter comment about some information to write this: https://github.com/lucide-icons/lucide/pull/1521#discussion_r1332141390 -->
Icons are pictures that show what something means without using words. They can be very helpful
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.

## Provide visible labels

Icons are a helpful tool to improve perception, but they aren't a replacement for text.

In most cases, it is probably a good idea to also provide a textual representation of your icon's
function.

![In short: Don’t rely on communicating the function of elements by icons alone. Do also provide a written description of the your interactive elements. For example: write out "On this page" on your on-page navigation element.](../../images/a11y/visible-labels.svg?raw=true)

## Contrast

Ensure there's enough contrast between the icon and its background so that it's visible to people
with low vision or color vision deficiencies.

We recommend
following [WCAG 2.1 SC 1.4.3](https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html).

![In short: use a contrast ratio of at least 4.5:1](../../images/a11y/contrast.svg?raw=true)

## Use of color

Avoid relying solely on color to convey meaning in icons, as some users may have color blindness.
Instead, use additional visual cues like shape, shading or text.

![For example: Don’t mark state with color, mark it with distinct visuals.](../../images/a11y/use-of-color.svg?raw=true)

## Interactivity

Ensure that interactive icons are accessible via keyboard navigation and provide clear feedback when
activated.

![](../../images/a11y/interactivity.svg?raw=true)

In most cases this is easily done by wrapping them in icon buttons.

## Minimum target size

Small targets can be difficult to click or touch, if your icon is interactive, we recommend that it
should have a minimum target size of 44×44 pixels.

![](../../images/a11y/target-size.svg?raw=true)

In practice, this doesn't necessarily mean that the icon itself should be this large, only its
interactive wrapper element.

## Meaningfulness

Icons should represent concepts or actions in a universally understandable way. Avoid using abstract
or ambiguous, or culture-specific symbols that might confuse some users.

![For example: Use universally understandable symbols and don't base your choice of icon on puns.](../../images/a11y/meaningfulness.svg?raw=true)

## Consistency

Maintain consistency in icon design and usage across your interface to help users learn and
understand their meanings more easily.

![For example: Don’t use the same icon for multiple distinct purposes or meanings. Don’t use different icons for the same purpose or function.](../../images/a11y/consistency.svg?raw=true)

## Text Alternatives

You may have to provide text labels or alternative text descriptions for icons, especially for
screen readers used by people with visual impairments.

However: descriptions should only be provided to standalone icons that aren't purely decorative, as
providing accessible names to non-functional elements only increases clutter when using screen
readers.

### On standalone icons

Icons are usually very unlikely to stand on their own with no semantically meaningful wrapper
element. In most cases they will be part of a badge, button (including icon buttons), navigation
item or other interactive UI element.

::: warning
In case some of your icons stand alone, and they serve a non-decorative function, make sure to
provide the appropriate accessible label for them.
:::

![In short: provide accessible label for semantic icons, but not for decorative icons.](../../images/a11y/alttext-standalone.svg?raw=true)

In general try to avoid using functional icons with no interactivity, we recommend that:

1) you either add a visible description next to them, or
2) place them in badges, labels or on buttons, and at least add a tooltip to them.

In any such case, it is preferred that the accessible name be provided for these interactive
elements (badges, buttons, nav items etc.) only, _not_ the icons themselves.

### On buttons

Do not provide an accessible label to icons when used on a button, as this label will be read out by
screen readers, leading to nonsensical text.

![](../../images/a11y/alttext-buttons.svg?raw=true)

::: details Code examples

```tsx
// Don't do this
<button>
<Plus aria-label="Plus icon"/>
Add document
</button>

// Do this, just leave it
<button>
<Plus/>
Add document
</button>
```

:::

### On icon buttons

Icon buttons are buttons that do not contain any visible text apart from the icon itself (think of
the close button of a dialog for example).

As previously stated, you should provide your accessible label on the icon button itself, not the
contained icon.

![](../../images/a11y/alttext-iconbuttons.svg?raw=true)

::: details Code examples

```tsx
// Don't do this
<button class="btn-icon">
<Home/>
</button>

// Don't do this either
<button class="btn-icon">
<Home aria-label="Home icon"/>
</button>

// This works but might not be the best solution, see below
<button aria-label="Go to home" class="btn-icon">
<Home/>
</button>

// Do this instead
<button class="btn-icon">
<Home/>
<span class="visually-hidden">Go to home</span>
</button>
```

:::

## A note on `aria-label`

Although you could provide accessible labels to your elements via the `aria-label` attribute, we
generally recommend avoiding this and instead suggest that you use your chosen CSS framework's "
visually hidden" utility whenever possible. You can
[read more about why `aria-label` might not be the best solution](https://gomakethings.com/revisting-aria-label-versus-a-visually-hidden-class/).
### Example - Radix UI

Use [Radix UI's built-in accessible icon utility component](https://www.radix-ui.com/primitives/docs/utilities/accessible-icon).

```tsx
import { ArrowRightIcon } from 'lucide-react';
import { AccessibleIcon } from '@radix-ui/react-accessible-icon';

<AccessibleIcon label="Next item">
<ArrowRightIcon />
</AccessibleIcon>
```
### Example - Bootstrap

```html

<div>
<i data-lucide="phone" aria-hidden="true"></i>
<span class="visually-hidden">Phone number</span>
</div>
```

### Example - Tailwind CSS

```html

<div>
<i data-lucide="phone" aria-hidden="true"></i>
<span class="sr-only">Phone number</span>
</div>
```

If you're not sure, you may consider learning more
about [how to hide content.](https://www.a11yproject.com/posts/how-to-hide-content/)

## Further resources

We also recommend checking out the following resources about accessibility:

- [Web Content Accessibility Guidelines (WCAG) 2.1](https://www.w3.org/TR/WCAG21/)
- [Web Accessibility Initiative (WAI)](https://www.w3.org/WAI/)
- [Learn accessibility on web.dev](https://web.dev/learn/accessibility)
- [Inclusive Components](https://inclusive-components.design/)
- [A11yTalks](https://www.a11ytalks.com/)
- [A11y automation tracker](https://a11y-automation.dev/)
- [The A11Y Project](https://www.a11yproject.com/)
6 changes: 6 additions & 0 deletions docs/guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ As new applications with specific features arise, Lucide aims to provide a compl

In addition to design, code is also important. Assets like icons can significantly increase bandwidth usage in web projects. With the growing internet, Lucide has a responsibility to keep their assets as small as possible. To achieve this, Lucide uses SVG compression and specific code architecture for tree-shaking abilities. After tree-shaking, you only ship the icons you used, which helps to keep software distribution size to a minimum.

## Accessibility

Icons are pictures that show what something means without using words. They can be very helpful because they can quickly give information.

However, not everyone can understand them easily. Read more about [how to use Lucide in an accessible way](./advanced/accessibility.md).

## Official Packages

Lucide's official packages are designed to work on different platforms, making it easier for users to integrate icons into their projects. The packages are available for various technologies, including [Web (Vanilla)](https://lucide.dev/guide/packages/lucide), [React](https://lucide.dev/guide/packages/lucide-react), [React Native](https://lucide.dev/guide/packages/lucide-react-native), [Vue](https://lucide.dev/guide/packages/lucide-vue), [Vue 3](https://lucide.dev/guide/packages/lucide-vue-next), [Svelte](https://lucide.dev/guide/packages/lucide-svelte),[Preact](https://lucide.dev/guide/packages/lucide-preact), [Solid](https://lucide.dev/guide/packages/lucide-solid), [Angular](https://lucide.dev/guide/packages/lucide-angular), [NodeJS](https://lucide.dev/guide/packages/lucide-static#nodejs) and [Flutter](https://lucide.dev/guide/packages/lucide-flutter).
Expand Down
Loading

0 comments on commit 881221c

Please sign in to comment.