Giter VIP home page Giter VIP logo

carbon-icons-svelte's Introduction

carbon-icons-svelte

NPM GitHub npm downloads to date

Carbon Design System SVG icons as Svelte components.

This zero dependency icon library builds Carbon Design System icons as Svelte components. Although best paired with carbon-components-svelte, these icons can be consumed standalone.

Try it in the Svelte REPL.

Installation

Install carbon-icons-svelte as a development dependency.

# Yarn
yarn add -D carbon-icons-svelte

# npm
npm i -D carbon-icons-svelte

# pnpm
pnpm i -D carbon-icons-svelte

Usage

Basic

Import the icon from the carbon-icons-svelte/lib folder. See the Icon Index for a list of supported icons.

<script>
  import Add from "carbon-icons-svelte/lib/Add.svelte";
</script>

<Add />

Custom size

Use the size prop to specify the icon size.

Supported icon sizes include 16, 20, 24, and 32.

The default size is 16.

<Add size={16} />
<Add size={20} />
<Add size={24} />
<Add size={32} />

Custom props

$$restProps are forwarded to the svg element.

You can use fill to customize the color or pass any other valid svg attribute to the component.

<Add fill="red" class="icon" />

Labelled

<Add aria-label="Add" />

Labelled icon that is focusable

<Add aria-label="Add" tabindex="0" />

Labelled by

<label id="add-file">Add file</label>

<Add aria-labelledby="add-file" />

API

Props

All props are optional.

Name Type Default value
size 16 | 20 | 24 | 32 16
title string undefined

License

Apache 2.0

carbon-icons-svelte's People

Contributors

alexander-mart avatar bartosjiri avatar dependabot-preview[bot] avatar dependabot[bot] avatar imgbotapp avatar metonym avatar stevemar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

carbon-icons-svelte's Issues

docs: clean-up README

  • feature Icon Index more prominently
  • provide descriptions for each recipe
  • document steps to provide a custom fill color

Update the Twitter SVG to X SVG

Here's the official SVG provided by the X brand toolkit:

<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1227" viewBox="0 0 1200 1227" fill="none">
<path d="M714.163 519.284L1160.89 0H1055.03L667.137 450.887L357.328 0H0L468.492 681.821L0 1226.37H105.866L515.491 750.218L842.672 1226.37H1200L714.137 519.284H714.163ZM569.165 687.828L521.697 619.934L144.011 79.6944H306.615L611.412 515.685L658.88 583.579L1055.08 1150.3H892.476L569.165 687.854V687.828Z" fill="white"/>
</svg>

Fix generated `build-info.json` with correct icons and classification

This was flagged in #158 (review)

The current build-info.json generated by index.ts is used by the documentation site. The impact of this bug is that the documentation site for icons may omit/misclassify certain icons.

The current script relies on the module name from @carbon/icons/metadata.json to categorize modules into glyphs or icons. It should instead use the metadata from that file to determine the groupings.

{
  "name": "low-severity",
  "friendlyName": "Low severity",
  "sizes": [
    "glyph"
  ]
  // ...
}

Package optimizations

From: carbon-design-system/carbon-components-svelte#1613 (comment)

Looking at packaging options, I looked into unplugin-icons for Iconify. I see the full Carbon icon set is provided by Iconify and there's a Svelte implementation: https://icon-sets.iconify.design/carbon/4k/. Perhaps consumers of carbon-components-svelte can have the privilege of choice; they may:

  1. Consume the forthcoming carbon-icons-svelte featuring the full Carbon icon set in node_modules
  2. Use unplugin-icons, giving you options to use Iconify-hosted icons or have Vite process them and be bundled in shipped code via the ?raw suffix
  3. Use Iconify's Svelte implementation to use their CDN-hosted icons that includes the Carbon icon set

Folks with certain enterprise restrictions should be able to determine which would work best for them, and we can help document the pros and cons of each option.

And: carbon-design-system/carbon-components-svelte#1561 (comment)

It may be worth thinking about how carbon-icons-svelte is setup. I've been using svelte-awesome for icons and it is very fast as it only has ~5 .svelte files. That could possibly be a better approach than generating lots of .svelte files

Ideally, we want to ship a single Icon.svelte component that can return inlined SVGs via @html. This should improve vite dev performance.

Mention breaking changes of upstream library in release notes?

v11 comes with the breaking changes of @carbon/icons, I specifically noticed that the Delete icon was gone and found out that TrashCan is what should be used (descriptive over semantic 👍).

Apparently Delete along with several other other icons has been removed as it had been previously deprecated.

Not sure why this is marked as "feature" in the release notes 😅

New features 🚀

Also, the lack of a closing } here bugs me:
image

Improve security practices for `carbon-icons-svelte`

Hey there, Carbon team member here! 👋 We'd like to ensure the security practices for packages published from the carbon-design-system GitHub org are in place and up to date. We'd like to work with you to get the following security practices implemented:

Tasks

Most of these can be found under the Security tab for this repository. You may already have most of these implemented and turned on - if so, awesome!

For establishing a security policy, the existing security policy for the Carbon monorepo can be used as a template if you'd like. It can be modified to include proper version(s) for your package and any other attributes unique to your project that you may want to highlight.

I'm happy to meet up and chat about this if you'd like, just let me know. Thanks in advance for your help in ensuring security and stability across the Carbon ecosystem! 🙏 💙

Use named imports in docs

Current example:

<script>
  import Accessibility from "carbon-icons-svelte/lib/Accessibility.svelte";
</script>

<Accessibility />

Proposed example:

<script>
  import { Accessibility } from "carbon-icons-svelte";
</script>

<Accessibility />

Since a lot of the time Icons can be autocompleted, using named imports is something users may expect.

image

feat: add data selector based on module name

Add a data selector for easier querying to facilitate automated testing or client-side analytics.

The data selector could support an optional, arbitrary data value to be serialized as a string.

Examples

<script>
  export let data = undefined;
</script>

<svg data-icon-module-name ... />
<svg data-icon-module-name={data ? JSON.stringify(data) : undefined} ... />

Icon type lacks constructor.

Currently you get type errors when trying to construct a carbon icon programmatically with TypeScript.

E.g.

new Edit20({ target: element });

Expected 0 arguments, but got 1. ts(2554)

CarbonIcon should probably extend SvelteComponentDev, because that is where the common component constructor signature is defined. Alternatively the constructor definition could be copied over into the icon type.

Package crashes npm, yarn, & node several times

I'd tried installing and using (only successfully installed once) the package alongside carbon-components-svelte (worked pretty fine), but it almost never actually successfully installed. It'd always crash during the installation process via yarn.
Only time it actually installed, upon running "npm run dev", or "yarn dev", nodejs throws "Heap Out Of Memory Error". Debugged quite a while and discovered the problem's from this package.
Was first using elderjs, but switched up to plain ol' svelte ( as i debugged). Nothing changed.

I run Mint 20.2 (Uma) and Windows 10.
Nodejs v16.14.0
npm v8.3.1
yarn v1.22.17

Error when using icons

I get a svelte type error when using the icons.
My svelte version is 3.4.9

The error I get is:

Argument of type 'typeof SideNavItems' is not assignable to parameter of type 'ConstructorOfATypedSvelteComponent'.
  Types of construct signatures are incompatible.
    Type 'new (options: ComponentConstructorOptions<SideNavItemsProps>) => SideNavItems' is not assignable to type 'new (args: { target: any; props?: any; }) => ATypedSvelteComponent'.
      Construct signature return types 'SideNavItems' and 'ATypedSvelteComponent' are incompatible.
        The types of '$on' are incompatible between these types.
          Type '<K extends never>(type: K, callback: (e: {}[K]) => void) => () => void' is not assignable to type '(event: string, handler: ((e: any) => any) | null | undefined) => () => void'.
            Types of parameters 'callback' and 'handler' are incompatible.
              Type '((e: any) => any) | null | undefined' is not assignable to type '(e: never) => void'.
                Type 'undefined' is not assignable to type '(e: never) => void'.

Possible causes:
- You use the instance type of a component where you should use the constructor type
- Type definitions are missing for this Svelte Component. If you are using Svelte 3.31+, use SvelteComponentTyped to add a definition:
  import type { SvelteComponentTyped } from "svelte";
  class ComponentName extends SvelteComponentTyped<{propertyName: string;}> {}

I get this error on all the icons I'm using.
I also get a similar error when using the some of the components in the component library, but I made a separate issue there

Package format issue?

Hi, I'm using the icons package in a sveltekit project, and when I run the dev server with npm run dev, this is the output:
carbon-icons-svelte doesn't appear to be written in CJS, but also doesn't appear to be a valid ES module (i.e. it doesn't have "type": "module" or an .mjs extension for the entry point). Please contact the package author to fix..
Everything works fine though.

Safari highlights icon instead of whole button

On iOS Safari when tapping an icon that's inside a button, the icon gets highlighted instead of the whole button.

When removing the event forwarders the glitch goes away.

I tried to pass the event modifiers preventDefault and stopPropagation and removing all Safari builtin styling for focused elements, but still no luck.

Keyboard events are fine, this is only affected by mouse events.

Can't click on icons twice on the website

On the website, when you click once on an icon, it opens a modal with import code. When you close this modal and click on the icon again, the modal doesn't pop up

Very Much Error in run

my use

import { Save16 } from "carbon-icons-svelte";

erro such as

ERROR in ./node_modules/carbon-icons-svelte/lib/index.js 7025:0-71
Module not found: Error: Can't resolve './VolumeFileStorage24' in 'G:\Webstorm\write\Test\node_modules\carbon-icons-svelte\lib'
Did you mean 'index.js'?
BREAKING CHANGE: The request './VolumeFileStorage24' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '.mjs' file, or a '.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.
@ ./src/pages/book/components/Test.svelte 44:0-45 95:10-16 1132:2-8

....

...
...

...

ERROR in ./node_modules/carbon-icons-svelte/lib/index.js 7762:0-55
Module not found: Error: Can't resolve './_4KFilled32' in 'G:\Webstorm\write\Test\node_modules\carbon-icons-svelte\lib'
Did you mean 'index.js'?
BREAKING CHANGE: The request './_4KFilled32' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '.mjs' file, or a '.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.

webpack 5.70.0 compiled with 7762 errors and 4 warnings in 140617 ms

my package.json

"dependencies": {
"@capacitor/android": "^2.4.7",
"@capacitor/cli": "^2.4.7",
"@capacitor/core": "^2.4.7",
"@codexteam/shortcuts": "^1.1.1",
"@editorjs/delimiter": "^1.2.0",
"@editorjs/editorjs": "^2.22.2",
"@editorjs/header": "^2.6.2",
"@editorjs/list": "^1.6.2",
"@editorjs/marker": "^1.2.2",
"@editorjs/paragraph": "^2.8.0",
"@editorjs/quote": "^2.4.0",
"@editorjs/underline": "^1.0.0",
"@itech-indrustries/editorjs-callout": "^1.0.0",
"@livingdocs/editable.js": "^3.0.7",
"animate.css": "^4.1.1",
"animejs": "^3.2.1",
"caret-pos": "^2.0.0",
"editorjs-alert": "^1.0.3",
"editorjs-break-line": "^0.2.1",
"editorjs-drag-drop": "^1.0.0",
"editorjs-inline-font-size-tool": "^1.0.1",
"editorjs-style": "^3.0.2",
"editorjs-text-alignment-blocktune": "^1.0.3",
"editorjs-text-color-plugin": "^1.1.22",
"editorjs-tooltip": "^1.1.0",
"editorjs-undo": "^1.0.1",
"findandreplacedomtext": "^0.4.6",
"holmes.js": "^1.17.3",
"hotkeys-js": "^3.8.7",
"hover.css": "^2.3.2",
"localforage": "^1.10.0",
"lodash": "^4.17.21",
"lunr": "^2.3.9",
"marked": "^4.0.5",
"moment": "^2.29.1",
"mousetrap": "^1.6.5",
"node-fetch": "^2.6.1",
"nzh": "^1.0.5",
"omnia-ebook-generator": "^0.2.1",
"omnia-editor": "^0.1.0",
"rxjs": "^7.4.0",
"semver": "^7.3.5",
"sortablejs": "^1.13.0",
"sveltejs-tippy": "^3.0.0",
"time-stamp": "^2.2.0",
"tippy.js": "^6.3.7",
"uuid": "^8.3.2"
},
"devDependencies": {
"@babel/core": "^7.13.10",
"@babel/preset-env": "^7.13.12",
"@carbon/charts-svelte": "^0.53.5",
"@editorjs/footnotes": "^1.1.0",
"@storybook/addon-actions": "^6.1.21",
"@storybook/addon-essentials": "^6.1.21",
"@storybook/addon-links": "^6.1.21",
"@storybook/preset-scss": "^1.0.3",
"@storybook/svelte": "^6.1.21",
"@testing-library/jest-dom": "^5.11.10",
"@testing-library/svelte": "^3.0.3",
"@testing-library/user-event": "^12.8.3",
"@types/file-saver": "^2.0.1",
"@types/findandreplacedomtext": "^0.4.1",
"@types/jest": "^26.0.22",
"@types/lodash": "^4.14.178",
"@types/lunr": "^2.3.4",
"@types/uuid": "^8.3.3",
"@typescript-eslint/eslint-plugin": "^5.7.0",
"@typescript-eslint/parser": "^5.7.0",
"appwrite": "^2.0.0",
"autoprefixer": "^10.4.0",
"babel-jest": "^26.6.3",
"babel-loader": "^8.2.2",
"carbon-components-svelte": "^0.50.1",
"carbon-icons-svelte": "^10.38.0",
"carbon-preprocess-svelte": "^0.6.0",
"cross-env": "^7.0.3",
"css-loader": "^4.3.0",
"d3": "^7.2.1",
"date-fns": "^2.19.0",
"electron": "^11.4.1",
"electron-builder": "^22.13.1",
"electron-winstaller": "^5.0.0",
"eslint": "^8.4.1",
"eslint-plugin-svelte3": "^2.7.3",
"file-loader": "^6.2.0",
"file-saver": "^2.0.5",
"husky": "^4.3.8",
"jest": "^26.6.3",
"jest-transform-svelte": "^2.1.1",
"license-checker": "^25.0.1",
"mini-css-extract-plugin": "^0.11.3",
"normalize.css": "^8.0.1",
"npm-run-all": "^4.1.5",
"postcss": "^8.4.5",
"postcss-loader": "^6.2.1",
"prettier": "^2.2.1",
"prettier-plugin-svelte": "^1.4.2",
"sass": "^1.32.8",
"sass-loader": "^10.1.1",
"style-loader": "^1.3.0",
"svelte": "^3.35.0",
"svelte-htm": "^1.1.1",
"svelte-i18n": "^3.3.7",
"svelte-jester": "^1.3.2",
"svelte-loader": "^3.1.2",
"svelte-preprocess": "^4.10.0",
"svelte-spa-router": "^3.1.0",
"ts-loader": "^9.2.6",
"typescript": "^4.5.4",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.7.2",
"workbox-webpack-plugin": "^5.1.4",
"workbox-window": "^5.1.4"
}

my webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const Autoprefixer = require("autoprefixer")
const path = require("path");
const mode = process.env.NODE_ENV || "development";
const isProduction = mode === "production";
const isDevelopment = !isProduction;
module.exports = {
entry: {
bundle: ["./src/main.js"]
},
resolve: {
alias: {
svelte: path.resolve("node_modules", "svelte" ),
src: path.resolve(__dirname, 'src')
},
extensions: [".mjs", ".js", ".svelte",'.tsx', '.ts'],
mainFields: ["svelte", "browser", "module", "main"]
},
output: {
clean: true,
path: __dirname + "/public/build",
publicPath: '/build/',
filename: "[name].js",
chunkFilename: "bundle.[name].js"
},
module: {
rules: [
{
test: /.svelte$/,
use: {
loader: "svelte-loader",
options: {
compilerOptions: {
dev: isDevelopment
},
emitCss: isProduction,
preprocess: require("svelte-preprocess")({
scss: true,
sass: true,
postcss: {
plugins: [
Autoprefixer
]
}
}),
}
}
},
{
test: /.(sa|sc|c)ss$/,
use: [
/**
* MiniCssExtractPlugin doesn't support HMR.
* For developing, use 'style-loader' instead.
* */
isProduction ? MiniCssExtractPlugin.loader : "style-loader",
"css-loader",
"sass-loader"
]
},
{
test: /.ts$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
compress: true,
hot: false,
liveReload: true,
open: true,
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css"
}),
],
mode,
devtool: isProduction ? false : "source-map"
};

Viewbox

I am often fighting positioning of icons. I have noticed this library has a viewbox always set to 0 0 32 32 (https://github.com/carbon-design-system/carbon-icons-svelte/blob/master/src/template.ts#L19) but some icons have a svg with 0 0 16 16.

Examples of these are status icons like circle-stroke, circle-fill, caution, etc.

It is problematic because the icons are hard to center like this.

Correct example of such icon svg straight from https://carbondesignsystem.com/guidelines/icons/library/
Snímek obrazovky 2023-05-24 v 15 04 20

Incorrect example of svelte icon
Snímek obrazovky 2023-05-24 v 15 06 40

TypeScript support for deeply imported Svelte components

The following is TypeScript compatible:

import Add24 from "carbon-icons-svelte/lib/Add24";

but the following isn't:

import Add24 from "carbon-icons-svelte/lib/Add24/Add24.svelte";

There needs to be a file called Add24.svelte.d.ts.

Support for custom icons?

If an icon is not contained in the provided set, it would be useful to have a generic component that can be used to define custom icons that then would be compatible with carbon-components-svelte. The fact that the props expect Carbon icon component constructors rather than say component or DOM element instances makes this a bit tricky, though.

Currently I have created my own version of such a generic component and utility functions that can dynamically create component constructors from an SVG string. There is a bit of overhead involved as the SVG is first parsed and then its contents are inserted into the SVG frame supplied by the generic component. In my case, I make sure that the viewBox matches, otherwise that would need to be transferred.

It might be difficult to provide this functionality in a way that matches all relevant use-cases, but here would be my implementation for reference:

icon.svelte (based on the carbon icon template)

<script type="text/typescript">
	let className: string | undefined = undefined;
	export { className as class };
	export let id: string | undefined = undefined;
	export let tabindex: string | undefined = undefined;
	export let focusable = false;
	export let title: string | undefined = undefined;
	export let style: string | undefined = undefined;
	export let size: number;
	export let svg: string;

	let iconGroup: SVGGElement;
  
	$: ariaLabel = $$props['aria-label'];
	$: ariaLabelledBy = $$props['aria-labelledby'];
	$: labelled = ariaLabel || ariaLabelledBy || title;
	$: attributes = {
		'aria-label': ariaLabel,
		'aria-labelledby': ariaLabelledBy,
		'aria-hidden': labelled ? undefined : true,
		role: labelled ? 'img' : undefined,
		focusable: tabindex === '0' ? true : focusable,
		tabindex
	};

	$: if (svg != null && iconGroup != null)
	{
		[...iconGroup.children].forEach(c => iconGroup.removeChild(c));
		const svgDocument = new DOMParser().parseFromString(svg, 'image/svg+xml');
		[...svgDocument.documentElement.children].forEach(c => iconGroup.appendChild(c));
	}
</script>

<svg xmlns="http://www.w3.org/2000/svg"
	width={size} height={size} viewBox="0 0 32 32"
	on:click
	on:mouseover
	on:mouseenter
	on:mouseleave
	on:keyup
	on:keydown
	fill="currentColor"
	class={className}
	preserveAspectRatio="xMidYMid meet"
	{style}
	{id}
	{...attributes}>
	<g bind:this={iconGroup}/>

	<slot>
		{#if title}
			<title>{title}</title>
		{/if}
	</slot>
</svg>

index.ts in same directory

import Icon from './icon.svelte';
import type { CarbonIcon } from 'carbon-icons-svelte';

export function icon(svg: string, size: number): typeof CarbonIcon
{
	function ctor(this: any, options: any)
	{
		const o = { ...options }
		if (o.props == null)
			o.props = {};

		o.props.svg = svg;
		o.props.size = size;

		return new Icon(o);
	}

	ctor.prototype = Object.create(Icon.prototype);

	// @ts-expect-error
	return ctor;
}

Usage defining new icons:

// Webpack imports SVGs as SVGO-optimized string
import headings from './headings.svg';
import horizontalLine from './horizontal-line.svg';
import { icon } from '../../components/utility';

export const Headings = (size: number) => icon(headings, size);
export const HorizontalLine = (size: number) => icon(horizontalLine, size);
<script type="text/typescript">
	import { Button } from 'carbon-components-svelte';
	import { Headings } from '../icons';
</script>

<Button icon={Headings(20)} />
Alternatively have all sizes hardcoded (seems a bit unnecessary though):
// Webpack imports SVGs as SVGO-optimized string
import headings from './headings.svg';
import horizontalLine from './horizontal-line.svg';
import { icon } from '../../components/utility';

export const Headings16 = icon(headings, 16);
export const Headings20 = icon(headings, 20);
export const Headings24 = icon(headings, 24);
export const Headings32 = icon(headings, 32);
export const HorizontalLine16 = icon(horizontalLine, 16);
//...
<script type="text/typescript">
	import { Button } from 'carbon-components-svelte';
	import { Headings20 } from '../icons';
</script>

<Button icon={Headings20} />

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.