简体   繁体   中英

How to create a dynamic Material UI Icon Atom in StoryBook and React TypeScript?

I am using StoryBook with React , TypeScript , and Material UI . I want to create an Icon Atom that behaves dynamically so that it can render the icon which I want to pass in as a prop .

Right Now, I am using the below-mentioned approach, but there are some problems with this.

  1. I am unable to change the Icon for a particular story. That's not the dynamic behavior I want.
  2. I also want to pass in some props such as fontSize and color to my Material UI Icon so that it can use them to render differently based on the value of props .

I want my component to behave according to the above two points. Please help !!

Icon.stories.tsx File

import React from "react";
import { ComponentStory, ComponentMeta } from "@storybook/react";
import MyIcon from "./Icon";
import AccessTimeIcon from "@mui/icons-material/AccessTime";
import PersonOutlineIcon from "@mui/icons-material/PersonOutline";

export default {
  title: "Atoms/MyIcon",
  component: MyIcon,
  argTypes: {
    color: {
      options: [
        "primary",
        "secondary",
        "warning",
        "error",
        "info",
        "success",
        "action",
      ],
      control: { type: "radio" },
    },
    fontSize: {
      options: ["small", "medium", "large"],
      control: { type: "radio" },
    },
  },
} as ComponentMeta<typeof MyIcon>;

const Template: ComponentStory<typeof MyIcon> = (args) => <MyIcon {...args} />;

export const Clock = Template.bind({});
Clock.args = {
  fontSize: "medium",
  color: "primary",
  materialIcon: <AccessTimeIcon />,
};

export const Person = Template.bind({});
Person.args = {
  fontSize: "large",
  color: "warning",
  materialIcon: <PersonOutlineIcon />,
};

Icon.tsx File

import React from "react";
import type { IconProps } from "@mui/material/Icon";

interface MyIconProps extends IconProps {
  materialIcon: React.ReactElement;
}

const MyIcon = ({ materialIcon, fontSize, color }: MyIconProps) => {
  return <>{materialIcon}</>;
};
export default MyIcon;

One approach is to use a library like material-icons-react which provides a react component that you can render with custom props.

import MaterialIcon, {colorPalette} from 'material-icons-react';

<MaterialIcon icon="dashboard" />

// different sizes
<MaterialIcon icon="dashboard" size='large' />
<MaterialIcon icon="dashboard" size={100} />

// colours
<MaterialIcon icon="dashboard" color={colorPalette.amber._200} />
<MaterialIcon icon="dashboard" color={colorPalette.amber.A700} />
<MaterialIcon icon="dashboard" color='#7bb92f' />

Another approach is including the material icons via Google Web Fonts script.

Add this to your html entry point:

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

Then you can use the material-icons class name and put the icon name inside the element:

<span class="material-icons">access_time_icon</span>

You can put this rendering in you Icon component and pass any styling props you want.

Note that if you use other icon variants, eg outlined, you need to add a separate font for each variant and use a different class like material-icons-outlined .

 <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <span class="material-icons">access_time_icon</span>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM