Custom Toggle Switch

Is this possible to make in Node-red?

Thank you!

Yes the UI-template node can do what you want to do.
There are numerous examples on the forum

@E1cid, I tried that, but only a checkbox is displayed.

Did you add the css styling too?

Are you referring to this?

<style>
    /*--- Toggle Switch CSS --- */

    /* Settings */
    :root{
        /* Standard Toggle */
        --tog-scale: 1;
        --tog-height: 42px;
        --tog-width: 84px;
        --tog-knob-diameter: 36px;
        --tog-background-inactive: rgb(182, 182, 182);
        --tog-background-active: rgb(127, 180, 210);
        --tog-knob-color-inactive: rgb(130, 130, 130);
        --tog-knob-color-active: rgb(0, 107, 165);
        --tog-text-color-inactive: black;
        --tog-text-color-active: black;
        --tog-text-size: 1rem;
        --tog-transition-speed: 0.15s;
        
        /* Power Toggle */
        --pwr-tog-scale: 1;
        --pwr-tog-height: 42px;
        --pwr-tog-width: 84px;
        --pwr-tog-knob-diameter: 36px;
        --pwr-tog-background-inactive: rgb(182, 182, 182);
        --pwr-tog-background-active: rgb(248, 154, 154);
        --pwr-tog-knob-color-inactive: rgb(130, 130, 130);
        --pwr-tog-knob-color-active: rgb(130, 130, 130); /*rgb(237, 24, 24);*/
        --pwr-tog-knob-icon-color-active: orange;
        --pwr-tog-knob-icon-color-inactive: lightgray;
        --pwr-tog-text-color-inactive: black;
        --pwr-tog-text-color-active: black;
        --pwr-tog-text-size: 1rem;
        --pwr-tog-transition-speed: 0.15s;
    }

    /* CSS Selector for toggle-widget settings */
    .toggle-widget {
        display: block;
        padding: 0;
    }

    /* Standard Toggle switch body */
    .toggle{
        display: block;
        appearance: none;
        -webkit-appearance: none;
        -moz-appearance: none;
        width: var(--tog-width);
        height: var(--tog-height);
        background: var(--tog-background-inactive);
        border-radius: calc(var(--tog-height) / 2);
        position: relative;
        transform: scale(var(--tog-scale));
        transition-property: background;
        transition-duration: var(--tog-transition-speed);
        align-self: center;
        vertical-align: center !important;
        margin: 0px !important;
    }
    
    /* Standard Toggle switch knob */
    .toggle:before{
        content: "";
        background: var(--tog-knob-color-inactive);
        height: var(--tog-knob-diameter);
        width: var(--tog-knob-diameter);
        position: absolute;
        border-radius: 50%;
        top: calc((var(--tog-height) - var(--tog-knob-diameter)) / 2);
        left: calc((var(--tog-height) - var(--tog-knob-diameter)) / 2);
        transition: all var(--tog-transition-speed);
        z-index: 2;
    }
    
    /* Standard Toggle switch inactive text */
    .toggle:after{
        content: "OFF";
        position: absolute;
        font-size: var(--tog-text-size);
        color: var(--tog-text-color-inactive);
        font-weight: bold;
        top: 50%;
        left: 50%;
        transform: translate(8%, -43%);
        z-index: 1;
    }
    
    /* Standard Toggle switch checked state */
    .toggle:checked{
        background: var(--tog-background-active);
    }
    
    /* Standard Toggle Switch Knob offset */
    .toggle:checked::before{
        background: var(--tog-knob-color-active);
        left: calc((var(--tog-height) - var(--tog-knob-diameter)) / 2 + var(--tog-width) - var(--tog-height));
    }
    
    /* Standard Toggle Switch Active Text */
    .toggle:checked::after{
        content: "ON";
        left: 5%;
        color: var(--tog-text-color-active);
    }

    /* --- Power Toggle CSS --- */

    /* Power Toggle switch body */
    .toggle-pwr{
        display: block;
        appearance: none;
        -webkit-appearance: none;
        -moz-appearance: none;
        width: var(--pwr-tog-width);
        height: var(--pwr-tog-height);
        background: var(--pwr-tog-background-inactive);
        border-radius: calc(var(--pwr-tog-height) / 2);
        position: relative;
        transform: scale(var(--pwr-tog-scale));
        transition-property: background;
        transition-duration: var(--pwr-tog-transition-speed);
        align-self: center;
        vertical-align: center !important;
        margin: 0px !important;
    }
    
    /* Power Toggle switch knob */
    .toggle-pwr:before{
        display: flex;
        align-items: center;
        justify-content: center;
        font-family: "Material Icons";
        content: "\e8ac";
        font-size: 2rem;
        color: var(--pwr-tog-knob-icon-color-inactive);
        /* transition: color .35s ease; */
        background: var(--pwr-tog-knob-color-inactive);
        height: var(--pwr-tog-knob-diameter);
        width: var(--pwr-tog-knob-diameter);
        position: absolute;
        border-radius: 50%;
        top: calc((var(--pwr-tog-height) - var(--pwr-tog-knob-diameter)) / 2);
        left: calc((var(--pwr-tog-height) - var(--pwr-tog-knob-diameter)) / 2);
        transition: all var(--pwr-tog-transition-speed);
        z-index: 2;
    }
    
    /* Power Toggle switch inactive text */
    .toggle-pwr:after{
        content: "OFF";
        position: absolute;
        font-size: var(--pwr-tog-text-size);
        color: var(--pwr-tog-text-color-inactive);
        font-weight: bold;
        top: 50%;
        left: 50%;
        transform: translate(8%, -43%);
        z-index: 1;
    }
    
    /* Power Toggle cwitch checked state */
    .toggle-pwr:checked{
        background: var(--pwr-tog-background-active);
    }
    
    /* Power Toggle Switch Knob offset */
    .toggle-pwr:checked::before{
        color: var(--pwr-tog-knob-icon-color-active);
        /*text-shadow: 0 0 3px var(--pwr-tog-knob-icon-color-active);*/
        /*text-shadow: 0 0 2px #fff, 0 0 4px #fff, 0 0 6px #e60073, 0 0 8px #e60073, 0 0 10px #e60073, 0 0 12px #e60073, 0 0 14px #e60073;*/
        text-shadow: 0 0 2px var(--pwr-tog-knob-icon-color-active), 0 0 4px var(--pwr-tog-knob-icon-color-active), 0 0 6px #e60073, 0 0 8px #e60073, 0 0 10px #e60073, 0 0 12px #e60073, 0 0 14px #e60073;
        background: var(--pwr-tog-knob-color-active);
        left: calc((var(--pwr-tog-height) - var(--pwr-tog-knob-diameter)) / 2 + var(--pwr-tog-width) - var(--pwr-tog-height));
    }
    
    /* Power Toggle Switch Active Text */
    .toggle-pwr:checked::after{
        content: "ON";
        left: 5%;
        color: var(--pwr-tog-text-color-active);
    }
</style>

Yes that should be in the template with the html and any Javascript.

It works now, but it makes my dashboard page smaller. How do I fix that?

Template node:

<label class="switch">
    <input type="checkbox">
    <span></span>
</label>

<!-- dribbble -->
<a class="dribbble" href="https://dribbble.com/shots/5449131-Switch-animation"
    target="_blank"><img src="https://cdn.dribbble.com/assets/dribbble-ball-mark-2bd45f09c2fb58dbbfb44766d5d1d07c5a12972d602ef8b32204d28fa3dda554.svg" alt=""></a>


    <style>

        .switch {
        cursor: pointer;
        }
        .switch input {
        display: none;
        }
        .switch input + span {
        width: 48px;
        height: 28px;
        border-radius: 14px;
        transition: all 0.3s ease;
        display: block;
        position: relative;
        background: #FF4651;
        box-shadow: 0 8px 16px -1px rgba(255, 70, 81, 0.2);
        }
        .switch input + span:before, .switch input + span:after {
        content: "";
        display: block;
        position: absolute;
        transition: all 0.3s ease;
        }
        .switch input + span:before {
        top: 5px;
        left: 5px;
        width: 18px;
        height: 18px;
        border-radius: 9px;
        border: 5px solid #fff;
        }
        .switch input + span:after {
        top: 5px;
        left: 32px;
        width: 6px;
        height: 18px;
        border-radius: 40%;
        transform-origin: 50% 50%;
        background: #fff;
        opacity: 0;
        }
        .switch input + span:active {
        transform: scale(0.92);
        }
        .switch input:checked + span {
        background: #48EA8B;
        box-shadow: 0 8px 16px -1px rgba(72, 234, 139, 0.2);
        }
        .switch input:checked + span:before {
        width: 0px;
        border-radius: 3px;
        margin-left: 27px;
        border-width: 3px;
        background: #fff;
        }
        .switch input:checked + span:after {
        -webkit-animation: blobChecked 0.35s linear forwards 0.2s;
        animation: blobChecked 0.35s linear forwards 0.2s;
        }
        .switch input:not(:checked) + span:before {
        -webkit-animation: blob 0.85s linear forwards 0.2s;
        animation: blob 0.85s linear forwards 0.2s;
        }
        
        html {
        -webkit-font-smoothing: antialiased;
        }
        
        * {
        box-sizing: border-box;
        }
        *:before, *:after {
        box-sizing: border-box;
        }
        
        body {
        min-height: 100vh;
        font-family: Roboto, Arial;
        color: #ADAFB6;
        display: flex;
        justify-content: center;
        align-items: center;
        background: #F5F9FF;
        }
        body .dribbble {
        position: fixed;
        display: block;
        right: 20px;
        bottom: 20px;
        }
        body .dribbble img {
        display: block;
        height: 28px;
        }
    </style>

I would say the css of the check box is messing with the css of dashboard. Css is not my thing i can fumble through it but would be guessing. Hopefully some other forum user maybe able to help here.

@E1cid, thank you for the help!

I was able to fix the dashboard size issue.

I am having a new issue. I am using ng-model to send output, but the switch is controlled through injected payload and manually clicking it. The switch does not register the new state when clicked after a state was injected. Any ideas?

Found the solution: setting the ng-checked="checkboxModel = msg.payload". This allowed me to use the toggle smoothly between injected payloads and manual switch control.