layer5io/sistent

Create a base `Icon` to derive from when creating icons

Opened this issue · 0 comments

Current Behavior

We have multiple icons that needs to be refactored to reduce duplication on variables and constants, and rather rely on one icon to use from.

Desired Behavior

  • Create base SistentIcon
  • Widen the IconProps to include sx props as an optional field to be used with MUI
  • Add size field in IconProps to provide the default sizes for xsmall, small, medium, large, and xlarge

Implementation

The below describes the SistentIcon that will wraps the svg path or else with Box, doesn't have to be box, it can be a div.

The children was changed to allow child elements within the div or Box

export type IconSize = "xsmall" | "small" | "medium" | "large";

export type IconProps = {
  children?: React.ReactNode;
  color?: string;
  title?: string;
  width?: number | string;
  height?: number | string;
  size?: IconSize;
  sx?: SxProps<Theme>;
} & Omit<BoxProps, "sx"> &
  React.SVGProps<SVGSVGElement>;

const iconSizes: Record<IconSize, { width: number; height: number }> = {
  xsmall: { width: 16, height: 16 },
  small: { width: 24, height: 24 },
  medium: { width: 32, height: 32 },
  large: { width: 40, height: 40 },
};

export default function SistentIcon({
  color,
  title,
  size = "medium",
  fill = CHARCOAL_FILL,
  viewBox,
  sx,
  children,
  ...rest
}: IconProps) {
  const { width, height } = iconSizes[size];

  return (
    <Box
      component={"svg"}
      xmlns="http://www.w3.org/2000/svg"
      width={width}
      height={height}
      viewBox={viewBox}
      fill={fill || color}
      sx={sx}
      {...rest}
    >
      {title && <title>{title}</title>}
      {children}
    </Box>
  );
}

The fill will be a default color, in this case charcoal. This can be changed inline in project specific. You can also use sx props from MUI in order to use the theme inline.

            <IconButton
              aria-label="close"
              onClick={onClose}
              sx={(theme) => ({
                "&:hover": {
                  "& svg": {
                    fill: theme.palette.keppelGreen,
                  },
                },
              })}
              disableRipple
            >
              <CloseIcon
                sx={(theme) => ({
                  fill: theme.palette.charcoal,
                })}
              />
            </IconButton>

Acceptance Tests

Mockups


Contributor Guide