React Icon System

栏目: IT技术 · 发布时间: 5年前

内容简介:Icons play a crucial role in interface design. They can certainly be used as visual embellishments, but they are quite often able to convey their meaning without additional text, making them a handy tool for designers & developers. There areOur starting po

Icons play a crucial role in interface design. They can certainly be used as visual embellishments, but they are quite often able to convey their meaning without additional text, making them a handy tool for designers & developers. There are many different ways to build icon systems. In the past, I havewritten about a sprite based technique. Since then, tooling has matured and there are better approaches. This article will show you how to set up an icon system using SVGR — a tool for transforming SVGs into React components.

Prepare the SVG Files

Our starting point will be SVG files – one per icon. You will likely use design tools like Figma, Illustrator or Sketch to create these.

When designing these icons, consider using a consistent artboard size. This ensures that all icons follow the same layout rules and can be used interchangeably. You should also consider adding a bit of padding to your artboard to keep the icon content visually centred.

React Icon System React Icon System

Artboard size, live area and padding

Generating the Icon Components

SVGR converts SVG files into React components. It is available as a Node library, a CLI tool and a webpack plugin.

Create React App comes pre-configured with SVGR. You can import an SVG file and use it as a component. This is a great start. It reduces the effort required to use SVGs with React.

import { ReactComponent as Logo } from './logo.svg';
function App() {
  return (
    <div>
      {/* Logo is an actual React component */}
      <Logo />
    </div>
  );
}

By using the SVGR CLI, you can customize the component generation and improve your workflow further. You can provide a custom template for component generation and even transform the SVG itself. To start, install the CLI using:

$ npm install @svgr/cli --save-dev

To create an icon, run:

$ npx svgr --icon --replace-attr-values "#000=currentColor" my-icon.svg

Notice, the --icon flag. It performs a couple of important tasks for us:

1em
viewBox

The --replace-attr-values "#000=currentColor" flag replaces the chosen color with currentColor , allowing you to control the icon color using the font-color CSS property.

Behind the scenes, SVGR also uses SVGO to optimize the SVG file before converting it into a component. This is a sample of what you can expect the output to look like:

MyIcon.js

import * as React from 'react';

function SvgMyIcon(props) {
  return (
    <svg
      width="1em"
      height="1em"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth={2}
      strokeLinecap="round"
      strokeLinejoin="round"
      {...props}
    >
      <path d="M22 12h-4l-3 9L9 3l-3 9H2" />
    </svg>
  );
}

export default SvgMyIcon;

To transform an entire directory of icons, use:

$ npx svgr --icon --replace-attr-values "#000=currentColor" -d icons icons

I generally treat these generated icon components as build artifacts. All the SVG files live in an icon directory, and the .js files within that directory are ignored by git. Then use an npm task to generate the icon components at build time.

package.json

{
  ...
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "prebuild": "npm run icons",    "test": "react-scripts test",
    "eject": "react-scripts eject"
    "icons": "svgr --icon --replace-attr-values '#000=currentColor' -d src/icons src/icons"  }
}

Customizing the Icon Component

You can provide a custom template to modify the generated component code. The template below creates an icon component that leverages styled-components to control its styling.

icon-template.js

function template(
  { template },
  opts,
  { imports, componentName, props, jsx, exports }
) {
  const styledComponentName = 'Styled' + componentName;

  return template.ast`
    ${imports}
    import styled from 'styled-components';

    const SVG = (${props}) => ${jsx};

    const ${componentName} = styled(SVG)\`
      display: \${(props) => (props.block ? 'block' : 'inline-block')};
      font-size: \${(props) => (props.fontSize ? props.fontSize : '16px')};
      color: \${(props) => (props.color ? props.color : '#ccc')};
      vertical-align: middle;
      shape-rendering: inherit;
      transform: translate3d(0, 0, 0);
    \`;

    export default ${componentName};
  `;
}

module.exports = template;

For the Radius design system, we are using TypeScript, styled-components and styled-system. Our custom template generated icons that are correctly typed and appropriately connected to our design tokens.

Compound Icons Component

We can further simplify the icons’ usage by combining all the generated icons into one compound Icons component.

import { Icons } from 'ds';

export const App = () => (
  <>
    <Icons.Airplay aria-title="airplay the video" />
    <Icons.AlertCircle aria-title="error" />
  </>
);

SVGR allows us to specify a custom index template. This template is used to generate the index.js file when transforming a directory of SVGs. The following template generates a compound component.

icon-index-template.js

const path = require('path');

function indexTemplate(files) {
  const compoundExportEntries = [];

  const importEntries = files.map(file => {
    const componentName = path.basename(file, path.extname(file));
    compoundExportEntries.push(componentName);

    return `import { default as ${componentName} } from './${componentName}';`;
  });

  return `${importEntries.join('\n')}

    export const Icons = {
      ${compoundExportEntries.join(',\n  ')}
    };
  `;
}

module.exports = indexTemplate;

It adds an import statement for all the components, generates a name for the component based on the file name and finally combines them all into the Icons object.

src/icons/index.js

import { default as Activity } from './Activity';
import { default as Airplay } from './Airplay';
import { default as AlertCircle } from './AlertCircle';
import { default as AlertOctagon } from './AlertOctagon';

export const Icons = {
  Activity,
  Airplay,
  AlertCircle,
  AlertOctagon,
};

And here is the final version of the npm task:

package.json

{
  "scripts": {
    ...
    "icons": "svgr --icon --replace-attr-values '#000=currentColor' --template icon-template.js --index-template ./icon-index-template.js -d src/icons src/icons"
  }
}

SVGR is a fantastic tool. You can use it out of the box with Create React App. You can also customize it to better fit your workflow. The full code for this example is available here . For a more complex example, I recommend checking out the Radius source-code .


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

产品故事地图

产品故事地图

唐娜·理查(Donna Lichaw) / 向振东 / 机械工业出版社 / 2017-6 / 49.9元

本书一共8章,分为三个部分:第1-2章讲述故事的作用、你该如何运用产品故事来吸引顾客,不是通过讲故事,而是创造故事。第3-5章阐述了不同情境和客户生命周期中的产品故事类型。第6-8章进一步研究如何在战略和策略层面发现、提升、用好你的产品故事。 《产品故事地图》写给那些想要通过创造出顾客喜欢用、经常用而且会推荐给别人用的产品来吸引客户的人。这里的“产品”包括网页、软件、APP、数字化或非数字化......一起来看看 《产品故事地图》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换