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

Introduce icon module #2613

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft

Introduce icon module #2613

wants to merge 1 commit into from

Conversation

falkoschindler
Copy link
Contributor

@falkoschindler falkoschindler commented Feb 25, 2024

This PR is an alternative, simplified implementation of PR #2537. It introduces an icon module and allows to use icons constants like this:

from nicegui import icon, ui

ui.icon(icon.HOME)
ui.icon(icon.HOME_OUTLINED)
ui.icon(icon.HOME_SYM_ROUND)

Actually I planned to create an API like this:

ui.icon(icon.HOME)
ui.icon(icon.HOME.outlined)
ui.icon(icon.HOME.symbol_round)

But because many icons are not available as "filled icons" (the default), the result of icon.SUCH_AN_ICON would be undefined. So I went back to the simply approach using a plain list of string constants.


Open tasks:

  • lowercase identifiers
  • symbols only, with font parameters
  • How to deal with leading numbers? n_?
  • documentation
  • pytest

@falkoschindler falkoschindler marked this pull request as draft February 25, 2024 16:54
@falkoschindler falkoschindler added the enhancement New feature or request label Feb 25, 2024
@rodja
Copy link
Member

rodja commented Feb 26, 2024

I like the API of ui.icon(icon.HOME.outlined) much better than icon.HOME_OUTLINED because it will provide much less cluttered auto-completion. For example when typing icon.STAR it's quite difficult to skim though all the icon names because each one repeats three times.

@falkoschindler I took a look into the json coming from https://fonts.google.com/metadata/icons?incomplete=1&key=material_symbols to find examples where "Material Icons" family was not supported. At least for some of these, there is another icon definition with the same name which provides this family:

    {
      "name": "accessibility",
      "version": 251,
      "popularity": 1889,
      "codepoint": 59470,
      "unsupported_families": [
        "Material Icons",
        "Material Icons Outlined",
        "Material Icons Round",
        "Material Icons Sharp",
        "Material Icons Two Tone"
      ],
      "categories": [
        "Common actions"
      ],
      "tags": [
        "accessibility",
        "accessible",
        "body",
        "handicap",
        "help",
        "human",
        "people",
        "person"
      ],
      "sizes_px": [
        20,
        24,
        40,
        48
      ]
    },
    {
      "name": "accessibility",
      "version": 13,
      "popularity": 26564,
      "codepoint": 59470,
      "unsupported_families": [
        "Material Symbols Outlined",
        "Material Symbols Rounded",
        "Material Symbols Sharp"
      ],
      "categories": [
        "action"
      ],
      "tags": [
        "accessibility",
        "accessible",
        "body",
        "handicap",
        "help",
        "human",
        "people",
        "person"
      ],
      "sizes_px": [
        24
      ]
    },

@rodja
Copy link
Member

rodja commented Feb 26, 2024

And if there is really not a filled version we could fallback to the outlined one.

@rodja
Copy link
Member

rodja commented Feb 26, 2024

And one other thought: Why have you chosen to go back to lowercase for the sub-type and not use Or icon.HOME.OUTLINED`?

I would like the syntax icon.home.outlined even better. Constants should be upper case according to PEP 8, but I would argue that the lower case variant is more readable and more in line with the actual icon names (which are also lower case).

@falkoschindler
Copy link
Contributor Author

@rodja

I like the API of ui.icon(icon.HOME.outlined) much better than icon.HOME_OUTLINED.

Me too.

At least for some of these, there is another icon definition with the same name which provides this family.

Yes, I know. This makes it a bit tricky to build the icon list, because they provide multiple icons with the same name, each with "unsupported families". So you have to combine them yourself to find the "supported families" yourself. Anyway, there are icons with "Symbols" only, or with "Round", "Sharp" and "Outlined" but no "Filled" icons, and so on. Basically every combination is possible.

And if there is really not a filled version we could fallback to the outlined one.

I'm sceptical about silently falling back to another family. If you plan to use one family only, it's hard to even notice that you didn't get what you wanted.

Why have you chosen to go back to lowercase for the sub-type

Good question. Actually, I also like icon.home.outlined better.

I wonder if we should introduce icon.home.filled. This way icon.home would be an Icon instance and you have to specify a family. That would be easy to implement, very flexible, very transparent. But it's a bit longer to type for the filled family.

@rodja
Copy link
Member

rodja commented Feb 26, 2024

I wonder if we should introduce icon.home.filled. This way icon.home would be an Icon instance and you have to specify a family. That would be easy to implement, very flexible, very transparent. But it's a bit longer to type for the filled family.

Ah. Let's combine the two. Let's make icon.home "some home icon" (eg. fall back to what ever is available) and icon.home.filled, .outlined, .round, ... is only available if the family is supported.

@rodja
Copy link
Member

rodja commented Feb 26, 2024

ChatGPT just told me that Material Symbols is a super-set of Material Icons. Also Outlined and Rounded variants are part of the old "Material Icons". Material Symbols are designed to be highly customizable, including Weight, Grade, Optical Size which makes the separate sets obsolete. See https://developers.google.com/fonts/docs/material_symbols.

I think it would be ok if icons only present the Material Symbols making the sub-selection obsolete. Or should we provide one import for icons and one for symbols? How would the Material Symbols appearance be configured? Looks like this can be done with css properties? Should we introduce a helper contextmanager or classes like icons-rounded, icons-outlined, ...?

@falkoschindler
Copy link
Contributor Author

Interesting idea...

Just for reference, here's a quick script counting the different family combinations:

import json
from collections import Counter
import httpx

FAMILIES = {
    'Material Icons',
    'Material Icons Outlined',
    'Material Icons Round',
    'Material Icons Sharp',
    'Material Symbols Outlined',
    'Material Symbols Rounded',
    'Material Symbols Sharp',
}

response = httpx.get('https://fonts.google.com/metadata/icons?incomplete=1&key=material_symbols')
icons: dict[str, list[str]] = {}
for icon in json.loads(response.text[4:])['icons']:
    if icon['name'] not in icons:
        icons[icon['name']] = []
    icons[icon['name']].extend(FAMILIES.difference(icon['unsupported_families']))

counter: Counter[frozenset] = Counter()
for name, families in icons.items():
    counter.update([frozenset(families)])
for family, count in sorted(counter.items()):
    print(f'{set(family)}: {count}')
set(): 26
{'Material Symbols Rounded', 'Material Symbols Sharp', 'Material Symbols Outlined'}: 1283
{'Material Icons'}: 10
{'Material Icons Sharp', 'Material Icons Round', 'Material Icons Outlined'}: 1
{'Material Icons', 'Material Icons Sharp', 'Material Icons Round', 'Material Icons Outlined'}: 213
{'Material Symbols Rounded', 'Material Symbols Sharp', 'Material Icons', 'Material Symbols Outlined'}: 24
{'Material Icons', 'Material Icons Sharp', 'Material Icons Round'}: 4
{'Material Symbols Sharp', 'Material Icons', 'Material Icons Round', 'Material Icons Outlined', 'Material Symbols Outlined', 'Material Icons Sharp', 'Material Symbols Rounded'}: 1909

So there are some icons without a symbol.

@rodja
Copy link
Member

rodja commented Feb 26, 2024

I think we can just ignore the icon names missing from the Material Symbols:

access_alarm, access_alarms, access_time, access_time_filled, add_alarm, add_circle_outline, add_ic_call, addchart, announcement, app_settings_alt, assessment, assistant, assistant_photo, audiotrack, auto_awesome, auto_fix_high, auto_fix_normal, auto_fix_off, auto_graph, auto_mode, battery_20, battery_30, battery_50, battery_60, battery_80, battery_90, battery_std, block_flipped, bluetooth_audio, bookmark_border, browser_not_supported, business, camera_alt, camera_enhance, card_giftcard, catching_pokemon, chat_bubble_outline, check_circle_outline, class, clear, closed_caption_off, cloud_queue, collections, color_lens, control_point, create, crop_din, crop_original, data_saver_off, delete_outline, delivery_dining, directions_boat_filled, directions_bus_filled, directions_car_filled, directions_railway_filled, directions_subway_filled, directions_transit, directions_transit_filled, discount, do_disturb, do_disturb_alt, do_disturb_off, do_disturb_on, do_not_disturb, do_not_disturb_alt, drive_eta, drive_file_move_outline, drive_file_move_rtl, drive_file_rename_outline, email, emoji_emotions, error_outline, face_retouching_natural, face_unlock, favorite_border, file_download, file_upload, filter_list_alt, fire_hydrant_alt, fitbit, fmd_good, free_breakfast, games, generating_tokens, get_app, gpp_good, gps_fixed, gps_not_fixed, gps_off, headset, help_outline, highlight_alt, highlight_off, home_filled, hourglass_full, https, image_not_supported, import_export, info_outline, insert_chart_outlined, insert_comment, insert_drive_file, insert_emoticon, insert_invitation, insert_link, insert_photo, insights, iso, join_full, keyboard_voice, label_important_outline, laptop, launch, lightbulb_outline, local_airport, local_grocery_store, local_hotel, local_movies, local_offer, local_phone, local_play, local_printshop, location_pin, lock_outline, loop, mail_outline, maps_home_work, markunread, message, mic_none, miscellaneous_services, mode, mode_edit, mode_edit_outline, money_off_csred, moped, motion_photos_pause, movie_creation, movie_filter, nightlight_round, no_cell, no_encryption_gmailerrorred, no_meals_ouline, not_interested, note, notifications_none, ondemand_video, outlined_flag, panorama_horizontal_select, panorama_photosphere_select, panorama_vertical_select, panorama_wide_angle_select, pause_circle_filled, pause_circle_outline, payment, people, people_alt, people_outline, perm_identity, person_add_alt, person_add_alt_1, person_outline, person_remove_alt_1, personal_video, phone, phonelink, photo_filter, photo_size_select_actual, pie_chart_outline, pie_chart_outlined, pix, place, play_circle_filled, play_circle_outline, plus_one, poll, portrait, query_builder, question_answer, queue, remove_circle, remove_circle_outline, remove_red_eye, replay_circle_filled, report_gmailerrorred, report_problem, restore, room, save_alt, sd_storage, security_update, sentiment_satisfied_alt, settings_input_composite, settings_suggest, shop_2, shortcut, signal_cellular_connected_no_internet_1_bar, signal_cellular_connected_no_internet_2_bar, signal_cellular_connected_no_internet_3_bar, signal_cellular_no_sim, signal_wifi_1_bar, signal_wifi_1_bar_lock, signal_wifi_2_bar, signal_wifi_2_bar_lock, signal_wifi_3_bar, signal_wifi_3_bar_lock, signal_wifi_4_bar_lock, signal_wifi_connected_no_internet_0, signal_wifi_connected_no_internet_1, signal_wifi_connected_no_internet_2, signal_wifi_connected_no_internet_3, signal_wifi_connected_no_internet_4, signal_wifi_statusbar_1_bar, signal_wifi_statusbar_2_bar, signal_wifi_statusbar_3_bar, signal_wifi_statusbar_4_bar, signal_wifi_statusbar_connected_no_internet, signal_wifi_statusbar_connected_no_internet_1, signal_wifi_statusbar_connected_no_internet_2, signal_wifi_statusbar_connected_no_internet_3, signal_wifi_statusbar_connected_no_internet_4, sim_card_alert, smart_button, sms_failed, source, star_border, star_border_purple500, star_outline, star_purple500, store_mall_directory, system_security_update, system_security_update_good, system_security_update_warning, tag_faces, terrain, textsms, thumb_down_alt, thumb_down_off_alt, thumb_up_alt, thumb_up_off_alt, time_to_leave, tips_and_updates, try, tungsten, turned_in, turned_in_not, warning_amber, watch_later, wb_cloudy, wb_twighlight, work_off, work_outline, workspaces_filled, workspaces_outline

The probes I took looked like the icons are still available but just not through the (strange) name.

@falkoschindler
Copy link
Contributor Author

I think we can just ignore the icon names missing from the Material Symbols [...]
The probes I took looked like the icons are still available but just not through the (strange) name.

@rodja I don't quite get what you're saying. 🤔

@rodja
Copy link
Member

rodja commented Feb 26, 2024

I mean we should only provide Material Symbols through the icons module. And possibly drop the Material Icons (+ Outline and Rounded) in 2.0.

@falkoschindler falkoschindler added this to the 2.0.0 milestone Apr 8, 2024
@falkoschindler falkoschindler modified the milestones: 2.0.0, 2.x Aug 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants