This is probably more than you wanted but it demonstrates changing icon colour
[{"id":"b3fae0cdaf1aa48b","type":"inject","z":"506727cd93754bdb","g":"f80590b4d4630047","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"ui-property: sliderRange","payload":"{\"min\": 1, \"max\": 50}","payloadType":"json","x":710,"y":860,"wires":[["c7b6dd708fbf3d12"]]},{"id":"c7b6dd708fbf3d12","type":"ui-template","z":"506727cd93754bdb","g":"f80590b4d4630047","group":"0a0ba0877032ca64","page":"","ui":"","name":"Icon Button","order":0,"width":0,"height":0,"head":"","format":"<template>\n <v-card class = \"card\">\n <v-btn class = \"btnBasic\" :class = \"btnClass\" stacked @click=\"changeState()\">\n {{btnText}}\n <v-icon class = \"iconBasic\" :class = \"iconClass\" >mdi-lightbulb-variant-outline</v-icon> \n \n </v-btn>\n \n <v-slider\n v-model=\"sliderValue\"\n width=\"50\" \n :min=\"sliderRange.min\" \n :max=\"sliderRange.max\" \n thumb-size=\"12\"\n :color = \"sliderColour\"\n @end=\"updateSlider()\">\n </v-slider>\n\n </v-card>\n\n</template>\n\n<script>\n export default {\n data() {\n return {\n btnState: 0,\n\n\t\t\t\tbtnData: {class: ['btnOff', 'btnOn'], text: ['Light']},\n iconData: {class: ['iconOff', 'iconOn']},\n\n outputValue: ['Off', 'On'],\n\n sliderColour: 'orange',\n sliderValue: 0,\n sliderRange: {min: 1, max: 100},\n\t\n }\n\t\n },\n \n methods: {\n changeState: function () {\n\t\t\t\tthis.toggleState(this.btnState)\n\n\t\t\t\tthis.send(this.outputValue[this.btnState])\n //this.send({topic: \"Button Out\", payload: this.outputValue[this.btnState]})\n\n },\n\t\n toggleState: function () { \n this.btnState = (++this.btnState) % this.outputValue.length\n\n // Slider starts at 1 if Button 'On', reset to 0 if Button is 'Off'\n\t\t\t\tthis.sliderValue = this.btnState\n \n },\n\n updateSlider: function () {\n if (this.btnState === 1) {\n this.send( parseInt(this.sliderValue) )\n\n } else {\n this.sliderValue = 0\n\n } \n },\n\t\t\t\n },\n\n watch: {\n\n },\n\n computed: {\n // automatically compute this variable\n // whenever VueJS deems appropriate\n btnText: function() {\n let buttonText = this.btnData.text[0]\n if (this.btnData.text.length > this.btnState) {\n buttonText = this.btnData.text[this.btnState]\n }\n\n return buttonText\n \n },\n\n btnClass: function() {\n return (this.btnState === 0) ? this.btnData.class[0] : this.btnData.class[1]\n\n },\n\t\t\t\n iconClass: function() {\n return (this.btnState === 0) ? this.iconData.class[0] : this.iconData.class[1]\n\n },\n\n },\n\n mounted () { \n this.$socket.on(\"msg-input:\" + this.id, (msg) => {\n /**\n * Comply with Dashboard 2 schema to set dynamic values\n * \n * topic: ui-property: <property>,\n * payload: \"<value>\"\n * \n */\n const payloadValue = msg.payload\n\n if (!msg.topic.includes('ui-property')) {\n // msg.payload can be 0 or 1, or values of button text\n if ((typeof payloadValue === 'string') || (payloadValue instanceof String)) {\n const index = outputValue.findIndex((element) => element.toLowerCase() === payloadValue.toLowerCase())\n // Nothing happens if payloadValue not found\n if (index >= 0) this.btnState = index\n\n } else if (typeof payloadValue === 'number' && isFinite(payloadValue)) {\n const maxValue = this.outputValue.length - 1\n const minValue = 0\n\n // Set btnState to payloadValue, or min or max if payloadValue < min or > max\n this.btnState = Math.min(maxValue, Math.max(payloadValue, minValue))\n\n }\n\n } else {\n\n this.send(payloadValue)\n /** Update Widget values if required\n * \n * Input ui-property payload <value>\n * buttonText Array of string, length 1 or more. Only number of outputValues\n * will be shown\n * output Array of output values (any), length 1 or more. Each 'click' of\n * button will output next value in Array. Button text will also\n * update for each 'click' if there is more than 1 string in btnData.text\n * Array\n * sliderRange Object, {min: <minValue>, max: <maxValue>}\n * sliderColour Slider color, (both track & thumb) \n * \n * msgPassThrough If true incoming msg is passed through, otherwise not\n * \n */\n \n const property = msg.topic.split(':')[1].trim()\n\n if (property === 'buttonText') this.btnData.text = payloadValue\n if (property === 'output') this.outputValue = payloadValue\n\n if (property === 'sliderRange') this.sliderRange = payloadValue\n if (property === 'sliderColour') this.sliderColour = payloadValue\n\n /**\n this.btnData.text = msg?.buttonText ?? this.btnData.text\n this.outputValue = msg?.output ?? this.outputValue\n this.sliderRange = msg?.sliderRange ?? this.sliderRange\n this.sliderColour = msg?.sliderColour ?? this.sliderColour\n\n */\n\n }\n\n })\n\n },\n\n unmounted() {\n // code here when the component is removed from the Dashboard\n // i.e. when the user navigates away from the page\n this.$socket.off(`msg-input:${this.id}`)\n },\n\n }\n\n</script>\n\n<style scoped>\n .card {\n background-color: #4F4F4F; /* Very dark gray */\n border: 1px solid black; \n border-radius: 8px; \n width: 75px !important;\n height: 105px;\n\n }\n\n .btnBasic {\n background-color: #4F4F4F; /* Very dark gray */\n border-radius: 8px;\n /*width: 75px !important;*/\n height: 75px !important;\n\n }\n\n\t.btnOn {\n color: rgb(189, 150, 8); /* Dark washed rose */\n\n\t}\n\t\n\t.btnOff {\n\t\tcolor: darkgrey;\n\n\t}\n\n\t.iconBasic {\n\t\tfont-size: 45px;\n height: 45px;\n width: 45px;\n\n\t}\n\n\t.iconOn {\n color: rgb(189, 150, 8); /* Dark washed rose */\n text-shadow: rgb(189, 150, 8) 0px 0px 10px; /* Dark washed rose */\n\n\t}\n\t\n\t.iconOff {\n\t\tcolor: darkgrey;\n\t\ttext-shadow: 0px 0px 0px;\n\n\t}\n\n .v-slider-thumb__surface{\n background-color: currentColor;\n\n }\n\n</style>","storeOutMessages":true,"passthru":false,"resendOnRefresh":true,"templateScope":"local","className":"","x":1050,"y":860,"wires":[["8f30da685c1e89e4"]],"info":" :color = \"sliderColour\"\r\n\r\n thumb-color = \"red\"\r\n track-color=\"green\" "},{"id":"8f30da685c1e89e4","type":"debug","z":"506727cd93754bdb","g":"f80590b4d4630047","name":"Icon Button","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1430,"y":860,"wires":[]},{"id":"0a0ba0877032ca64","type":"ui-group","name":"Icon Button","page":"79a8176801c89202","width":"6","height":"1","order":-1,"showTitle":true,"className":""},{"id":"79a8176801c89202","type":"ui-page","name":"Page 05","ui":"b810194ea14e3502","path":"/page05","layout":"grid","theme":"62307b5371f6467e","order":-1,"className":""},{"id":"b810194ea14e3502","type":"ui-base","name":"Various Dashboard 2 Examples","path":"/dashboard"},{"id":"62307b5371f6467e","type":"ui-theme","name":"Theme Name","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"}}]