decaporg / decap-cms

A Git-based CMS for Static Site Generators
https://decapcms.org
MIT License
17.84k stars 3.04k forks source link

Allow use of different icons via the config.yml file #1040

Open binaryben opened 6 years ago

binaryben commented 6 years ago

UPDATE: See below for a temporary workaround. Ideally someone can still make this happen via the config.yml file instead though.

 


Original Request

- Do you want to request a feature or report a bug?

Feature request

- What is the current behavior?

All icons for collections are the same. It is hard to quickly differentiate if there is a large number of collection types.

- What is the expected behavior?

Possibly through using something like font awesome instead of SVG's, allow developers to change the look of the icon next to each category in the side bar.

- Please link or paste your config.yml below if applicable.

See the addition of the icon attribute below as an example:

collections:
  - name: settings
    label: Settings
    icon: fa-cog
    files: 
      - label: Global Settings
        name: global
        file: global-settings.yml

Many users probably have font awesome cached in their browser as well if that helps.


 

Temporary Solution & Example of Output

For reference, I have added font awesome css to my site and used the web inspector to manually change the icons to see if it works. SPOILER: IT DOES! (as you would expect..)

So far all I had to do was replace the relevant SVG elements with the following:

<i class="fa fa-<<icon name>> fa-fw" aria-hidden="true"></i>

I did this by using the following javascript code placed after the react app:

<script>
    icons = [
      {"name": "cal","fa": "calendar"},
      // ...
      {"name": "settings","fa": "cogs"}
    ]

  function iconify() {
      icons.forEach(function(item) {
          var selector = "a[href$='" + item.name + "'] .nc-icon span";
          var loc = document.querySelector(selector);
          var i = document.createElement("i");
          i.classList.add("fa", "fa-fw", "fa-" + item.fa);
          i.setAttribute("aria-hidden", "true");
          if (loc) {
              while (loc.firstChild) loc.removeChild(loc.firstChild);
              loc.appendChild(i);
          }
      })
  }

  var observer = new MutationObserver(function(changes) {
      iconify();
  });

  var init = new MutationObserver(function(changes) {
      var exists = !!document.querySelector(".nc-app-main div");

      if (exists) {
          iconify();
          observer.observe(document.querySelector('.nc-app-main div'), {
              childList: true
          });
          init.disconnect();
      }
  });

  init.observe(document.querySelector('body'), {
      childList: true
  });
</script>

...and put the following in my HTML header:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<link href="https://unpkg.com/netlify-cms/dist/cms.css" rel="stylesheet" />
<style>
    .nc-collectionPage-sidebarLink i {
        font-size: 19px;
        line-height: 24px;
        margin-left: -1px;
    }
</style>

... which results in this:

screen shot 2018-01-24 at 9 36 42 pm

This is exactly the type of output I am hoping for from this feature request. Unfortunately I don't have any time for a little while to try and integrate these better myself, but this might help someone else in the mean time?

P.S. This workaround only works in modern browsers due to use of MutationObserver. I'm also not sure how efficient it is.. feedback appreciated!

erquhart commented 6 years ago

At a minimum we could accept an icon name from the CMS' built in collection (we have a cog). Makes sense to me, just need to document those icons.

Thoughts, anyone?

binaryben commented 6 years ago

The cog was just given as an obvious example, but glad it is there. Also noticed a bunch of other icons that cover 50% of my needs, which is promising - but I think there is still value in adding other sources for icons as options?

Maybe we could use the existing icons to get something up faster, but it shouldn't be too hard to add a pattern check to allow alternatives after that. Documentation is arguably as simple as adding it to the list of collection objects available to every collection at this link:

  • icon: use a different icon to identify the collection in the editor UI; use the name of any existing icon (don't add the .svg extension; defaults to icon: write), any Font Awesome icon (e.g. icon: fa-cog) if you have FA installed on your admin page, or any publicly available square SVG (e.g. icon: /admin/link-to-file.svg)

 

Knowing where to load the relevant sprite from:

Honestly, if someone mistypes (not that I know anything about that.. haha) and no icon shows up, it's on the developer. So not much checking beyond that should be needed.

 

Example documentation for installing Font Awesome:

Can add the following to this page for showing users how to "install" font-awesome if they want to use it.

Make sure to include <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" /> before your own styles if you want to use custom icons in the Netlify CMS user interface

 

Bonus points if Netlify CMS can instead dynamically load Font Awesome if it detects it is needed (so no user installation on the admin page; also good for use in custom widgets potentially?) or if the team decide to use Font Awesome for their fonts!

binaryben commented 6 years ago

I have updated OP with a temp. solution.

erquhart commented 6 years ago

Your workaround is pretty cool, nice work :)

I definitely see the value of allowing other icons to be used, but I'd rather not favor one lib (e.g. font awesome) over others. I think we're on the same page with the outcome, but more consideration is needed to figure out the right abstraction. Should be maximally compatible with icon libraries without making things too messy.

cdeath commented 6 years ago

CSS-only workaround with icon font:

Choose your favorite icon font or generate your own (FortAwesome, IcoMoon, etc...) and include it the cms page:

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">

This example uses Font Awesome:

aside a span {
  display: inline-flex !important;
  justify-content: center;
  align-items: center
}

aside a span svg {
  display: none !important;
}

aside a span::before {
  font-family: "Font Awesome 5 Free";
  font-size: 1rem;
}

aside a[href="#/collections/posts"] span::before {
  content: "\f5a1";
}

aside a[href="#/collections/pages"] span::before {
  content: "\f15c";
}

aside a[href="#/collections/sections"] span::before {
  content: "\f550";
}

aside a[href="#/collections/menus"] span::before {
  content: "\f0e8";
}

aside a[href="#/collections/people"] span::before {
  content: "\f2b9";
}

aside a[href="#/collections/settings"] span::before {
  content: "\f085";
}

You have to pick which character is assigned to the icon you want in your font and use it as the content of the pseudo-element.

Use more or less specific selectors as you see fit.

Result:

screen shot 2018-10-06 at 02 00 56

If you don't want to use an icon font, you can use an SVG sprite or individual SVG files, you just have to set them as a background of the pseudo-elements.

m2creates commented 5 years ago

If you are using the free version of Font Awesome 5 double check your font weight! I fixed my custom icons following cdeath's guide with a minor addition (after much head-desking).

aside a span::before {
  font-family: "Font Awesome 5 Free";
  font-size: 1rem;
  /* Regular (400) only includes some icons. Solid (900) has the rest of the free ones */
  font-weight: 900;
}
stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

hacknug commented 4 years ago

Please, be a good bot and don't close this. @erquhart promised us changes soon. Let him close it when it's time 🙂

hanneskuettner commented 4 years ago

Is it worth checking out how to integrate react-icons since they seem to support all of the most common icon libraries out there?

We could possible build a icon library registry that we use internally and expose to the user to register their own icon libraries if they really wanted to.

Something like

const myIconLibrary {
  prefix: "mi",
  get: (name) => <MyIcon name={name} />
}

CMS.registerIconLibrary(myIconLibrary)

and in the configuration icons could be referenced like mi/cog or in the case of all supported react-icons icon libraries, eg. fa/FaAccessibleIcon.

austincondiff commented 4 years ago

Regarding #2557, I am using the open source Feather icon set with a few additions of my own. In this redesign I planned to allow to specify the icon used for each collection by specifying the name in config.yml like this.

collections:
  - name: posts
    label: Posts
    icon: pin

We could default to this set and allow for custom icons or entire icon sets to be used.

hanneskuettner commented 4 years ago

I love feather icons. They would make a great default. Also they come with the react-icons package as well.

I just don't know how we would incorporate your additions. Are they intended to be used internally or with user defined collections as well?

I think then we should add something like a default icon library so the user can drop the fi prefix (or any other for that matter) and just use the icon names.

austincondiff commented 4 years ago

@hanneskuettner Check out our Icon story in storybook here. Also look at the ui-default package in the v3-ui-redesign branch.

As you can see right now they are all react components but maybe we could be handling that better. I am not including the Feather icons package because I wanted to do my own and include them. But now that I think about it, we might just use our icon as a proxy and only include custom icons. Maybe not though. I think I did it this way to allow for more flexibility. If you have any input here I’m all ears!

moritzpflueger commented 3 months ago

Is there any update on this?

binaryben commented 3 months ago

Is there any update on this?

Both @hanneskuettner and myself have started working at Directus since this was first created. So I guess that is an update? Not to brag or anything, but you can customise the Collection icons in Directus 💪