Giter Site home page Giter Site logo

templarian / materialdesign-react Goto Github PK

View Code? Open in Web Editor NEW
137.0 9.0 21.0 1.64 MB

Dist for Material Design Icons React Component for JS/TypeScript

Home Page: https://materialdesignicons.com

License: MIT License

JavaScript 2.31% TypeScript 97.69%
material-design react icons

materialdesign-react's Introduction

React - Material Design Icons

Material Design Icons can be used in React with a custom component or with the one provided in this module.

View the Demo

npm install @mdi/react

Usage

The example below uses the @mdi/js package which contains all the MDI icon's path data.

import React, { Component } from 'react';
import Icon from '@mdi/react';
import { mdiAccount } from '@mdi/js';

class App extends Component {
  render() {
    return (
      <Icon path={mdiAccount}
        size={1}
        horizontal
        vertical
        rotate={90}
        color="red"/>
    );
  }
} 

Stack Usage

To layer <Icons/> nest them inside of the <Stack/> component.

import React, { Component } from 'react';
import Icon, { Stack } from '@mdi/react';
import { mdiAccount, mdiBlockHelper } from '@mdi/js';

class App extends Component {
  render() {
    return (
      <Stack color="#444">
        <Icon path={mdiAccount}/>
        <Icon path={mdiBlockHelper}
          color="red"/>
      </Stack>
    );
  }
} 

Props

Icon <Icon/>

Prop PropTypes Default Details
title string, null null A11y <title>{title}</title>
description string, null null A11y <desc>{desc}</desc>
path string required SVG path data. Usually from @mdi/js
size number, string null {size * 1.5}rem, 1em, 48px
horizontal bool false Flip Horizontal
vertical bool false Flip Vertical
rotate number 0 degrees 0 to 360
color string null rgb() / rgba() / #000
spin bool, number false true = 2s, -2 counterclockwise, {spin}s

Note: Additional props will be applied to the <svg> element.

Stack <Stack/>

All props below will override the nested <Icon/>'s default prop values.

Prop PropTypes Default Details
title string, null null A11y <title>{title}</title>
description string, null null A11y <desc>{desc}</desc>
size number, string, null null {size * 1.5}rem
horizontal bool, null null Flip Horizontal
vertical bool, null null Flip Vertical
rotate number, null null degrees 0 to 360
color string, null null rgb() / rgba() / #000
spin bool, number, null null true = 2s, -2 counterclockwise, {spin}s

Note: Additional props on <Stack> will apply to the <svg> element. Only in a <Stack> will addional props to the <Icon> component apply to the nested <path> elements.

Styling

Applying a className attribute is usually the easiest solution. The example below demonstrates using SCSS to style the icons.

In most cases it may be a good idea to set a base size. Assuming a 16px base font-size in most themes applying 1.5rem will make the icon a 24px.

svg {
  width: 1.5rem;
}

For more specific styling apply classes. To make selection of layers easier use the nth-child selector.

// For <Icon className="custom-class" />
svg.custom-class {
  path {
    fill: blue;
  }
}
// For <Stack className="custom-class">
svg.custom-class {
  // First layer (behind)
  path:nth-child(1) {
    fill: blue;
  }
  // Second layer (infront)
  path:nth-child(2) {
    fill: red;
  }
}

Accessibility

Making icons accessible can be done through the title prop. If for some rare reason more information is required a description field can also be used.

By leaving off the title prop an icon is assumed to be presentation only. These will be ignored by screen readers. This is ideal for icon buttons or areas where text next to the icon suffices.

<p><Icon path={mdiAccount} /> User Profile</p>
<p><Icon path={mdiAccount} title="User Profile" /></p>
<button aria-label="User Profile"><Icon path={mdiAccount} /></button>

Development

To develop clone the repo and run npm install.

  • src/Icon.tsx - Icon Component
    • tests/Icon.spec.tsx - Unit tests
  • src/Stack.tsx - Stack Component
    • tests/Stack.spec.tsx - Unit tests

Commands:

  • npm run start - Watch for file changes
  • npm run build - Build Icon.js
  • npm run test - Run unit tests

Note: This project is setup to use the Mocha Sidebar extension which makes it easier to view the tests.

Related Packages

NPM @MDI Organization

materialdesign-react's People

Contributors

davidjb avatar dependabot[bot] avatar jinyang1994 avatar maadhattah avatar ngburke avatar nielsrowinbik avatar templarian avatar weishiji 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

materialdesign-react's Issues

[Feature request] Add default class attribute to all svg elements

Like as other library the element should have a class to identify, Like as Font Awesome which use fa, and also should every specific element has their own icon name as a class, Like as fa-search and the final output of svg should be like this:
<svg class="mdi mdi-search [...Rest]">...
This is good idea to identify all MDI icons and also identify an specific icon.

This is a feature request and do not take personal my used words (like should), My English is not good to use best words in sentence.

How to dynamically Import Icons?

I want to load menu in my application which contains the name of the icon. But it is not showing because not imported. So how to import the icons dynamically and show it in an array

Need a way to add a title child element and ARIA attributes for sake of accessibility

There seems to be no way to add title or desc child elements, or their related ARIA attributes. Both are necessities for basic accessibility (a11y) affordances[1].

Two goals here:

  1. Be understood by accessible browsing technology like screen readers

  2. Ability to have a description of the item appear when a user hovers their mouse over the SVG icon.

Both goals can be accomplished by accommodating ARIA attributes and the title and/or desc child elements.

Remember: title and alt attributes added to the svg element are not valid, not supported by browsers, aren't read by screen readers, and don't display the tooltip on hover, and thus are insufficient for a11y concerns. To work reliably, it has to be the child element of svg, not an attribute.

With this change, I'd expect to have a title parameter on the Icon component, thusly:

<Icon 
  path={mdiShieldCheck}
  className="my-verified-badge" 
  title="Verified"
  titleId="myUniqueTitleID"
 />

Which you'd expect to yield something akin to this:

<svg aria-labelledby="myUniqueTitleID">
  <title id="..."></title>
  <path> ... </path>
</svg>

Specifically, using the mdi icon from my example:

<svg viewBox="0 0 24 24" class="my-verified-badge" aria-labelledby="myUniqueTitleID"><title id="myUniqueTitleID">Verified</title><path d="M10,17L6,13L7.41,11.59L10,14.17L16.59,7.58L18,9M12,1L3,5V11C3,16.55 6.84,21.74 12,23C17.16,21.74 21,16.55 21,11V5L12,1Z"></path></svg>

Here's an example using the desc attribute as well, which adds a description that will be read aloud by screen reader technology to give much-needed context to the SVG (here, an mdi icon):

<Icon 
  path={mdiShieldCheck}
  className="my-verified-badge" 
  title="Verified"
  titleId="myUniqueTitleID"
  description="This member is a verified member of the community."
  descId="myUniqueDescID"
 />
<svg aria-labelledby="myUniqueTitleID myUniqueDescID">
  <title id="..."></title>
  <desc id="..."></desc>
  <path> ... </path>
</svg>

Specifically, using the mdi icon from my example (line breaks added to aid in readability here):

<svg viewBox="0 0 24 24" class="my-verified-badge" aria-labelledby="myUniqueTitleID myUniqueDescID">
<title id="myUniqueTitleID">Verified</title>
<desc id="myUniqueDescID">This member is a verified member of the community.</desc>
<path d="M10,17L6,13L7.41,11.59L10,14.17L16.59,7.58L18,9M12,1L3,5V11C3,16.55 6.84,21.74 12,23C17.16,21.74 21,16.55 21,11V5L12,1Z"></path>
</svg>

All that said... has anyone else run into this issue when trying to make the icons accessible?

[1] https://css-tricks.com/accessible-svgs/

icon size

Hi, why the icon size is multiplied by 1.5 ?

I refer to this snippet:

  const width = typeof size === "string" ? size : `${size * 1.5}rem`;

I am wrapping @mdi/react icon to add isSmall, isLarge props: I expected that size would be passed as is.

How do you dynamically load an Icon?

So, in my app, I want to provide an Icon picker...let the user choose their icon. Once saved, I would use it on other pages in the app.

How do I dynamically import this specific icon on those pages?

Add 'prop-types' as a dependency (or remove it)

This library is dependent of 'prop-types'. Either loose the dependency, or add it as one in package.js instead of a devDependency.

Error after installing @mdi/react and @mdi/js to my app and starting it:

ERROR in ./node_modules/@mdi/react/Icon.js
Module not found: Error: Can't resolve 'prop-types' in '/app/node_modules/@mdi/react'
@ ./node_modules/@mdi/react/Icon.js 1:957-978

Though it is easily fixed on my side by adding 'prop-types' to my own app.

Handle relative sizes

Would be nice to have an option of either using em or rem.

Using em's can be helpful to infer icon size from where it's currently used or use css, and can allow size prop to be optional.

As an example, currently I'm using manually made icons this way:

import React, { SFC } from "react";

const Tag: SFC = props => (
  <svg viewBox="0 0 24 24" width="1em" height="1em" {...props}>
    <path
      fill="inherit"
      fillRule="evenodd"
      d="..."
    />
  </svg>
);

export default Tag;

Cannot assign to read only property 'width' of object '#<Object>' icon

If size is specified together with a read only style the component breaks.

The code bellow will produce this error: Cannot assign to read only property 'width' of object '#<Object>' icon

App.tsx

const fixedStyle = { color: "red" } as const;

export function SomeComponent(){
  return <Icon path={mdiCheck} style={fixedStyle} size={1} />
}

This issue seems to be triggered by mutating the style object in Icon.tsx L31

Build error

Hello. I am using icon set for my project. It worked fine until. But when I build and run it doesn't work. I am using vite to build the project.
The full text of the error you just encountered is:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

Version of me:
"@mdi/js": "^6.5.95",
"@mdi/react": "^1.5.0",
"react": "^17.0.2",

Release v1.0.0 on NPM

Testing for the new updated codebase is merged into master.

Only thing left is to do a NPM release. This includes 1 breaking change.

  • The size prop no longer defaults to 1, so the width: 1.5rem size will no longer show by default.
    • .container-here svg { width: 1.5rem; }

Allow color prop to inherit from parent.

Can you please change the color property to inherit the color of the parent component by default instead of null.

When using Material-UI for React, specifying the color adds unneeded complexity to theming.

For example:

import { IconButton } from "@material-ui/core";
import Icon from "@mdi/react";
import { mdiClose } from "@mdi/js";

<IconButton color="default">
   <Icon path={mdiClose} size={1} />
</IconButton>

The code snippet will render a close icon with the default color black instead of inheriting the gray color of the IconButton parent component.

An added bonus would be to allow the size prop to inherit from the parent as well.

Counter Clockwise Spin Support

Basically as the title says. Allow spin to take a negative number. -1 would be 1 second spin counter clockwise.

I have no plans to add this at the moment, just creating the issue to judge interest. If no one needs it I'll leave it off.

ToDo: TypeScript

Rewrite this component in TypeScript 3 and include the definition files like we do for @mdi/js.

Change/Disabled role in svg icon

Thanks for the library. I would like to ask how you can change the role of the svg icon. At the moment I am using react testing library for tests and it turns out not entirely correct that I am looking for the role of the presentation in the test and the icon is. I can use the title to remove the role, but this behavior is also not entirely correct for me. Thanks!

Spread extra props through

As a user of @mdi/react, I would like to pass other props through to the underlying <svg> object, such as className, so that I can add additional attributes to the Icon or Stack.

Our use case is specifically className, used to place error classes on icons and change their appearance via CSS.

Support Offsetting in Stack

It may be useful for some people to have the ability to offset when stacking icons.

<Stack>
  <Icon x={2} y={2} path={mdiAccount}/>
</Stack>

I don't have a use for this, but we've told users to use the stack to solve combining icons in the past.

`<svg>` bigger than the `<path>`

Hi,

I'm using the icon AccountBoxOutline and noticed that the <svg> is bigger than the <path> itself, so I end up getting an <svg> with content that is smaller than the <svg> itself.

Downloading the <svg> file for the icon from the website and importing that file does not provide the same problem.

What can be done to fix this? It shouldn't be like this - this is wasted space (and in my use case, space is quite necessary).

Dynamic load icons

I want to load icons which get icon names from server, is there any way to load/import them dynamically?

For example the user select the icon of a menu item or enter the name of icon.

Icon path prop not accepting strings?

Hi,

I have a data array of tile-objects over witch I map, to generate some Material-UI grid.

I want to generate multiple grid-items (Cards) with different Icons. However, passing
<Icon path={tile.icon}.... (tile.icon is the string "mdiCog") does not display anything. If I insert <Icon path={mdiCog}....
it works perfectly.

       <Grid container spacing={3}>
          {tiles.map((tile) => {
            return (
              <Grid item xs={12} md={3} key={tile.id} alignItems="center" justify="center">
                <Card className={classes.card}>
                  <CardActionArea
                    onClick={() => router.navigate(router.linkTo(tile.target))}
                    className={classes.cardAction}
                  >
                    <Icon
                      path={tile.icon}        <----------------------- here --------------------------------
                      title="User Profile"
                      size={4}
                      horizontal
                      vertical
                      rotate={90}
                      color="red"
                      spin
                    />
                    <CardContent className={classes.cardContent}>
                      {/* <Icon className={classes.icon} icon={factoryIcon} /> */}
                      <Typography variant="h6" align="center">
                        {i18n.translateToString(tile.title)}
                      </Typography>
                    </CardContent>
                  </CardActionArea>
                </Card>
              </Grid>
            );
        </Grid>

What am I overlooking?

Stacks do not work

The documentation states to use a Stack, to import the components like this:

import Icon, { Stack } from '@mdi/react';

However, when doing that on the current version, you receive the following error:

[!] Error: 'Stack' is not exported by node_modules/@mdi/react/Icon.js
https://rollupjs.org/guide/en#error-name-is-not-exported-by-module-
src/components/ToolbarMenu/ToolbarMenu.jsx (7:15)
5: import { Manager, Reference, Popper } from 'react-popper';
6: import { ClickAwayListener, MenuList, Tooltip } from '@material-ui/core';
7: import Icon, { Stack } from '@mdi/react';
                  ^
8: import { mdiColorHelper, mdiMenuDown } from '@mdi/js';
Error: 'Stack' is not exported by node_modules/@mdi/react/Icon.js

Why '--save-dev'?

Why does the documentation indicate to install through npm with npm install @mdi/react --save-dev? Why is -dev appended to the end? Is this needed/recommended in this case?

Make the default `size` be equal to 1, not null

Please make the size prop default to 1 if no value is provided. If you leave size off, the icon simply will not render (0 viewbox).

In most cases,

<Icon path={mdiMenu} />

is preferable to

<Icon path={mdiMenu} size={1} />

Stack Component

Do we want to add support for overlaying icons?

  • path array support
  • size array support
  • color array support

Usage:

<Icon path={[mdiFormatColorFill, mdiColorHelper]}
  color={[null, this.state.color]}/>

Write Tests

After rewriting this component in TypeScript it needs some tests.

Does this library still need to be maintained?

Asking because import Icon from '@mdi/react'; throws error when building with vitejs. Have to use named import to get it to work. So I was wondering if it can be changed to named export rather than using export default.

More Unit Tests

The component is feature complete, so now to focus on code quality. There are quite a few unit tests already, but there could always be more.

  • Negative Spin
  • Edge cases for combining rotate, horziontal, and vertical props.
    • So much time in this component is dealt with this due to transforms/animations.
  • etc...

Incremented `id` doesn't play nicely w/ SSR

Incrementing the id will cause HTML mismatch warnings when SSR'd, because the id incrementing will occur in a single context (the node server) when generating the server HTML but occur in "multiple" contexts (each user's browser) when hydrated. To put it another way, if you get 3 requests, it'll give id 1 to the first, id 2 to the second, id 3 to the third, but each will get id 1 when the client does its rendering, because it doesn't load up with the same id as present on the server (cuz it's starting from scratch, so to speak).

Easiest non-breaking solution would be to allow id to be provided as a prop and fall back to the incrementing if no id is provided. I'd be happy to open a PR to get this fixed if it would be accepted, as it's causing some issues with our Next.js project.

Thanks for the icon suite! It's been really helpful.

Can't use 'onClick' on Icon in Typescript

The onClick attribute can be used without issue on <Icon /> components in JavaScript as follows:
<Icon className="helpButton" path={mdiHelpBox} onClick={() => showHelp(helpModalData)} />

However in Typescript, I get the following error:
Property 'onClick' does not exist on type 'IntrinsicAttributes & IconProps'.ts(2322)

It would appear that the intended way of resolving this is to wrap the <Icon /> in an additional element and give the outer element the onClick attribute.

It would be nice if onClick attributes could be given directly to Icon components, especially considering that there is no issue with doing so at runtime.

Default import of Icon crushes production build

When I use icons like import Icon from "@mdi/react"; it crushes production build,
I have get errors like : Error: Minified React error #130; visit https://reactjs.org/docs/error-decoder.html?invariant=130&args[]=object&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
After a long search for a solution, I noticed that the problem was the default import of the icon
So, if anyone encounters same errors, try to change default import od Icon to named :
import Icon from '@mdi/react'; -> import {Icon} from '@mdi/react';

My setup:

  • React-18.2.0
  • Typescript-4.9.5
  • Vite-4.0.1
  • Vitest-0.25.8
  • nx-15.6.3

Icon prop types do not allow assignment of onClick

Using Typescript, an error is thrown when using an onClick prop on the Icon, such as for switching between two icon states. I'm using this for a password field which has two different icons depending on whether the password is shown.

image

I'm making a PR with the necessary changes to fix this. It is no longer showing the error after changing locally.

Invariant Violation

Hi, I am getting this error. I am not sure what I am missing. This was tested in the default react native template.

versions used:
[email protected]
@mdi/[email protected]
@mdi/[email protected]

Screen Shot 2020-02-03 at 12 11 52 PM

import React from 'react';
import {SafeAreaView, StyleSheet, StatusBar} from 'react-native';

import {Colors} from 'react-native/Libraries/NewAppScreen';

import Icon from '@mdi/react';
import {mdiAccount} from '@mdi/js';

const App: () => React$Node = () => {
  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView>
        <Icon
          path={mdiAccount}
          size={1}
          horizontal
          vertical
          rotate={90}
          color="red"
        />
      </SafeAreaView>
    </>
  );
};

add a view-box prop

<Icon path="M10 3.5A6.5 6.5 0 0 0 3.5 10A.75.75 0 0 1 2 10a8 8 0 1 1 8 8a.75.75 0 0 1 0-1.5a6.5 6.5 0 1 0 0-13z" spin />

<Icon path="M10 3.5A6.5 6.5 0 0 0 3.5 10A.75.75 0 0 1 2 10a8 8 0 1 1 8 8a.75.75 0 0 1 0-1.5a6.5 6.5 0 1 0 0-13z" spin viewBox="0 0 20 20" />

this path designed by view-box="0 0 20 20", could you add a viewBox prop to set view-box attribute?

Switch Build to `tsc` Build

Seeing as we don't really have to support CommonJS, we might as well just provide ES6 transpiled code for react developers with a module: "" property.

I wonder if there is any reason to support CommonJS for a React library.

Baseline flag

Icons are currently always square and centered. In a lot of cases it's a good thing, but sometimes the design would be better served by being aligned with the neighbouring text. It would be nice to have a flag to instruct the generated svg element to exclude the surrounding transparent borders (at least on the bottom side).

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.