verbb / icon-picker

A Craft CMS field to select SVG or font icons from a folder for use in your content.
Other
17 stars 8 forks source link

Ability to add multiple icon sources #50

Closed DynamiteGoesBoom closed 2 years ago

DynamiteGoesBoom commented 2 years ago

What are you trying to do?

I'd like a way to be able to select from several icon sources:

I know I can just add the icons to config/icon-picker.php but it would be great if the icon sources that you want for a particular site was selectable. I'm working on a SaaS that offers a bevy of options for components. It would be awesome if I could offer a few different sets of icons without necessarily showing all of the icons at once from the various sources.

Another option could be to have a heading inside of the icon picker dropdown with the name of the Icon Source within it so users could see which icons are available. But I do think this could be confusing AX for users.

Also if we did have several icon sets to choose from, it would be terrific if that icon set value could be set via an .env variable.

Thanks gang for this powerful plugin!

When I do this:

use verbb\iconpicker\services\IconSources;
use verbb\iconpicker\events\RegisterIconSourceEvent;
use yii\base\Event;

Event::on(IconSources::class, IconSources::EVENT_REGISTER_ICON_SOURCE, function(RegisterIconSourceEvent $event) {
    $icons = [
        'insert-emoticon',
        'mdi-account-lock-open'
    ];

    $event->sources['material-icons'] = [
        'label' => Craft::t('icon-picker', 'Material Icons'),
        'url' => 'https://unpkg.com/browse/material-icons@1.2.2/css/material-icons.min.css',
        'icons' => $icons,
        'classes' => 'mi-',
        'fontName' => 'Material Icons',
    ];
});

I see that the icons don't appear in the selector too:

Screen Shot 2022-01-21 at 3 43 06 PM

I've looked in the above css file to attempt to map the icons correctly with no luck. Also on the frontend I still show some font awesome classes being outputted instead of the classes in set above.

engram-design commented 2 years ago

I was about to say, you can register your own icon sources through an event, which you're doing. The Material icons should work, but you should be using the raw CSS? https://unpkg.com/material-icons@1.2.2/css/material-icons.min.css.

I've made some slight tweaks:

Event::on(IconSources::class, IconSources::EVENT_REGISTER_ICON_SOURCE, function(RegisterIconSourceEvent $event) {
    $icons = [
        'insert-emoticon',
        'account-circle'
    ];

    $event->sources['material-icons'] = [
        'label' => Craft::t('icon-picker', 'Material Icons'),
        'url' => 'https://unpkg.com/material-icons@1.2.2/css/material-icons.min.css',
        'icons' => $icons,
        'classes' => 'mi mi-',
        'fontName' => 'Material Icons',
    ];
});

However that's only part of the solution. We need to include the @font-face rule, which Font Awesome itself does (see https://use.fontawesome.com/releases/v5.15.1/css/all.css), but isn't included with Material Icons. That poses a bit of an issue I'm afraid, and we'll need to figure out a way to inject the @font-face definition:

Event::on(IconSources::class, IconSources::EVENT_REGISTER_ICON_SOURCE, function(RegisterIconSourceEvent $event) {
    $icons = [
        'insert-emoticon',
        'account-circle'
    ];

    $event->sources['material-icons'] = [
        'label' => Craft::t('icon-picker', 'Material Icons'),
        'url' => [
            'https://fonts.googleapis.com/css2?family=Material+Icons&display=swap',
            'https://unpkg.com/material-icons@1.2.2/css/material-icons.min.css',
        ],
        'icons' => $icons,
        'classes' => 'mi mi-',
        'fontName' => 'Material Icons',
    ];
});

Here, I'm adding support for multiple URLs to be provided for an icon source. You could of course make your own, singular one, but this is probably going to get common down the track.

You'll need to ensure you're using the latest patch to get this early, change your verbb/icon-picker requirement in composer.json to:

"require": {
  "verbb/icon-picker": "dev-craft-3 as 1.1.12",
  "...": "..."
}

Then run composer update.

DynamiteGoesBoom commented 2 years ago

@engram-design Thanks as always and I'll give this a whirl. Is there anything we can do just to show one particular source?

Also how would you recommend adding all of the Material icon names? I could likely find a JSON blob of all the classes, but that will likely make my config file a bit much to manage. Not a huge deal but curious on your thoughts.

I'm assuming I'd have to leverage this somehow:

public function getJsonData($file)
    {
        $iconPath = __DIR__ . '/../json/' . $file;

        return Json::decode(file_get_contents($iconPath));
    }

I'm just not sure off hand how.

Thanks again!

engram-design commented 2 years ago

When you say showing just one source, what do you mean? Do you mean you want some fields to show only Material icons, some only Font Awesome, etc? That's just a matter of setting the available remote sources as required.

And yeah, as for adding all the names, that's a pretty painstaking task.

You'd want to copy getJsonData(), but that's geared towards just Icon Picker ones, you'd need to change the path to your module or project files.

{
  "insert-emoticon",
  "account-circle"
}
Event::on(IconSources::class, IconSources::EVENT_REGISTER_ICON_SOURCE, function(RegisterIconSourceEvent $event) {
    $icons = Json::decode(file_get_contents('/path/to/json'));

    $event->sources['material-icons'] = [
        'label' => Craft::t('icon-picker', 'Material Icons'),
        'url' => [
            'https://fonts.googleapis.com/css2?family=Material+Icons&display=swap',
            'https://unpkg.com/material-icons@1.2.2/css/material-icons.min.css',
        ],
        'icons' => $icons,
        'classes' => 'mi mi-',
        'fontName' => 'Material Icons',
    ];
});

Or you might've noticed that we've added support for Material - sorta. This is for the icon font glyphs, as someone needed this support some time ago. You could make use of that json file. $icons = array_keys(IconPicker::$plugin->getIconSources()->getJsonData('material.json'));

I probably need to revisit (somehow) how remote sources/sets work and provide some better mechanisms to make things easier. It's just difficult as each icon provider out there is different!

DynamiteGoesBoom commented 2 years ago

Hey @engram-design I just think it would be nice to be able to determine what source can be used via a config file for each field type. Much like how https://github.com/percipioglobal/craft-colour-swatches does it with a selectable config file. We probably wouldn't need to go that far, but having a way to pull those sources out from the field type itself would be really nice.

Thanks for all of the awesome work that you and your team does! Yeah I totally get that not all Icon Sources work the same. That would make things way too easy for everyone, thus will never have a fully adopted approach to icons.

Thanks again...

engram-design commented 2 years ago

Yep, appreciate the suggestion - I'll see how we can improve this!

DynamiteGoesBoom commented 2 years ago

@engram-design perfect and that's all we can ask for!

engram-design commented 2 years ago

Font Sources have gotten a complete revamp into regular icon sets in 2.0.0, so this should be improved.