Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration with Material-UI SvgIcon #358

Closed
iblecher opened this issue Nov 18, 2019 · 6 comments
Closed

Integration with Material-UI SvgIcon #358

iblecher opened this issue Nov 18, 2019 · 6 comments

Comments

@iblecher
Copy link

Hi,
I'm trying to write a custom template that will wrap the svg jsx content inside a SvgIcon component.
This is the custom template I tried to use:

return template.ast`
                ${imports}
                import SvgIcon from '@material-ui/core/SvgIcon';
                const ${componentName} = (${props}) => (<SvgIcon>${jsx}</SvgIcon>)
                ${exports}
              `

However, I get an error:

Unexpected token (5:36)
  3 |                 $0
  4 |                 import SvgIcon from '@material-ui/core/SvgIcon';
> 5 |                 const $1 = ($2) => (<SvgIcon>$3</SvgIcon>)
    |                                    ^
  6 |                 $4
  7 |               

I searched the issues for any possible solution but could not find one.
Could you please assist me?

Thanks !

@tkomstadius
Copy link

I did the same and to make it work I used React.createElement and added jsx.children only, to get rid of the <svg> wrapper.

return template.ast`
    ${imports}
    import SvgIcon from '@material-ui/core/SvgIcon'
    const ${componentName} = (${props}) => React.createElement(SvgIcon, props, ${jsx.children})
    ${exports}`;

@gregberge
Copy link
Owner

@tkomstadius solution seems pretty good! A custom template is the best way to do it.

@kelly-tock
Copy link

any ideas on how to keep the things from when you run icon?

<svg width="1em" height="1em" viewBox="0 0 24 25" fill="none" {...props}>

@kelly-tock
Copy link

does this look reasonable?

function template({ template }, opts, { imports, componentName, props, jsx, exports }) {
  const typeScriptTpl = template.smart({ plugins: ['typescript'] });
  const viewBox = jsx.openingElement.attributes.find((att) => att.name.name === 'viewBox');
  const fill = jsx.openingElement.attributes.find((att) => att.name.name === 'fill');
  const stroke = jsx.openingElement.attributes.find((att) => att.name.name === 'stroke');
  const viewBoxValue = `${viewBox.value.value}`;
  const fillValue = fill ? `fill: "${fill.value.value}",` : undefined;
  const strokeValue = stroke ? `stroke: "${stroke.value.value}",` : undefined;

  let addedProps = `{ width: "1rem", height: "1rem", viewBox: "${viewBoxValue}", ${
    fillValue ? fillValue : ''
  } ${strokeValue ? strokeValue : ''}}`;

  return typeScriptTpl.ast`
    ${imports}
    import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon';
    const ${componentName} = (props: SvgIconProps) => React.createElement(SvgIcon,
      ${addedProps}, ${jsx.children});
    ${exports};
  `;
}
module.exports = template;

?

@kelly-tock
Copy link

ended up with:

function template({ template }, opts, { imports, componentName, props, jsx, exports }) {
  const typeScriptTpl = template.smart({ plugins: ['typescript'] });
  const viewBox = jsx.openingElement.attributes.find((att) => att.name.name === 'viewBox');
  const fill = jsx.openingElement.attributes.find((att) => att.name.name === 'fill');
  const stroke = jsx.openingElement.attributes.find((att) => att.name.name === 'stroke');
  const viewBoxValue = `${viewBox.value.value}`;
  const fillValue = fill ? `fill: "${fill.value.value}",` : '';
  const strokeValue = stroke ? `stroke: "${stroke.value.value}",` : '';

  let addedProps = `{ width: "1rem", height: "1rem", viewBox: "${viewBoxValue}", ${fillValue} ${strokeValue} }`;

  return typeScriptTpl.ast`
    ${imports}
    import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon';
    const ${componentName} = (props: SvgIconProps) => React.createElement(SvgIcon,
      ${addedProps}, ${jsx.children});
    ${exports};
  `;
}
module.exports = template;

@yairEO
Copy link

yairEO commented May 20, 2024

To anyone who wants a full solution on how to integrate SVGR with MUI,
I wrote a complete solution for React projects based on Vite:

https://stackoverflow.com/a/78505950/104380

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants