I created a basic icon component that extends SVG
from react-inlinesvg with styled-components
to allow for custom styling props. In addition, an attr
call specifies the src
property to the SVG
component, as different SVG
files will have different styling implementation, therefore each one is its own component. Here's the relevant code for that:
import SVG from 'react-inlinesvg';
import { CSSProperties as _CSSProperties } from "react";
import styled, { Interpolation } from "styled-components";
// Remove undefined from CSSProperties, as all these constants are guaranteed to
// exist.
export type RequiredCSSProperties = Required<_CSSProperties>;
// Add a prop that allows for custom CSS to be added to a styled component instance without
// creating a new styled component.
export type WithCSSProp<T={}> = T & { $css?: Interpolation<Omit<T, "$css">> };
export type MenuIconStyleAttributes = {
$color?: RequiredCSSProperties['stroke'] | null;
$width?: RequiredCSSProperties['width'];
$height?: RequiredCSSProperties['height'];
};
export default styled(SVG).attrs<WithCSSProp<MenuIconStyleAttributes>>(
(props) => ({
src: '/icons/menu.svg',
$color: props.$color ?? null,
$width: props.$width ?? '24px',
$height: props.$height ?? 'auto',
$css: props.$css ?? null
})
)`
width: ${({$width}) => $width};
height: ${({$height}) => $height};
> path {
stroke: ${({$color, theme}) => $color ?? theme.textColor};
}
${({$css}) => $css}
`;
My issue is that, when I'm using this component, the src
property is being seen as required even though it's specified with a static value. Exact error:
No overload matches this call.
Overload 1 of 2, '(props: PolymorphicComponentProps<"web", FastOmit<Substitute<Substitute<{ string?: string | number | undefined; stroke?: string | undefined; clipPath?: string | undefined; color?: string | undefined; cursor?: string | number | undefined; ... 481 more ...; uniquifyIDs?: boolean | undefined; }, { ...; }>, WithCSSProp<...>>, never>, void, void, {}, {}>): Element', gave the following error.
Property 'src' is missing in type '{}' but required in type 'FastOmit<Substitute<FastOmit<Substitute<Substitute<{ string?: string | number | undefined; stroke?: string | undefined; clipPath?: string | undefined; color?: string | undefined; cursor?: string | number | undefined; direction?: string | ... 1 more ... | undefined; ... 480 more ...; uniquifyIDs?: boolean | undefined...'.
Overload 2 of 2, '(props: FastOmit<Substitute<Substitute<{ string?: string | number | undefined; stroke?: string | undefined; clipPath?: string | undefined; color?: string | undefined; cursor?: string | number | undefined; direction?: string | ... 1 more ... | undefined; ... 480 more ...; uniquifyIDs?: boolean | undefined; }, { ...; }>, WithCSSProp<...>>, never>): ReactNode', gave the following error.
Property 'src' is missing in type '{}' but required in type 'FastOmit<Substitute<Substitute<{ string?: string | number | undefined; stroke?: string | undefined; clipPath?: string | undefined; color?: string | undefined; cursor?: string | number | undefined; direction?: string | ... 1 more ... | undefined; ... 480 more ...; uniquifyIDs?: boolean | undefined; }, { ...; }>, With...'.
I'm able to override src
to be optional, but the value would be dismissed anyway, so I really just want to get rid of that prop altogether. Is this possible?
I found an answer myself. I created the following wrapper function around the SVG component and styled this component rather than the SVG itself:
import SVG from 'react-inlinesvg';
import { ComponentProps } from 'react';
function StaticSrcSVG(src: string) {
return Object.assign(
(props: Omit<ComponentProps<typeof SVG>, 'src'>) => <SVG src={src} {...props} />,
{
displayName: `${src}(StaticSrcSVG)`
}
);
}