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.
- I am unable to change the Icon for a particular story. That's not the dynamic behavior I want.
- I also want to pass in some
propssuch asfontSizeandcolorto myMaterial UI Iconso that it can use them to render differently based on the value ofprops.
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;
CodePudding user response:
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' />
CodePudding user response:
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 >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, e.g. 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 >access_time_icon</span>
