tailwindlabs / heroicons

A set of free MIT-licensed high-quality SVG icons for UI development.
https://heroicons.com
MIT License
21.45k stars 1.28k forks source link

Extending with custom icons (without adding to the library) #553

Closed stephanbogner closed 2 years ago

stephanbogner commented 2 years ago

Hey there, Weirdly I haven't found an issue related to this. I love the syntax (and style) of HeroIcons in my react projects – especially using text-color to color them.

Problem

Every so often I need a certain icon that is not part of the set. Often very custom that wouldn't even make sense to be part of the icon set.

Workaround

Currently I just import them as normal images and use them accordingly, but that means I have two workflows when working with icons. 😱

Idea

I am not sure what would achieve the best workflow, but even something simple would enhance my workflow:

import customShuffleIcon from './assets/shuffle-icon.svg'
import {
  iconShell,
} from '@heroicons/react/'

[...]

<iconShell className="h-5 w-5 text-blue-500" icon={customShuffleIcon} alt="Shuffle"/>

(The icon would have to be exported in a certain way – e.g. fill="currentColor" – but that would be fine too)

And I guess it's also an open question on how other people deal with this, because most must have this problem (eventually)? πŸ€·β€β™‚οΈ

stephanbogner commented 2 years ago

Ok, I did some research and I assume that the main reason is, that React doesn't support inline SVGs out-of-the-box well. That would be required because otherwise fill="currentColor" is ignored.

I assume also that that's the reason why the built HeroIcon-components have such "weird" code.

I would still wanna know how other people structure their code when a custom icon is needed. Maybe I am missing something? 🀷

bradlc commented 2 years ago

Hey @stephanbogner. The icon "shell" thing is a neat idea but I think it's outside the scope of the Heroicons packages. You could make your own pair of shell components, something like:

function IconShellSolid(props) {
  return <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg" {...props} />
}

function IconShellOutline(props) {
  return <svg width="24" height="24" viewBox="0 0 24 24" fill="none" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" xmlns="http://www.w3.org/2000/svg" {...props} />
}

// Example usage:

function MyIcon() {
  return (
    <IconShellOutline className="text-blue-500">
      <circle cx="12" cy="12" r="10" />
    </IconShellOutline>
  )
}

I hope that's helpful!

stephanbogner commented 2 years ago

Thanks for your input @bradlc!