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

Add multi-path icon support and path attributes #18189

Merged
merged 8 commits into from
Oct 19, 2023

Conversation

sisimomo
Copy link
Contributor

@sisimomo sisimomo commented Oct 11, 2023

Breaking change

This PR does not introduce any breaking changes. I have taken care to ensure that the existing 'path' property remains fully functional. Additionally, I've introduced a new 'paths' property as an optional feature. This enhancement is designed to provide users with greater flexibility and customization options while preserving the seamless experience of those who choose not to use the 'paths' feature. This change is aimed at empowering users with more choices rather than disrupting their current usage of the 'path' property.

Proposed change

I aimed to enhance Home Assistant's capabilities by introducing support for multi-color icons. To achieve this, I've implemented the ability to compose icons from multiple distinct paths, each with its own set of customizable attributes. The primary change involves the addition of the 'paths' property within the 'CustomIcon' interface, allowing custom icon packs for Home Assistant to create intricate and multi-path icons with individually specified attributes. This enhancement empowers users to create more visually diverse and dynamic icons, which can greatly enhance the overall aesthetics and user experience of Home Assistant. I believe that these additions will provide Home Assistant users with a richer and more versatile icon customization option, aligning with the project's commitment to user-driven flexibility and personalization.

Here an example of what enable this new feature:
image
image

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (thank you!)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Example configuration

To explore this exciting new feature, I've performed the following steps on my local instance:

config/configuration.yaml
frontend:
  extra_module_url:
    - /local/hass-multi-color-icons/hass-multi-color-icons.js
    - /local/card-mod.js

switch:
  - platform: virtual
    name: Switch 1
    initial_value: on
  - platform: virtual
    name: Switch 2
    initial_value: off

light:
  - platform: virtual
    name: "Light 1"
    initial_value: "on"
    support_brightness: true
    initial_brightness: 100
    support_color: true
    initial_color: [0, 255]
    support_color_temp: true
    initial_color_temp: 255
    support_white_value: true
    initial_white_value: 240
    initial_availability: true
  - platform: virtual
    name: "Light 2"
    initial_value: "off"
    support_brightness: true
    initial_brightness: 100
    support_color: true
    initial_color: [0, 255]
    support_color_temp: true
    initial_color_temp: 255
    support_white_value: true
    initial_white_value: 240
    initial_availability: true
  - platform: virtual
    name: "Light 3"
    initial_value: "on"
    support_brightness: true
    initial_brightness: 100
    support_color: true
    initial_color: [0, 255]
    support_color_temp: true
    initial_color_temp: 255
    support_white_value: true
    initial_white_value: 240
    initial_availability: true
  - platform: virtual
    name: "Light 4"
    initial_value: "on"
    support_brightness: true
    initial_brightness: 100
    support_color: true
    initial_color: [0, 255]
    support_color_temp: true
    initial_color_temp: 255
    support_white_value: true
    initial_white_value: 240
    initial_availability: true
  - platform: virtual
    name: "Light 5"
    initial_value: "on"
    support_brightness: true
    initial_brightness: 100
    support_color: true
    initial_color: [0, 255]
    support_color_temp: true
    initial_color_temp: 255
    support_white_value: true
    initial_white_value: 240
    initial_availability: true

fan:
  - platform: virtual
    name: Fan 1
    speed: True
    speed_count: 5
    direction: True
    oscillate: True
  - platform: virtual
    name: Fan 2
    speed: True
    speed_count: 5
    direction: True
    oscillate: True

config/www/card-mod.js

config/custom_components/virtual

config/www/hass-multi-color-icons/hass-multi-color-icons.js
const MULTI_COLOR_ICONS_MAP = {
  "mdi_ceiling-light": {
    paths: [
      {
        value: "m 8,9 h 3 v 0 h 2 v 0 h 3 l 4,8 H 4 L 8,9",
        attributes: {
          "data-type": "colored",
        },
      },
      {
        value: "M 11,9 V 9 4 h 2 v 5 0 0 h -2 v 0 m 3,9 c 0,1.104569 -0.895431,2 -2,2 -1.104569,0 -2,-0.895431 -2,-2 z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["home automation", "ceiling-lamp"],
  },
  "mdi_coach-lamp": {
    paths: [
      {
        value: "m 10,8 1.839844,9 h 4.320312 L 18,8 Z",
        attributes: {
          "data-type": "colored",
          fill: "transparent",
        },
      },
      {
        value: "M16 5L15 2H13L12 5L6 8H8L8.6 11H4V7H2V17H4V13H9L10 18L12 20L13 22H15L16 20L18 18L20 8H22M16.16 17H11.84L10 8H18Z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["home automation", "coach-light", "carriage-lamp", "carriage-light"],
  },
  mdi_doorbell: {
    paths: [
      {
        value: "m 12,10 c -1.1,0 -2,0.9 -2,2 0,1.1 0.9,2 2,2 1.1,0 2,-0.9 2,-2 0,-1.1 -0.9,-2 -2,-2",
        attributes: {
          "data-type": "colored",
        },
      },
      {
        value: "M 16,2 H 8 C 6.9,2 6,2.9 6,4 v 16 c 0,1.1 0.9,2 2,2 h 8 c 1.1,0 2,-0.9 2,-2 V 4 C 18,2.9 17.1,2 16,2 m 0,18 H 8 V 4 h 8 z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["home automation"],
  },
  mdi_fan: {
    paths: [
      {
        value:
          "M 12.5,2 C 8.9407508,2 8.1502639,5.959102 10.138672,9.6484375 10.668374,9.2288235 11.324233,9.0003395 12,9 12.387672,8.9998095 12.771707,9.0747593 13.130859,9.2207031 13.320859,8.2907031 13.76,7.24 14.75,6.75 17.11,5.57 17,2 12.5,2 Z M 4.3222656,7.7324219 C 3.1266455,7.825564 2,8.96875 2,11.5 c 0,3.57 3.9603906,4.349141 7.6503906,2.369141 0.00458,0.0057 -0.00462,-0.0057 0,0 C 9.2194471,13.335499 9.0000106,12.68592 9,12 c -1.905e-4,-0.387672 0.074759,-0.771707 0.2207031,-1.130859 -0.93,-0.19 -1.9804687,-0.619375 -2.4804687,-1.6093754 C 6.2239844,8.2228906 5.2521924,7.659978 4.3222656,7.7324219 Z M 18.40625,9.0566406 c -1.241602,-0.034688 -2.669141,0.3242188 -4.056641,1.0742184 -0.0049,-0.0062 0.005,0.0061 0,0 C 14.781255,10.664239 14.999436,11.313843 15,12 c 2.97e-4,0.38269 -0.07263,0.761904 -0.214844,1.117188 v 0 c 0.930001,0.19 1.994141,0.623281 2.494141,1.613281 1.18,2.37 4.75,2.269531 4.75,-2.230469 0,-2.2375 -1.553711,-3.3855469 -3.623047,-3.4433594 z M 13.880859,14.339844 C 13.345667,14.775707 12.690222,15.00002 12,15 c -0.38269,2.97e-4 -0.754091,-0.06872 -1.109375,-0.210938 0.0027,0.0011 -0.0027,-0.0011 0,0 -0.2,0.920001 -0.641094,1.961172 -1.6210938,2.451172 C 6.9095312,18.420234 7,22 11.5,22 c 3.58,0 4.370859,-3.970156 2.380859,-7.660156 0.005,-0.0043 -0.005,0.0043 0,0 z",
        attributes: {
          "data-type": "colored",
        },
      },
      {
        value:
          "M 11.947266,8.9981049 A 3.0014853,3.0014853 0 0 0 8.998047,12.000058 3.0014853,3.0014853 0 0 0 12,15.002011 3.0014853,3.0014853 0 0 0 15.001953,12.000058 3.0014853,3.0014853 0 0 0 12,8.9981049 a 3.0014853,3.0014853 0 0 0 -0.05273,0 z m 0.05273,2.0019531 a 1,1 0 0 1 1,1 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["home automation", "automotive"],
  },
  "mdi_floor-lamp": {
    paths: [
      {
        value: "m 15,2 2,7 H 7 L 9,2",
        attributes: {
          "data-type": "colored",
        },
      },
      {
        value: "m 11,10 h 2 v 10 h 3 v 2 H 8 v -2 h 3 z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["home automation", "floor-light"],
  },
  mdi_lamp: {
    paths: [
      {
        value: "m 8,2 h 8 l 4,12 H 4 L 8,2",
        attributes: {
          "data-type": "colored",
        },
      },
      {
        value: "m 11,15 h 2 v 5 h 5 v 2 H 6 v -2 h 5 z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["home automation"],
  },
  "mdi_mirror-rectangle": {
    paths: [
      {
        value:
          "M 6 3 L 6 21 L 18 21 L 18 3 L 6 3 z M 11.529297 7.0292969 L 12.589844 8.0898438 L 9.3496094 11.339844 L 8.2890625 10.279297 L 11.529297 7.0292969 z M 14.359375 8.9492188 L 15.419922 10 L 9.7597656 15.669922 L 8.6992188 14.609375 L 14.359375 8.9492188 z",
        attributes: {
          "data-type": "colored",
          fill: "transparent",
        },
      },
      {
        value: "m8.29 10.28l3.24-3.25l1.06 1.06l-3.24 3.25l-1.06-1.06m.41 4.33l5.66-5.66L15.42 10l-5.66 5.67l-1.06-1.06M18 3v18H6V3h12m2-2H4v22h16V1Z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["home automation"],
  },
  mdi_television: {
    paths: [
      {
        value: "M 3,5 V 17 H 21 V 5 Z",
        attributes: {
          "data-type": "colored",
          fill: "transparent",
        },
      },
      {
        value: "M21,17H3V5H21M21,3H3A2,2 0 0,0 1,5V17A2,2 0 0,0 3,19H8V21H16V19H21A2,2 0 0,0 23,17V5A2,2 0 0,0 21,3Z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["device tech", "home automation", "tv"],
  },
  "mdi_vanity-light": {
    paths: [
      {
        value:
          "m 22,20 h -6 c 0,-1.66 1.34,-7 3,-7 1.66,0 3,5.34 3,7 M 12,13 c -1.66,0 -3,5.34 -3,7 h 6 c 0,-1.66 -1.34,-7 -3,-7 M 5,13 C 3.34,13 2,18.34 2,20 H 8 C 8,18.34 6.66,13 5,13",
        attributes: {
          "data-type": "colored",
        },
      },
      {
        value:
          "M 14.82,6 C 14.26,4.44 12.53,3.64 11,4.2 10.14,4.5 9.5,5.17 9.18,6 H 2 v 2 h 2 v 4 H 6 V 8 H 9.18 C 9.5,8.85 10.15,9.5 11,9.82 V 12 h 2 V 9.82 C 13.85,9.5 14.5,8.85 14.82,8 H 18 v 4 h 2 V 8 h 2 V 6 Z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["bathroom", "light", "wall"],
  },
  hue_adore: {
    paths: [
      {
        value:
          "m 2.4003906,11.699219 c -0.1,0 -0.4003906,0.40039 -0.4003906,0.90039 0,0.6 0.3003906,0.59961 0.4003906,0.59961 H 21.599609 c 0.1,0 0.400782,3.9e-4 0.300782,-0.59961 0,-0.6 -0.200391,-0.90039 -0.400391,-0.90039 z",
        attributes: {
          "data-type": "colored",
          fill: "transparent",
        },
      },
      {
        value:
          "M21.6,8.8H2.4C1.6,8.8,1,9.7,1,10.7v1.9c0,1.1,0.7,1.6,1.4,1.6h6.9c0,0,0,0,0,0.1v0.4c0,0.6,0.5,1.1,1.1,1.1 h3.3c0.6,0,1.1-0.5,1.1-1.1v-0.4c0,0,0,0,0-0.1h6.9c0.7,0,1.4-0.5,1.4-1.6v-1.9C23,9.7,22.4,8.8,21.6,8.8z M21.6,13.2H2.4 c-0.1,0-0.4,0-0.4-0.6c0-0.5,0.3-0.9,0.4-0.9h19.1c0.2,0,0.4,0.3,0.4,0.9C22,13.2,21.7,13.2,21.6,13.2z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["bathroom", "light", "wall"],
  },
  "hue_bulb-group-classic-4-alt": {
    paths: [
      {
        value:
          "m 17.25,9.96 c 0,0.22 -0.04,0.41 -0.06,0.61 -0.03,0.19 -0.06,0.35 -0.1,0.53 -0.82,0.35 -2.55,0.75 -5.09,0.75 -2.54,0 -4.27,-0.39 -5.09,-0.74 C 6.87,10.93 6.83,10.77 6.81,10.58 6.79,10.38 6.75,10.18 6.75,9.97 6.75,7.59 9.11,5.09 12,5.09 c 2.89,0 5.25,2.5 5.25,4.87 z M 15.26,2.99 C 14.52,2.04 13.34,1.34 12,1.34 c -1.34,0 -2.52,0.7 -3.26,1.65 0.61,0.35 1.13,0.82 1.53,1.36 0.56,-0.17 1.14,-0.26 1.73,-0.26 0.61,0 1.18,0.1 1.73,0.26 0.4,-0.53 0.92,-1.01 1.53,-1.36 z M 9.69,4.56 C 8.95,3.65 7.79,2.98 6.49,2.98 4.25,2.98 2.42,4.92 2.42,6.76 2.42,6.92 2.45,7.08 2.47,7.23 2.49,7.38 2.52,7.5 2.55,7.64 3.14,7.9 4.34,8.17 6.08,8.21 6.67,6.61 8.03,5.24 9.69,4.56 Z m 11.9,2.19 c 0,-1.83 -1.83,-3.77 -4.07,-3.77 -1.31,0 -2.45,0.66 -3.2,1.57 1.71,0.7 3.01,2.12 3.59,3.66 1.74,-0.04 2.95,-0.32 3.54,-0.57 0.03,-0.14 0.06,-0.26 0.08,-0.41 0.02,-0.16 0.05,-0.3 0.06,-0.48 z",
        attributes: {
          "data-type": "colored",
        },
      },
      {
        value:
          "m 15,15.59 c -0.1,0.61 -0.19,1.47 -0.13,2.1 0.04,0.4 -0.26,0.75 -0.66,0.79 -0.65,0.07 -1.38,0.11 -2.21,0.11 -0.83,0 -1.56,-0.04 -2.21,-0.11 C 9.39,18.44 9.08,18.09 9.12,17.69 9.18,17.06 9.1,16.2 8.99,15.59 8.75,14.18 7.75,13.51 7.18,12 c 1.41,0.45 3.48,0.59 4.82,0.59 1.34,0 3.41,-0.14 4.82,-0.59 -0.58,1.51 -1.58,2.18 -1.82,3.59 z m -1.12,5.97 c -0.02,0.16 -0.11,0.32 -0.23,0.43 l -0.35,0.32 c -0.03,0.02 -0.05,0.05 -0.07,0.07 l -0.37,0.44 c -0.14,0.17 -0.36,0.27 -0.59,0.27 h -0.55 c -0.23,0 -0.45,-0.1 -0.57,-0.26 L 10.78,22.39 C 10.76,22.36 10.73,22.34 10.71,22.32 L 10.36,22 C 10.23,21.89 10.15,21.73 10.13,21.57 L 9.75,19.24 c 0.78,0.07 1.64,0.1 2.25,0.1 0.61,0 1.47,-0.03 2.25,-0.1 z M 5.9,8.78 C 4.9,8.75 3.66,8.63 2.75,8.34 c 0.44,1.17 1.21,1.69 1.4,2.78 0.08,0.48 0.15,1.14 0.1,1.63 -0.03,0.31 0.21,0.58 0.52,0.61 0.5,0.06 1.07,0.09 1.71,0.09 0.1,0 0.19,-0.01 0.28,-0.01 C 6.58,13.12 6.4,12.77 6.24,12.36 6.17,12.19 6.02,11.75 5.93,11.34 V 11.33 L 5.91,11.26 C 5.9,11.25 5.9,11.23 5.9,11.22 5.89,11.18 5.89,11.14 5.88,11.1 5.86,10.98 5.83,10.85 5.81,10.69 5.8,10.63 5.8,10.57 5.79,10.52 5.77,10.36 5.75,10.18 5.75,9.97 5.75,9.57 5.8,9.17 5.9,8.78 Z m 0.59,5.25 C 6.02,14.03 5.35,14 4.75,13.95 l 0.29,1.81 c 0.02,0.12 0.08,0.24 0.18,0.33 l 0.27,0.24 c 0.02,0.02 0.04,0.03 0.05,0.06 l 0.29,0.34 c 0.09,0.12 0.26,0.2 0.44,0.2 H 6.7 c 0.18,0 0.35,-0.08 0.46,-0.21 L 7.44,16.38 C 7.46,16.36 7.47,16.34 7.5,16.33 L 7.77,16.08 C 7.86,15.99 7.93,15.87 7.95,15.74 L 7.96,15.62 C 7.84,15.11 7.58,14.7 7.25,14.2 7.21,14.14 7.17,14.07 7.13,14.01 6.9,14.02 6.68,14.02 6.49,14.03 Z m 10.75,-0.6 c 0.09,0 0.18,0.01 0.28,0.01 0.64,0 1.21,-0.04 1.71,-0.09 0.31,-0.03 0.54,-0.3 0.51,-0.61 -0.05,-0.49 0.02,-1.16 0.1,-1.63 0.19,-1.09 0.96,-1.61 1.41,-2.78 -0.92,0.29 -2.16,0.41 -3.16,0.44 0.1,0.39 0.16,0.79 0.16,1.18 0,0.22 -0.03,0.4 -0.05,0.55 -0.01,0.05 -0.01,0.11 -0.02,0.16 0,0.02 -0.01,0.04 -0.01,0.06 -0.01,0.1 -0.03,0.18 -0.05,0.27 V 11 c 0,0.04 -0.02,0.16 -0.06,0.31 v 0.01 0 c -0.1,0.38 -0.27,0.94 -0.31,1.04 -0.15,0.41 -0.34,0.76 -0.51,1.07 z m -1.21,2.16 0.03,0.17 c 0.02,0.12 0.08,0.24 0.18,0.33 l 0.27,0.25 0.05,0.05 0.29,0.34 c 0.09,0.12 0.26,0.2 0.44,0.2 h 0.43 c 0.18,0 0.35,-0.08 0.46,-0.21 l 0.29,-0.34 0.05,-0.05 0.25,-0.25 c 0.09,-0.08 0.16,-0.21 0.18,-0.33 l 0.29,-1.8 c -0.6,0.06 -1.27,0.08 -1.74,0.08 -0.18,0 -0.41,0 -0.64,-0.01 l -0.12,0.18 c -0.32,0.49 -0.58,0.89 -0.71,1.39 z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["light"],
  },
  "hue_ceiling-aurelle-circle": {
    paths: [
      {
        value: "m 3.9,12.5 c 0,1.8 4.1,2.7 8.1,2.7 4,0 8.1,-0.9 8.1,-2.7 C 20.2,9 3.9,9 3.9,12.5 Z",
        attributes: {
          "data-type": "colored",
        },
      },
      {
        value:
          "m 12,6.4 c -6.4,0 -11.5,2.2 -11.5,5 v 1 c 0,2.8 5,5 11.5,5 6.5,0 11.5,-2.2 11.5,-5 v -1 c 0,-2.8 -5,-5 -11.5,-5 z m 0,9.9 c -6.3,0 -10.5,-2 -10.5,-4 0,-2 4.2,-4 10.5,-4 6.3,0 10.5,2 10.5,4 0,2 -4.2,4 -10.5,4 z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["light"],
  },
  "hue_ceiling-still": {
    paths: [
      {
        value:
          "m 12.12341,10.77791 c 0,0 -5.51306,0.03845 -5.49383,1.1145 0.01922,1.076 4.51227,1.46033 5.49383,1.46033 0.98156,0 5.38172,-0.38434 5.38172,-1.49878 0,-1.11444 -5.38172,-1.07605 -5.38172,-1.07605 z",
        attributes: {
          "data-type": "colored",
        },
      },
      {
        value:
          "m 22.45312,9.7068 c -1.73339,-1.89062 -5.209,-2.84912 -10.32958,-2.84912 -5.12159,0 -8.59717,0.9585 -10.33008,2.84912 -0.6564974,0.65171 -1.03352062,1.533381 -1.05121,2.45826 l -6e-5,2.4e-4 6e-5,3e-4 0.00189,0.04316 c 0.005512,0.03076 0.014016,0.0609 0.02539,0.09 0.29028,2.19428 7.497,2.78351 11.354,2.78351 3.85723,0 11.06286,-0.58929 11.35394,-2.78314 0.01143,-0.02922 0.01996,-0.0595 0.02545,-0.09039 -0.0015,-0.940775 -0.379518,-1.841802 -1.0498,-2.50194 z m -10.32958,4.37549 c -6.84913,0 -10.38135,-1.34375 -10.38135,-1.917 0,-0.57325 3.53222,-1.917 10.38135,-1.917 6.84913,0 10.38134,1.34375 10.38134,1.917 0,0.57325 -3.53222,1.917 -10.38134,1.917 z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["light"],
  },
  "hue_lightstrip-tv": {
    paths: [
      {
        value:
          "m 20.992187,13.304688 a 0.796875,0.80859375 0 0 1 -0.796875,0.808594 0.796875,0.80859375 0 0 1 -0.796875,-0.808594 0.796875,0.80859375 0 0 1 0.796875,-0.808593 0.796875,0.80859375 0 0 1 0.796875,0.808593 z m 0,-3.710938 A 0.796875,0.80859375 0 0 1 20.195312,10.402344 0.796875,0.80859375 0 0 1 19.398437,9.59375 0.796875,0.80859375 0 0 1 20.195312,8.7851563 0.796875,0.80859375 0 0 1 20.992187,9.59375 Z m 0,-3.7890625 a 0.796875,0.80859375 0 0 1 -0.796875,0.8085937 0.796875,0.80859375 0 0 1 -0.796875,-0.8085937 0.796875,0.80859375 0 0 1 0.796875,-0.8085938 0.796875,0.80859375 0 0 1 0.796875,0.8085938 z m -4.003906,-0.00391 A 0.796875,0.80859375 0 0 1 16.191406,6.609375 0.796875,0.80859375 0 0 1 15.394531,5.8007812 0.796875,0.80859375 0 0 1 16.191406,4.9921875 0.796875,0.80859375 0 0 1 16.988281,5.8007812 Z m -3.898437,0.00781 A 0.796875,0.80859375 0 0 1 12.292969,6.6171875 0.796875,0.80859375 0 0 1 11.496094,5.8085937 0.796875,0.80859375 0 0 1 12.292969,5 0.796875,0.80859375 0 0 1 13.089844,5.8085937 Z m -3.996094,0 A 0.796875,0.80859375 0 0 1 8.296875,6.6171875 0.796875,0.80859375 0 0 1 7.5,5.8085937 0.796875,0.80859375 0 0 1 8.296875,5 0.796875,0.80859375 0 0 1 9.09375,5.8085937 Z M 5.1914062,5.7929687 A 0.796875,0.80859375 0 0 1 4.3945312,6.6015625 0.796875,0.80859375 0 0 1 3.5976563,5.7929687 0.796875,0.80859375 0 0 1 4.3945312,4.984375 0.796875,0.80859375 0 0 1 5.1914062,5.7929687 Z m 0.00391,3.8085948 A 0.796875,0.80859375 0 0 1 4.3984375,10.410157 0.796875,0.80859375 0 0 1 3.6015625,9.6015635 0.796875,0.80859375 0 0 1 4.3984375,8.7929697 0.796875,0.80859375 0 0 1 5.1953125,9.6015635 Z M 5.0898437,13.410155 a 0.796875,0.80859375 0 0 1 -0.796875,0.808594 0.796875,0.80859375 0 0 1 -0.7968749,-0.808594 0.796875,0.80859375 0 0 1 0.7968749,-0.808593 0.796875,0.80859375 0 0 1 0.796875,0.808593 z",
        attributes: {
          "data-type": "colored",
        },
      },
      {
        value:
          "M 21.8,3.4 H 3 C 2.4,3.4 1.8,4 1.8,4.7 v 10.2 c 0,0.7 0.5,1.2 1.2,1.2 h 0.4 v 0 h 8.2 v 2.8 h -1.4 c -0.4,0 -0.8,0.3 -0.8,0.8 0,0.5 0.3,0.8 0.8,0.8 h 4.4 c 0.4,0 0.8,-0.3 0.8,-0.8 0,-0.5 -0.3,-0.8 -0.8,-0.8 h -1.5 v -2.8 h 6.2 1.2 1 c 0.7,0 1.2,-0.6 1.2,-1.2 V 4.7 c 0,-0.3 0,-1.3 -0.9,-1.3 z m 0.0016,11.5 c 0,0.1 -0.1,0.2 -0.2,0.2 H 19 c -0.2,0 -0.3,0 -0.4,-0.1 -0.1,-0.1 -0.1,-0.2 -0.1,-0.2 V 9 C 18.5,8.4 18.3,8.1 18.1,7.9 17.7,7.5 17.2,7.5 17.1,7.5 v 0 H 7.2 C 6.3,7.5 5.9,8.3 5.9,8.8 v 6 c 0,0.2 -0.2,0.3 -0.2,0.3 H 3.1 C 3,15.1 2.9,15 2.9,14.9 V 4.7 C 2.9,4.6 3,4.5 3.1,4.5 h 18.54375 c 0,0 0.08001,-0.0061 0.125,0.041406 C 21.81084,4.5858503 21.8,4.7 21.8,4.7 c 0.002,3.3993138 -0.0034,6.803448 0.0016,10.2 z",
        attributes: {
          "data-type": "not_colored",
        },
      },
    ],
    keywords: ["led", "light"],
  },
};

async function getIcon(name) {
  let new_name;

  if (!(name in MULTI_COLOR_ICONS_MAP)) {
    // try swapping the '_' for a '-'
    new_name = name.replace(/_/gm, `-`);
    if (!(new_name in MULTI_COLOR_ICONS_MAP)) {
      console.log(`Icon "${name}" is not available`);
      return "";
    } else {
      console.log(`Aliased "${name}" with "${new_name}"`);
      return { path: MULTI_COLOR_ICONS_MAP[new_name].path };
    }
  }
  return { paths: MULTI_COLOR_ICONS_MAP[name].paths };
}

async function getIconList() {
  return Object.entries(MULTI_COLOR_ICONS_MAP).map(([icon, content]) => ({
    name: icon,
    keywords: content.keywords,
  }));
}
window.customIcons = window.customIcons || {};
window.customIcons["mci"] = { getIcon, getIconList };

window.customIconsets = window.customIconsets || {};
window.customIconsets["mci"] = getIcon;

console.info(
  `%c MULTI-COLOR-ICONS %c Version 0.0.1`,
  "color: orange; font-weight: bold; background: black",
  "color: white; font-weight: bold; background: dimgray"
);
Then I created a dashboard
title: Home
views:
  - path: default_view
    title: Home
    badges: []
    cards:
      - square: false
        type: grid
        cards:
          - type: tile
            entity: light.virtual_light_1
            icon: mci:mdi_ceiling-light
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_1
            icon: mci:mdi_coach-lamp
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: currentcolor;
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_1
            icon: mci:mdi_doorbell
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: mci:mdi_ceiling-light
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: mci:mdi_coach-lamp
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: mci:mdi_doorbell
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
        columns: 3
      - square: false
        type: grid
        cards:
          - type: tile
            entity: fan.virtual_fan_1
            icon: mci:mdi_fan
            color: black
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                  svg{
                   animation: 2s linear 0s infinite normal none running rotating;
                  }
                  @keyframes rotating {
                    0% { 
                      transform: rotate(0); 
                    }
                    100% { 
                      transform: rotate(360deg);
                    }
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_3
            icon: mci:mdi_floor-lamp
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_3
            icon: mci:mdi_lamp
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: fan.virtual_fan_2
            icon: mci:mdi_fan
            color: white
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                  svg{
                   animation: 2s linear 0s infinite normal none running rotating;
                  }
                  @keyframes rotating {
                    0% { 
                      transform: rotate(0); 
                    }
                    100% { 
                      transform: rotate(360deg);
                    }
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: mci:mdi_floor-lamp
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: mci:mdi_lamp
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
        columns: 3
      - square: false
        type: grid
        cards:
          - type: tile
            entity: light.virtual_light_4
            icon: mci:mdi_mirror-rectangle
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: currentcolor;
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_4
            icon: mci:mdi_television
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: currentcolor;
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_4
            icon: mci:mdi_vanity-light
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: mci:mdi_mirror-rectangle
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: currentcolor;
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: mci:mdi_television
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: currentcolor;
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: mci:mdi_vanity-light
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
        columns: 3
      - square: false
        type: grid
        cards:
          - type: tile
            entity: light.virtual_light_5
            icon: mci:hue_adore
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: currentcolor;
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_5
            icon: mci:hue_bulb-group-classic-4-alt
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_5
            icon: mci:hue_ceiling-aurelle-circle
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: mci:hue_adore
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: mci:hue_bulb-group-classic-4-alt
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: mci:hue_ceiling-aurelle-circle
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
        columns: 3
      - square: false
        type: grid
        cards:
          - type: tile
            entity: switch.virtual_switch_1
            icon: mci:hue_ceiling-still
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: switch.virtual_switch_1
            icon: mci:hue_lightstrip-tv
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: switch.virtual_switch_1
            icon: mci:hue_ceiling-still
          - type: tile
            entity: switch.virtual_switch_2
            icon: mci:hue_ceiling-still
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: switch.virtual_switch_2
            icon: mci:hue_lightstrip-tv
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path[data-type="colored"] {
                    fill: rgba(158, 158, 158, 0.4);
                  }
                  svg path[data-type="not_colored"] {
                    fill: rgba(158, 158, 158, 1);
                  }
          - type: tile
            entity: switch.virtual_switch_2
            icon: mci:hue_ceiling-still
        columns: 3
      - show_name: false
        show_icon: true
        show_state: false
        type: glance
        entities:
          - entity: sensor.sun_next_dawn
          - entity: sensor.sun_next_dusk
          - entity: sensor.sun_next_midnight
          - entity: sensor.sun_next_noon
          - entity: sensor.sun_next_rising
          - entity: sensor.sun_next_setting
          - entity: input_button.test_1
          - entity: input_button.test_2
          - entity: input_button.test_3
          - entity: input_button.test_4
          - entity: input_button.test_5
          - entity: input_button.test_6
          - entity: input_button.test_7
          - entity: input_button.test_8
        columns: 7

Animation

Additional information

  • This PR fixes or closes issue: fixes #
  • This PR is related to issue or discussion:
  • Link to documentation pull request:

Checklist

  • The code change is tested and works locally.
  • There is no commented out code in this PR.
  • Tests have been added to verify that the new code works. (No existing tests for "src/components/ha-svg-icon.ts" or for "src/components/ha-icon.ts", so not needed)

If user exposed functionality or configuration variables are added/changed:

@sisimomo
Copy link
Contributor Author

Hello,

I'm encountering an issue and could use some assistance. The 'CI / Lint and check format (pull_request)' task is currently throwing the following error:

/home/runner/work/frontend/frontend/src/components/ha-svg-icon.ts
Error: 11:27 error Unexpected use of file extension "js" for "lit/directives/unsafe-svg.js" import/extensions

However, when I attempt to resolve this issue by removing the 'js' extension from the file, I encounter a different error:

Module not found: Error: Package path './directives/unsafe-svg' is not exported from the package '/workspaces/frontend/node_modules/lit' (see exports field in '/workspaces/frontend/node_modules/lit/package.json)

In my search for a solution, I came across this helpful StackOverflow comment.

I would greatly appreciate any assistance in resolving this matter.

Thank you!

@bramkragten
Copy link
Member

bramkragten commented Oct 11, 2023

I think this changes too much of the core code for a feature that can only be used by custom things.

I suggest the following:

  • Add a new optional property secondaryPath to ha-svg-icon and CustomIcon
  • path will be the primary path (like it already is)
  • Add css in ha-svg-icon for primary and secondary path:
.primary-path {
	fill: var(--icon-primary-color, currentcolor);
	opacity: var(--icon-primary-opactity, 1);
}
.secondary-path {
	fill: var(--icon-secondary-color, currentcolor);
	opacity: var(--icon-secondary-opactity, .4);
}

This way duo tone icons will work out of the box, and can be styled with themes instead of just card-mod.
Also our current logic doesn't have to be changed, and we don't need any logic for legacy handling.

@sisimomo
Copy link
Contributor Author

sisimomo commented Oct 11, 2023

Hi,

I want to share some of my concerns regarding the proposed solution. I believe it's crucial to maintain the ability for creators of custom icon packs to add attributes to their paths. This feature is in my opinion vital as it enables some customization, which can essential for certain use cases. To illustrate this, I've included an example that demonstrates how these path attributes are indispensable in some cases. Take a look at the following example:

let mdi_television = {
  paths: [
    {
      value: "M 3,5 V 17 H 21 V 5 Z",
      attributes: {
        "data-type": "colored",
        fill: "transparent",
      },
    },
    {
      value: "M21,17H3V5H21M21,3H3A2,2 0 0,0 1,5V17A2,2 0 0,0 3,19H8V21H16V19H21A2,2 0 0,0 23,17V5A2,2 0 0,0 21,3Z",
      attributes: {
        "data-type": "not_colored",
      },
    },
  ],
  keywords: ["device tech", "home automation", "tv"],
};

image
Without the custom attribute fill: "transparent" the icon would look significantly different if not altered with custom CSS, as highlighted in red in the image.

Furthermore, path attributes also allow users not to be tied to a specific theme. But if wanted, creators of custom icon packs can easily add class attributes to their paths to allow customization through themes.

While your proposal for a secondaryPath property is intriguing and simplifies duo-tone icon support, I have some concerns about its potential limitations. It might restrict the flexibility required by certain use cases, especially for more complex icons with three or more colors. Here's an example for reference:
image
Source - matt8707/hass-config

I'm entirely open to making adjustments to ensure that my feature request aligns better with the project's goals. If you have any alternative ideas or guidance on how we can achieve maximum customization while minimizing the impact on the core code, I'd greatly appreciate your thoughts and input.

Thank you for your consideration, and I look forward to find a solution together to create this feature.

@bramkragten
Copy link
Member

bramkragten commented Oct 12, 2023

I understand that my proposal has it's limitations but still feel we would deal with 90%+ of the use cases this way.

I do not want to make this overly complex, and it should be useable without using card mod for styling. Your example with the fill: "transparent" attribute can never work without using a custom card, while it could also work with my proposal with the --icon-primary-color or --icon-primary-opactity css variables (which you can set with card mod if you want).

I don't think we want to support more than 2 paths at the moment, I don't think there are enough icons and use-cases around for that.

@sisimomo
Copy link
Contributor Author

Hello,

First and foremost, I'd like to express my gratitude for your prompt responses.

I'd like to suggest a compromise after carefully considering your idea. It seems feasible to combine the strengths of both solutions - your approach's simplicity and my approach's customization.

Here's the proposal:
We can introduce an 'innerSvg' property to both 'ha-svg-icon' and 'CustomIcon'. This won't affect the standard 'path' method for creating SVG icons, which is currently in use. With this enhancement, users will gain the freedom to craft their ideal icons by simply passing the inner SVG as strings.

I'm interested in hearing your thoughts on this idea.

@bramkragten
Copy link
Member

Your solution makes the current logic easier, but is still very focused on custom use cases. There will be no standard ways of styling the icons etc.

This is great for really custom icons, but 90% of the use-cases simply don't need that, and work fine with just 2 paths, that would also just work normally out of the box without extra custom resources.

Other than that, your proposal also brings security issues (although custom resources in general are already security issues) by allowing any content unsafe in the svg.

@sisimomo
Copy link
Contributor Author

sisimomo commented Oct 13, 2023

Hello,

I appreciate your feedback and I wanted to clarify my intentions with this feature. I designed it specifically for Custom Icons and intentionally not standardized to allow for nearly limitless customization while remaining straightforward to understand and implement.

Nevertheless, thanks to the secondaryPath solution, I successfully attained the visual outcome I was aiming for. I've made the essential adjustments to implement this solution.

Below, you can see how the dashboard appears with this new implementation.

image
image

config/www/hass-dual-color-icons/hass-dual-color-icons.js
const DUAL_COLOR_ICONS_MAP = {
  "mdi_ceiling-light": {
    secondaryPath: "M 11,9 V 9 4 h 2 v 5 0 0 h -2 v 0 m 3,9 c 0,1.104569 -0.895431,2 -2,2 -1.104569,0 -2,-0.895431 -2,-2 z",
    path: "m 8,9 h 3 v 0 h 2 v 0 h 3 l 4,8 H 4 L 8,9",
  },
  "mdi_coach-lamp": {
    secondaryPath: "M16 5L15 2H13L12 5L6 8H8L8.6 11H4V7H2V17H4V13H9L10 18L12 20L13 22H15L16 20L18 18L20 8H22M16.16 17H11.84L10 8H18Z",
    path: "m 10,8 1.839844,9 h 4.320312 L 18,8 Z",
  },
  mdi_doorbell: {
    secondaryPath: "M 16,2 H 8 C 6.9,2 6,2.9 6,4 v 16 c 0,1.1 0.9,2 2,2 h 8 c 1.1,0 2,-0.9 2,-2 V 4 C 18,2.9 17.1,2 16,2 m 0,18 H 8 V 4 h 8 z",
    path: "m 12,10 c -1.1,0 -2,0.9 -2,2 0,1.1 0.9,2 2,2 1.1,0 2,-0.9 2,-2 0,-1.1 -0.9,-2 -2,-2",
  },
  mdi_fan: {
    secondaryPath:
      "M 11.947266,8.9981049 A 3.0014853,3.0014853 0 0 0 8.998047,12.000058 3.0014853,3.0014853 0 0 0 12,15.002011 3.0014853,3.0014853 0 0 0 15.001953,12.000058 3.0014853,3.0014853 0 0 0 12,8.9981049 a 3.0014853,3.0014853 0 0 0 -0.05273,0 z m 0.05273,2.0019531 a 1,1 0 0 1 1,1 1,1 0 0 1 -1,1 1,1 0 0 1 -1,-1 1,1 0 0 1 1,-1 z",
    path: "M 12.5,2 C 8.9407508,2 8.1502639,5.959102 10.138672,9.6484375 10.668374,9.2288235 11.324233,9.0003395 12,9 12.387672,8.9998095 12.771707,9.0747593 13.130859,9.2207031 13.320859,8.2907031 13.76,7.24 14.75,6.75 17.11,5.57 17,2 12.5,2 Z M 4.3222656,7.7324219 C 3.1266455,7.825564 2,8.96875 2,11.5 c 0,3.57 3.9603906,4.349141 7.6503906,2.369141 0.00458,0.0057 -0.00462,-0.0057 0,0 C 9.2194471,13.335499 9.0000106,12.68592 9,12 c -1.905e-4,-0.387672 0.074759,-0.771707 0.2207031,-1.130859 -0.93,-0.19 -1.9804687,-0.619375 -2.4804687,-1.6093754 C 6.2239844,8.2228906 5.2521924,7.659978 4.3222656,7.7324219 Z M 18.40625,9.0566406 c -1.241602,-0.034688 -2.669141,0.3242188 -4.056641,1.0742184 -0.0049,-0.0062 0.005,0.0061 0,0 C 14.781255,10.664239 14.999436,11.313843 15,12 c 2.97e-4,0.38269 -0.07263,0.761904 -0.214844,1.117188 v 0 c 0.930001,0.19 1.994141,0.623281 2.494141,1.613281 1.18,2.37 4.75,2.269531 4.75,-2.230469 0,-2.2375 -1.553711,-3.3855469 -3.623047,-3.4433594 z M 13.880859,14.339844 C 13.345667,14.775707 12.690222,15.00002 12,15 c -0.38269,2.97e-4 -0.754091,-0.06872 -1.109375,-0.210938 0.0027,0.0011 -0.0027,-0.0011 0,0 -0.2,0.920001 -0.641094,1.961172 -1.6210938,2.451172 C 6.9095312,18.420234 7,22 11.5,22 c 3.58,0 4.370859,-3.970156 2.380859,-7.660156 0.005,-0.0043 -0.005,0.0043 0,0 z",
  },
  "mdi_floor-lamp": {
    secondaryPath: "m 11,10 h 2 v 10 h 3 v 2 H 8 v -2 h 3 z",
    path: "m 15,2 2,7 H 7 L 9,2",
  },
  mdi_lamp: {
    secondaryPath: "m 11,15 h 2 v 5 h 5 v 2 H 6 v -2 h 5 z",
    path: "m 8,2 h 8 l 4,12 H 4 L 8,2",
  },
  "mdi_mirror-rectangle": {
    secondaryPath: "m8.29 10.28l3.24-3.25l1.06 1.06l-3.24 3.25l-1.06-1.06m.41 4.33l5.66-5.66L15.42 10l-5.66 5.67l-1.06-1.06M18 3v18H6V3h12m2-2H4v22h16V1Z",
    path: "M 6 3 L 6 21 L 18 21 L 18 3 L 6 3 z M 11.529297 7.0292969 L 12.589844 8.0898438 L 9.3496094 11.339844 L 8.2890625 10.279297 L 11.529297 7.0292969 z M 14.359375 8.9492188 L 15.419922 10 L 9.7597656 15.669922 L 8.6992188 14.609375 L 14.359375 8.9492188 z",
  },
  mdi_television: {
    secondaryPath: "M21,17H3V5H21M21,3H3A2,2 0 0,0 1,5V17A2,2 0 0,0 3,19H8V21H16V19H21A2,2 0 0,0 23,17V5A2,2 0 0,0 21,3Z",
    path: "M 3,5 V 17 H 21 V 5 Z",
  },
  "mdi_vanity-light": {
    secondaryPath:
      "M 14.82,6 C 14.26,4.44 12.53,3.64 11,4.2 10.14,4.5 9.5,5.17 9.18,6 H 2 v 2 h 2 v 4 H 6 V 8 H 9.18 C 9.5,8.85 10.15,9.5 11,9.82 V 12 h 2 V 9.82 C 13.85,9.5 14.5,8.85 14.82,8 H 18 v 4 h 2 V 8 h 2 V 6 Z",
    path: "m 22,20 h -6 c 0,-1.66 1.34,-7 3,-7 1.66,0 3,5.34 3,7 M 12,13 c -1.66,0 -3,5.34 -3,7 h 6 c 0,-1.66 -1.34,-7 -3,-7 M 5,13 C 3.34,13 2,18.34 2,20 H 8 C 8,18.34 6.66,13 5,13",
  },
  hue_adore: {
    secondaryPath:
      "M21.6,8.8H2.4C1.6,8.8,1,9.7,1,10.7v1.9c0,1.1,0.7,1.6,1.4,1.6h6.9c0,0,0,0,0,0.1v0.4c0,0.6,0.5,1.1,1.1,1.1 h3.3c0.6,0,1.1-0.5,1.1-1.1v-0.4c0,0,0,0,0-0.1h6.9c0.7,0,1.4-0.5,1.4-1.6v-1.9C23,9.7,22.4,8.8,21.6,8.8z M21.6,13.2H2.4 c-0.1,0-0.4,0-0.4-0.6c0-0.5,0.3-0.9,0.4-0.9h19.1c0.2,0,0.4,0.3,0.4,0.9C22,13.2,21.7,13.2,21.6,13.2z",
    path: "m 2.4003906,11.699219 c -0.1,0 -0.4003906,0.40039 -0.4003906,0.90039 0,0.6 0.3003906,0.59961 0.4003906,0.59961 H 21.599609 c 0.1,0 0.400782,3.9e-4 0.300782,-0.59961 0,-0.6 -0.200391,-0.90039 -0.400391,-0.90039 z",
  },
  "hue_bulb-group-classic-4-alt": {
    secondaryPath:
      "m 15,15.59 c -0.1,0.61 -0.19,1.47 -0.13,2.1 0.04,0.4 -0.26,0.75 -0.66,0.79 -0.65,0.07 -1.38,0.11 -2.21,0.11 -0.83,0 -1.56,-0.04 -2.21,-0.11 C 9.39,18.44 9.08,18.09 9.12,17.69 9.18,17.06 9.1,16.2 8.99,15.59 8.75,14.18 7.75,13.51 7.18,12 c 1.41,0.45 3.48,0.59 4.82,0.59 1.34,0 3.41,-0.14 4.82,-0.59 -0.58,1.51 -1.58,2.18 -1.82,3.59 z m -1.12,5.97 c -0.02,0.16 -0.11,0.32 -0.23,0.43 l -0.35,0.32 c -0.03,0.02 -0.05,0.05 -0.07,0.07 l -0.37,0.44 c -0.14,0.17 -0.36,0.27 -0.59,0.27 h -0.55 c -0.23,0 -0.45,-0.1 -0.57,-0.26 L 10.78,22.39 C 10.76,22.36 10.73,22.34 10.71,22.32 L 10.36,22 C 10.23,21.89 10.15,21.73 10.13,21.57 L 9.75,19.24 c 0.78,0.07 1.64,0.1 2.25,0.1 0.61,0 1.47,-0.03 2.25,-0.1 z M 5.9,8.78 C 4.9,8.75 3.66,8.63 2.75,8.34 c 0.44,1.17 1.21,1.69 1.4,2.78 0.08,0.48 0.15,1.14 0.1,1.63 -0.03,0.31 0.21,0.58 0.52,0.61 0.5,0.06 1.07,0.09 1.71,0.09 0.1,0 0.19,-0.01 0.28,-0.01 C 6.58,13.12 6.4,12.77 6.24,12.36 6.17,12.19 6.02,11.75 5.93,11.34 V 11.33 L 5.91,11.26 C 5.9,11.25 5.9,11.23 5.9,11.22 5.89,11.18 5.89,11.14 5.88,11.1 5.86,10.98 5.83,10.85 5.81,10.69 5.8,10.63 5.8,10.57 5.79,10.52 5.77,10.36 5.75,10.18 5.75,9.97 5.75,9.57 5.8,9.17 5.9,8.78 Z m 0.59,5.25 C 6.02,14.03 5.35,14 4.75,13.95 l 0.29,1.81 c 0.02,0.12 0.08,0.24 0.18,0.33 l 0.27,0.24 c 0.02,0.02 0.04,0.03 0.05,0.06 l 0.29,0.34 c 0.09,0.12 0.26,0.2 0.44,0.2 H 6.7 c 0.18,0 0.35,-0.08 0.46,-0.21 L 7.44,16.38 C 7.46,16.36 7.47,16.34 7.5,16.33 L 7.77,16.08 C 7.86,15.99 7.93,15.87 7.95,15.74 L 7.96,15.62 C 7.84,15.11 7.58,14.7 7.25,14.2 7.21,14.14 7.17,14.07 7.13,14.01 6.9,14.02 6.68,14.02 6.49,14.03 Z m 10.75,-0.6 c 0.09,0 0.18,0.01 0.28,0.01 0.64,0 1.21,-0.04 1.71,-0.09 0.31,-0.03 0.54,-0.3 0.51,-0.61 -0.05,-0.49 0.02,-1.16 0.1,-1.63 0.19,-1.09 0.96,-1.61 1.41,-2.78 -0.92,0.29 -2.16,0.41 -3.16,0.44 0.1,0.39 0.16,0.79 0.16,1.18 0,0.22 -0.03,0.4 -0.05,0.55 -0.01,0.05 -0.01,0.11 -0.02,0.16 0,0.02 -0.01,0.04 -0.01,0.06 -0.01,0.1 -0.03,0.18 -0.05,0.27 V 11 c 0,0.04 -0.02,0.16 -0.06,0.31 v 0.01 0 c -0.1,0.38 -0.27,0.94 -0.31,1.04 -0.15,0.41 -0.34,0.76 -0.51,1.07 z m -1.21,2.16 0.03,0.17 c 0.02,0.12 0.08,0.24 0.18,0.33 l 0.27,0.25 0.05,0.05 0.29,0.34 c 0.09,0.12 0.26,0.2 0.44,0.2 h 0.43 c 0.18,0 0.35,-0.08 0.46,-0.21 l 0.29,-0.34 0.05,-0.05 0.25,-0.25 c 0.09,-0.08 0.16,-0.21 0.18,-0.33 l 0.29,-1.8 c -0.6,0.06 -1.27,0.08 -1.74,0.08 -0.18,0 -0.41,0 -0.64,-0.01 l -0.12,0.18 c -0.32,0.49 -0.58,0.89 -0.71,1.39 z",
    path: "m 17.25,9.96 c 0,0.22 -0.04,0.41 -0.06,0.61 -0.03,0.19 -0.06,0.35 -0.1,0.53 -0.82,0.35 -2.55,0.75 -5.09,0.75 -2.54,0 -4.27,-0.39 -5.09,-0.74 C 6.87,10.93 6.83,10.77 6.81,10.58 6.79,10.38 6.75,10.18 6.75,9.97 6.75,7.59 9.11,5.09 12,5.09 c 2.89,0 5.25,2.5 5.25,4.87 z M 15.26,2.99 C 14.52,2.04 13.34,1.34 12,1.34 c -1.34,0 -2.52,0.7 -3.26,1.65 0.61,0.35 1.13,0.82 1.53,1.36 0.56,-0.17 1.14,-0.26 1.73,-0.26 0.61,0 1.18,0.1 1.73,0.26 0.4,-0.53 0.92,-1.01 1.53,-1.36 z M 9.69,4.56 C 8.95,3.65 7.79,2.98 6.49,2.98 4.25,2.98 2.42,4.92 2.42,6.76 2.42,6.92 2.45,7.08 2.47,7.23 2.49,7.38 2.52,7.5 2.55,7.64 3.14,7.9 4.34,8.17 6.08,8.21 6.67,6.61 8.03,5.24 9.69,4.56 Z m 11.9,2.19 c 0,-1.83 -1.83,-3.77 -4.07,-3.77 -1.31,0 -2.45,0.66 -3.2,1.57 1.71,0.7 3.01,2.12 3.59,3.66 1.74,-0.04 2.95,-0.32 3.54,-0.57 0.03,-0.14 0.06,-0.26 0.08,-0.41 0.02,-0.16 0.05,-0.3 0.06,-0.48 z",
  },
  "hue_ceiling-aurelle-circle": {
    secondaryPath:
      "m 12,6.4 c -6.4,0 -11.5,2.2 -11.5,5 v 1 c 0,2.8 5,5 11.5,5 6.5,0 11.5,-2.2 11.5,-5 v -1 c 0,-2.8 -5,-5 -11.5,-5 z m 0,9.9 c -6.3,0 -10.5,-2 -10.5,-4 0,-2 4.2,-4 10.5,-4 6.3,0 10.5,2 10.5,4 0,2 -4.2,4 -10.5,4 z",
    path: "m 3.9,12.5 c 0,1.8 4.1,2.7 8.1,2.7 4,0 8.1,-0.9 8.1,-2.7 C 20.2,9 3.9,9 3.9,12.5 Z",
  },
  "hue_ceiling-still": {
    secondaryPath:
      "m 22.45312,9.7068 c -1.73339,-1.89062 -5.209,-2.84912 -10.32958,-2.84912 -5.12159,0 -8.59717,0.9585 -10.33008,2.84912 -0.6564974,0.65171 -1.03352062,1.533381 -1.05121,2.45826 l -6e-5,2.4e-4 6e-5,3e-4 0.00189,0.04316 c 0.005512,0.03076 0.014016,0.0609 0.02539,0.09 0.29028,2.19428 7.497,2.78351 11.354,2.78351 3.85723,0 11.06286,-0.58929 11.35394,-2.78314 0.01143,-0.02922 0.01996,-0.0595 0.02545,-0.09039 -0.0015,-0.940775 -0.379518,-1.841802 -1.0498,-2.50194 z m -10.32958,4.37549 c -6.84913,0 -10.38135,-1.34375 -10.38135,-1.917 0,-0.57325 3.53222,-1.917 10.38135,-1.917 6.84913,0 10.38134,1.34375 10.38134,1.917 0,0.57325 -3.53222,1.917 -10.38134,1.917 z",
    path: "m 12.12341,10.77791 c 0,0 -5.51306,0.03845 -5.49383,1.1145 0.01922,1.076 4.51227,1.46033 5.49383,1.46033 0.98156,0 5.38172,-0.38434 5.38172,-1.49878 0,-1.11444 -5.38172,-1.07605 -5.38172,-1.07605 z",
  },
  "hue_lightstrip-tv": {
    secondaryPath:
      "M 21.8,3.4 H 3 C 2.4,3.4 1.8,4 1.8,4.7 v 10.2 c 0,0.7 0.5,1.2 1.2,1.2 h 0.4 v 0 h 8.2 v 2.8 h -1.4 c -0.4,0 -0.8,0.3 -0.8,0.8 0,0.5 0.3,0.8 0.8,0.8 h 4.4 c 0.4,0 0.8,-0.3 0.8,-0.8 0,-0.5 -0.3,-0.8 -0.8,-0.8 h -1.5 v -2.8 h 6.2 1.2 1 c 0.7,0 1.2,-0.6 1.2,-1.2 V 4.7 c 0,-0.3 0,-1.3 -0.9,-1.3 z m 0.0016,11.5 c 0,0.1 -0.1,0.2 -0.2,0.2 H 19 c -0.2,0 -0.3,0 -0.4,-0.1 -0.1,-0.1 -0.1,-0.2 -0.1,-0.2 V 9 C 18.5,8.4 18.3,8.1 18.1,7.9 17.7,7.5 17.2,7.5 17.1,7.5 v 0 H 7.2 C 6.3,7.5 5.9,8.3 5.9,8.8 v 6 c 0,0.2 -0.2,0.3 -0.2,0.3 H 3.1 C 3,15.1 2.9,15 2.9,14.9 V 4.7 C 2.9,4.6 3,4.5 3.1,4.5 h 18.54375 c 0,0 0.08001,-0.0061 0.125,0.041406 C 21.81084,4.5858503 21.8,4.7 21.8,4.7 c 0.002,3.3993138 -0.0034,6.803448 0.0016,10.2 z",
    path: "m 20.992187,13.304688 a 0.796875,0.80859375 0 0 1 -0.796875,0.808594 0.796875,0.80859375 0 0 1 -0.796875,-0.808594 0.796875,0.80859375 0 0 1 0.796875,-0.808593 0.796875,0.80859375 0 0 1 0.796875,0.808593 z m 0,-3.710938 A 0.796875,0.80859375 0 0 1 20.195312,10.402344 0.796875,0.80859375 0 0 1 19.398437,9.59375 0.796875,0.80859375 0 0 1 20.195312,8.7851563 0.796875,0.80859375 0 0 1 20.992187,9.59375 Z m 0,-3.7890625 a 0.796875,0.80859375 0 0 1 -0.796875,0.8085937 0.796875,0.80859375 0 0 1 -0.796875,-0.8085937 0.796875,0.80859375 0 0 1 0.796875,-0.8085938 0.796875,0.80859375 0 0 1 0.796875,0.8085938 z m -4.003906,-0.00391 A 0.796875,0.80859375 0 0 1 16.191406,6.609375 0.796875,0.80859375 0 0 1 15.394531,5.8007812 0.796875,0.80859375 0 0 1 16.191406,4.9921875 0.796875,0.80859375 0 0 1 16.988281,5.8007812 Z m -3.898437,0.00781 A 0.796875,0.80859375 0 0 1 12.292969,6.6171875 0.796875,0.80859375 0 0 1 11.496094,5.8085937 0.796875,0.80859375 0 0 1 12.292969,5 0.796875,0.80859375 0 0 1 13.089844,5.8085937 Z m -3.996094,0 A 0.796875,0.80859375 0 0 1 8.296875,6.6171875 0.796875,0.80859375 0 0 1 7.5,5.8085937 0.796875,0.80859375 0 0 1 8.296875,5 0.796875,0.80859375 0 0 1 9.09375,5.8085937 Z M 5.1914062,5.7929687 A 0.796875,0.80859375 0 0 1 4.3945312,6.6015625 0.796875,0.80859375 0 0 1 3.5976563,5.7929687 0.796875,0.80859375 0 0 1 4.3945312,4.984375 0.796875,0.80859375 0 0 1 5.1914062,5.7929687 Z m 0.00391,3.8085948 A 0.796875,0.80859375 0 0 1 4.3984375,10.410157 0.796875,0.80859375 0 0 1 3.6015625,9.6015635 0.796875,0.80859375 0 0 1 4.3984375,8.7929697 0.796875,0.80859375 0 0 1 5.1953125,9.6015635 Z M 5.0898437,13.410155 a 0.796875,0.80859375 0 0 1 -0.796875,0.808594 0.796875,0.80859375 0 0 1 -0.7968749,-0.808594 0.796875,0.80859375 0 0 1 0.7968749,-0.808593 0.796875,0.80859375 0 0 1 0.796875,0.808593 z",
  },
};

async function getIcon(name) {
  if (!(name in DUAL_COLOR_ICONS_MAP)) {
    // try swapping the '_' for a '-'
    let new_name = name.replace(/_/gm, `-`);
    if (!(new_name in DUAL_COLOR_ICONS_MAP)) {
      console.log(`Icon "${name}" is not available`);
      return { path: "" };
    } else {
      console.log(`Aliased "${name}" with "${new_name}"`);
      return DUAL_COLOR_ICONS_MAP[new_name];
    }
  }
  return DUAL_COLOR_ICONS_MAP[name];
}

async function getIconList() {
  return Object.entries(DUAL_COLOR_ICONS_MAP).map(([icon, content]) => ({
    name: icon,
    keywords: content.keywords,
  }));
}
window.customIcons = window.customIcons || {};
window.customIcons["dci"] = { getIcon, getIconList };

window.customIconsets = window.customIconsets || {};
window.customIconsets["dci"] = getIcon;

console.info(
  `%c DUAL-COLOR-ICONS %c Version 0.0.1`,
  "color: orange; font-weight: bold; background: black",
  "color: white; font-weight: bold; background: dimgray"
);
The dashboard
title: Home
views:
  - path: default_view
    title: Home
    badges: []
    cards:
      - square: false
        type: grid
        cards:
          - type: tile
            entity: light.virtual_light_1
            icon: dci:mdi_ceiling-light
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_1
            icon: dci:mdi_coach-lamp
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_1
            icon: dci:mdi_doorbell
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: dci:mdi_ceiling-light
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: dci:mdi_coach-lamp
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: dci:mdi_doorbell
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
        columns: 3
      - square: false
        type: grid
        cards:
          - type: tile
            entity: fan.virtual_fan_1
            icon: dci:mdi_fan
            color: white
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-opactity: 1;
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                  svg{
                   animation: 2s linear 0s infinite normal none running rotating;
                  }
                  @keyframes rotating {
                    0% { 
                      transform: rotate(0); 
                    }
                    100% { 
                      transform: rotate(360deg);
                    }
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_3
            icon: dci:mdi_floor-lamp
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_3
            icon: dci:mdi_lamp
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: fan.virtual_fan_2
            icon: dci:mdi_fan
            color: white
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-opactity: 1;
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                  svg{
                   animation: 2s linear 0s infinite normal none running rotating;
                  }
                  @keyframes rotating {
                    0% { 
                      transform: rotate(0); 
                    }
                    100% { 
                      transform: rotate(360deg);
                    }
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: dci:mdi_floor-lamp
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: dci:mdi_lamp
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
        columns: 3
      - square: false
        type: grid
        cards:
          - type: tile
            entity: light.virtual_light_4
            icon: dci:mdi_mirror-rectangle
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_4
            icon: dci:mdi_television
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_4
            icon: dci:mdi_vanity-light
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: dci:mdi_mirror-rectangle
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: dci:mdi_television
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: dci:mdi_vanity-light
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
        columns: 3
      - square: false
        type: grid
        cards:
          - type: tile
            entity: light.virtual_light_5
            icon: dci:hue_adore
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_5
            icon: dci:hue_bulb-group-classic-4-alt
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_5
            icon: dci:hue_ceiling-aurelle-circle
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: dci:hue_adore
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: dci:hue_bulb-group-classic-4-alt
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: light.virtual_light_2
            icon: dci:hue_ceiling-aurelle-circle
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
        columns: 3
      - square: false
        type: grid
        cards:
          - type: tile
            entity: switch.virtual_switch_1
            icon: dci:hue_ceiling-still
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: switch.virtual_switch_1
            icon: dci:hue_lightstrip-tv
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: switch.virtual_switch_1
            icon: dci:hue_ceiling-still
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: switch.virtual_switch_2
            icon: dci:hue_ceiling-still
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: switch.virtual_switch_2
            icon: dci:hue_lightstrip-tv
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
          - type: tile
            entity: switch.virtual_switch_2
            icon: dci:hue_ceiling-still
            card_mod:
              style:
                ha-tile-icon[data-state="on"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-secondary-color: rgb(158, 158, 158);
                  }
                ha-tile-icon[data-state="off"]$ ha-icon$ ha-svg-icon$: |
                  svg path {
                    --icon-primary-color: rgb(158, 158, 158);
                    --icon-primary-opactity: 0.4;
                    --icon-secondary-color: currentcolor;
                    --icon-secondary-opactity: 1;
                  }
        columns: 3
      - show_name: false
        show_icon: true
        show_state: false
        type: glance
        entities:
          - entity: sensor.sun_next_dawn
            icon: dci:mdi_ceiling-light
          - entity: sensor.sun_next_dusk
            icon: dci:mdi_coach-lamp
          - entity: sensor.sun_next_midnight
            icon: dci:mdi_doorbell
          - entity: sensor.sun_next_noon
            icon: dci:mdi_fan
          - entity: sensor.sun_next_rising
            icon: dci:mdi_floor-lamp
          - entity: sensor.sun_next_setting
            icon: dci:mdi_floor-lamp
          - entity: input_button.test_1
            icon: dci:mdi_mirror-rectangle
          - entity: input_button.test_2
            icon: dci:mdi_television
          - entity: input_button.test_3
            icon: dci:mdi_vanity-light
          - entity: input_button.test_4
            icon: dci:hue_adore
          - entity: input_button.test_5
            icon: dci:hue_bulb-group-classic-4-alt
          - entity: input_button.test_6
            icon: dci:hue_ceiling-aurelle-circle
          - entity: input_button.test_7
            icon: dci:hue_ceiling-still
          - entity: input_button.test_8
            icon: dci:hue_lightstrip-tv
        columns: 7

@bramkragten bramkragten merged commit 49f88a9 into home-assistant:dev Oct 19, 2023
12 checks passed
@frenck frenck added the Noteworthy Marks a PR as noteworthy and should be in the release notes (in case it normally would not appear) label Oct 19, 2023
@sisimomo sisimomo deleted the multi-path-icon branch November 3, 2023 01:44
@github-actions github-actions bot locked and limited conversation to collaborators Dec 9, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cla-signed hacktoberfest Noteworthy Marks a PR as noteworthy and should be in the release notes (in case it normally would not appear)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants