Hey guys!
I think I’ve figured out a work-around for using DashIconify for iconify icons localy. First you need to add a new .js file in assets folder. I have named mine IconifyProviders-custom.js. It looks like this:
IconifyProviders = {
'local': {
resources: ['http://127.0.0.1:8050/icons'],
},
};
Here you add ‘custom APIs’ in addition to public ones. It should work for either self-hosted servers or local folders. For local folders the structure should be like above: URL of app with /icons folder.
You can check the execution of .js as per plotly documentation: https://dash.plotly.com/external-resources
In app.py you add an import and a new route:
from flask import send_from_directory
@server.route("/icons/<path:filename>")
def serve_icon(filename):
return send_from_directory("assets/icons", filename)
This will point to assets/icons.
Inside of assets/icons folder you have to put .json files of icon sets with icons you want to use. Icons should be saved in Iconify icon format that you can find on iconify webpage https://icon-sets.iconify.design/ . For example icon set mdi would have a file mdi.json with its content looking like this:
{
"prefix": "mdi",
"icons": {
"account-box": {
"body": "<path d=\"M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z\" fill=\"currentColor\"/>"
},
"account-cash": {
"body": "<path d=\"M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z\" fill=\"currentColor\"/>"
},
"account": {
"body": "<path d=\"M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z\" fill=\"currentColor\"/>"
},
"home": {
"body": "<path d=\"M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z\" fill=\"currentColor\"/>"
}
},
"width": 24,
"height": 24
}
All we need to do now is override the public API when we use DashIconify. We achive that by pointing to our new ‘API’ called local with @ prefix.
DashIconify(icon="@local:mdi:home")
That’s it! Hope it works for you. I have only tested this on my local machine but if you define URL properly I don’t see why it wouldn’t work as expected on deployed apps.
Short recap:
- new ‘API’
- new route
- localy stored icons (assets/icons/{icon_set}.json
- icon syntax: DashIconify(icon=“@{API_name}:{icon_set}:{icon}”)
Source:
https://iconify.design/docs/api/icon-data.html
https://iconify.design/docs/api/providers.html
https://iconify.design/docs/api/config.html
EDIT:
You can simplify .json files creation with this code snippet:
import requests
import json
import os
from collections import defaultdict
def fetch_iconify_data_grouped_by_set(list_of_icons):
base_url = "http://api.iconify.design"
icon_groups = defaultdict(list)
for icon in list_of_icons:
prefix, icon_name = icon.split(":")
icon_groups[prefix].append(icon_name)
all_icon_data = {}
for prefix, icons in icon_groups.items():
sorted_icons = ",".join(sorted(icons))
url = f"{base_url}/{prefix}.json?icons={sorted_icons}&pretty=1"
response = requests.get(url)
if response.status_code == 200:
all_icon_data[prefix] = response.json()
else:
all_icon_data[prefix] = {
"error": f"Failed to fetch data for {prefix}. Status code: {response.status_code}"
}
return json.dumps(all_icon_data, indent=4)
def save_icon_sets_to_json(icon_data_grouped, output_dir="icon_sets"):
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for icon_set, data in icon_data_grouped.items():
file_path = os.path.join(output_dir, f"{icon_set}.json")
with open(file_path, "w") as json_file:
json.dump(data, json_file, indent=4)
print(f"JSON files created in '{output_dir}' directory for each icon set.")
This will create .json files for all icon sets with corresponding icons defined inside. Example usage:
list_of_icons = ["radix-icons:moon", "radix-icons:sun", "tabler:dots"]
icon_data_grouped = fetch_iconify_data_grouped_by_set(list_of_icons)
print(icon_data_grouped)
icon_data_grouped = json.loads(icon_data_grouped)
save_icon_sets_to_json(icon_data_grouped)
Result: