Hi Rainer, thank you for efforts once again!
This is a very good solution indeed, I don’t necessarily need the flip effect.
Hi Rainer, thank you for efforts once again!
This is a very good solution indeed, I don’t necessarily need the flip effect.
Could you point towards a resource where these are documented? I could not find anything in the f7 documentation so far?!
I don’t think these are documented tbh (or at least I don’t know where) - I used the dirty way here and beautified the app.css from my setup: http://YOUR-OH-IP:8080/css/app.css
… with this CSS beautifier and checked the available ‘keyframes’
https://www.freeformatter.com/css-beautifier.html
Oh I see it is a bit hacky but as long as they don’t rename the effect I should be fine
Thank you!
This btw does not work for me. I have to put the whole property in " for this to work
This looks and works awesome, thanks for sharing! I did notice that at least on mine with a range of 2700-6500k for temperature, it seems that going higher than 3900 the slider goes off the widget and at the 6500k mark it’s way off. Any ideas how to fix that?
I only noticed this behaviour in the editor when I resized the preview panel. Have you resized your window by any chance? Does a page reload fix it?
I had my browser maximized the the whole time, but shrinking it works and then it seems to work fine at any size except for if I then maximize it again and then the 6500k boundary stays at wherever it was when I shrunk the window so I can deal with that. On my phone (edge chromium browser) it seems that the upper boundary ends at the T in TV in my screenshot. Not sure how or if I can fix that since it seems to be a browser rendering issue
Hmmm, this is really weird. I cannot reproduce this issue here so I don’t really know what else you could try
I will paste you my current code asap that has some minor changes compared to Rainer’s suggestion above. Maybe this helps!?
This is the code I am currently using which works fine for me:
uid: color_light_v2
tags: []
props:
parameters:
- description: Header text
label: Header
name: header
required: false
type: TEXT
- context: item
description: Toggle ON/OFF
label: Toggle
name: lampToggle
required: true
type: TEXT
- context: item
description: Brightness
label: Brightness
name: brightness
required: true
type: TEXT
- context: item
description: Temperature in K
label: Temperature
name: temperature
required: true
type: TEXT
- context: item
description: Color mode (1 = White, 2 = Color)
label: Color Mode Item
name: colorMode
required: true
type: TEXT
- context: item
description: Color
label: Color Item
name: color
required: true
type: TEXT
parameterGroups: []
timestamp: Mar 15, 2021, 8:47:08 AM
component: f7-card
slots:
default:
- component: f7-card-content
config:
class:
- display-flex
- flex-direction-column
- justify-content-flex-start
- align-items-center
style:
height: 175px
slots:
default:
- component: f7-row
config:
style:
position: absolute
slots:
default:
- component: f7-block-header
slots:
default:
- component: Label
config:
text: =props.header
- component: f7-block
config:
class:
- no-padding
style:
width: 100%
height: 100%
margin-top: 2px
slots:
default:
- component: f7-block
config:
visible: '=items[props.colorMode].state == "1" ? true : false'
class:
- display-flex
- flex-direction-column
- justify-content-flex-end
style:
animation: f7-fade-in 300ms
height: 60%
margin-top: 10px
slots:
default:
- component: f7-row
config:
class:
- display-flex
- justify-content-space-between
- align-items-center
style:
width: calc(100% + 20px)
margin-left: -10px
slots:
default:
- component: f7-icon
config:
f7: thermometer
size: 20
style:
color: var(--f7-block-header-text-color)
- component: Label
config:
text: =items[props.temperature].state + "K"
style:
color: var(--f7-block-header-text-color)
- component: f7-row
config:
class:
- display-flex
- justify-content-center
- align-items-center
style:
width: 100%
slots:
default:
- component: oh-slider
config:
color: white
label: true
min: 1700
max: 6500
item: =props.temperature
style:
--f7-range-bar-size: 18px
--f7-range-bar-border-radius: 10px
--f7-range-knob-size: 20px
--f7-range-bar-active-bg-color: transparent
--f7-range-bar-bg-color: linear-gradient(to right, rgba(246,158,81,0.8), rgba(246,158,81,0))
--f7-range-knob-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3)
--f7-range-label-text-color: black
width: 100%
z-index: 99 !important
- component: f7-row
config:
class:
- display-flex
- justify-content-space-between
- align-items-center
style:
width: calc(100% + 20px)
margin-left: -10px
slots:
default:
- component: f7-icon
config:
f7: sun_min
size: 20
style:
color: var(--f7-block-header-text-color)
- component: Label
config:
text: =items[props.brightness].state + "%"
style:
color: var(--f7-block-header-text-color)
- component: f7-row
config:
class:
- display-flex
- justify-content-center
- align-items-center
style:
width: 100%
slots:
default:
- component: oh-slider
config:
color: white
label: true
item: =props.brightness
style:
--f7-range-bar-size: 18px
--f7-range-bar-border-radius: 10px
--f7-range-knob-size: 20px
--f7-range-bar-active-bg-color: rgba(246,246,0,0.5)
--f7-range-bar-bg-color: linear-gradient(to right, rgba(169,169,169,0.8), rgba(246,158,81,0))
--f7-range-knob-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3)
--f7-range-label-text-color: black
width: 100%
z-index: 99 !important
- component: f7-block
config:
visible: '=items[props.colorMode].state != "1" ? true : false'
class:
- no-margin
style:
animation: f7-fade-in 300ms
slots:
default:
- component: f7-row
config:
class:
- display-flex
- justify-content-center
slots:
default:
- component: f7-block
config:
style:
width: 180px
slots:
default:
- component: oh-colorpicker
config:
item: =props.color
modules:
- wheel
- component: f7-block
config:
class:
- display-flex
- justify-content-center
- align-items-center
- no-padding
- no-margin
style:
position: absolute
width: 40px
height: 40px
left: 10px
bottom: 10px
border-top:
box-shadow: '=items[props.lampToggle].state == "ON" ? "none" : "2px solid #ddd"'
box-shadow: "inset 0px 1px 2px #eee"
background: white
border-radius: 50%
slots:
default:
- component: f7-block
config:
class:
- no-margin
style:
position: absolute
width: 100%
height: 100%
box-shadow: '=items[props.lampToggle].state == "ON" ? "0 0 20px #fff, 0px 0px 30px rgba(0,255,0,0.5)" : "none"'
border-radius: 50%
transition: transform 0.2s
background: '=items[props.lampToggle].state == "ON" ? "rgba(124, 252, 0, 0.5)" : "transparent"'
transform: '=items[props.lampToggle].state =="ON" ? "scale(1,1)" : "scale(0,0)"'
- component: f7-block
config:
style:
position: absolute
width: calc(100% - 10px)
height: calc(100% - 10px)
background: rgba(255,255,255,0.8)
border-radius: 50%
- component: oh-link
config:
iconOnly: true
iconF7: power
iconSize: 17
action: toggle
actionItem: =props.lampToggle
actionCommand: '=items[props.lampToggle].state == "ON" ? "OFF" : "ON"'
style:
border: solid 2pt white
border-radius: 50%
background-color: "#f7f7f7"
background-image: "linear-gradient(135deg, #f7f7f7, #e7e7e7)"
color: "#a7a7a7"
width: calc(100% - 10px)
height: calc(100% - 10px)
text-align: center
box-shadow: 0px 3px 8px
backdrop-filter: opacity(88%)
z-index: 99 !important
- component: f7-block
config:
class:
- display-flex
- justify-content-center
- align-items-center
- no-padding
- no-margin
style:
position: absolute
bottom: 10px
right: 10px
width: 40px
height: 40px
border-top: '=items[props.colorMode].state == 2 ? "none" : "2px solid #ddd"'
box-shadow: "inset 0px 1px 2px #eee"
background: white
border-radius: 50%
slots:
default:
- component: f7-block
config:
class:
- no-margin
style:
position: absolute
width: 100%
height: 100%
box-shadow: '=items[props.colorMode].state == 2 ? "0 0 15px #fff, -7px -7px 15px rgba(255,0,0,0.5), 7px -7px 15px rgba(255,255,0,0.5), 7px 7px 15px rgba(0,255,0,0.5), -7px 7px 15px rgba(255,255,0,0.5)" : "none"'
border-radius: 50%
transition: transform 0.2s
background: '=items[props.colorMode].state == 2 ? "linear-gradient(135deg, red, orange, yellow, green, blue)" : "transparent"'
transform: '=items[props.colorMode].state == 2 ? "rotate(360deg) scale(1,1)" : "rotate(0deg) scale(0,0)"'
- component: f7-block
config:
style:
position: absolute
width: calc(100% - 10px)
height: calc(100% - 10px)
background: rgba(255,255,255,0.8)
border-radius: 50%
- component: oh-link
config:
iconOnly: true
iconF7: paintbrush
iconSize: 17
action: command
actionItem: =props.colorMode
actionCommand: 2
style:
display: '=items[props.colorMode].state == 1 ? "block" : "none"'
border: solid 2pt white
border-radius: 50%
background-color: "#f7f7f7"
background-image: "linear-gradient(135deg, #f7f7f7, #e7e7e7)"
color: "#a7a7a7"
width: calc(100% - 10px)
height: calc(100% - 10px)
text-align: center
box-shadow: 0px 3px 8px
backdrop-filter: opacity(88%)
class:
- nextSlide
- component: oh-link
config:
iconOnly: true
iconF7: paintbrush_fill
iconSize: 17
action: command
actionItem: =props.colorMode
actionCommand: 1
style:
display: '=items[props.colorMode].state == 2 ? "block" : "none"'
border: solid 2pt white
border-radius: 50%
background-color: "#f7f7f7"
background-image: "linear-gradient(135deg, #f7f7f7, #e7e7e7)"
color: "#a7a7a7"
width: calc(100% - 10px)
height: calc(100% - 10px)
text-align: center
box-shadow: 0px 3px 8px
backdrop-filter: opacity(88%)
class:
- previousSlide
- component: f7-card-footer
slots:
default:
- component: Label
config:
text: '=items[props.lampToggle].state == "ON" ? "Licht an" : "Licht aus"'
The v2 version seems to have fixed all of my issues, thanks!
You may also want to checkout v3. I’ll also update the code in the first post.
Changes:
uid: color_light_v3
tags: []
props:
parameters:
- description: Header text
label: Header
name: header
required: false
type: TEXT
- context: item
description: Toggle ON/OFF
label: Toggle
name: lampToggle
required: true
type: TEXT
- context: item
description: Brightness
label: Brightness
name: brightness
required: true
type: TEXT
- context: item
description: Temperature in K
label: Temperature
name: temperature
required: true
type: TEXT
- context: item
description: Color mode (1 = White, 2 = Color)
label: Color Mode Item
name: colorMode
required: true
type: TEXT
- context: item
description: Color
label: Color Item
name: color
required: true
type: TEXT
- context: item
description: Timer
label: Shutdown Timer Item
name: shutdowntimer
required: false
type: TEXT
parameterGroups: []
timestamp: Mar 17, 2021, 12:19:06 AM
component: f7-card
slots:
default:
- component: f7-card-content
config:
class:
- display-flex
- flex-direction-column
- justify-content-flex-start
- align-items-center
style:
height: 175px
slots:
default:
- component: f7-row
config:
style:
position: absolute
slots:
default:
- component: f7-block-header
slots:
default:
- component: Label
config:
text: =props.header
- component: f7-block
config:
class:
- no-padding
style:
width: 100%
height: 100%
margin-top: 2px
slots:
default:
- component: f7-block
config:
visible: '=items[props.colorMode].state == "1" ? true : false'
class:
- display-flex
- flex-direction-column
- justify-content-flex-end
style:
animation: f7-fade-in 300ms
height: 60%
margin-top: 10px
slots:
default:
- component: f7-row
config:
class:
- display-flex
- justify-content-space-between
- align-items-center
style:
width: calc(100% + 20px)
margin-left: -10px
slots:
default:
- component: f7-icon
config:
f7: thermometer
size: 20
style:
color: var(--f7-block-header-text-color)
- component: Label
config:
text: =items[props.temperature].state + "K"
style:
color: var(--f7-block-header-text-color)
- component: f7-row
config:
class:
- display-flex
- justify-content-center
- align-items-center
style:
width: 100%
slots:
default:
- component: oh-slider
config:
color: white
label: true
min: 1700
max: 6500
item: =props.temperature
style:
--f7-range-bar-size: 18px
--f7-range-bar-border-radius: 10px
--f7-range-knob-size: 20px
--f7-range-bar-active-bg-color: transparent
--f7-range-bar-bg-color: linear-gradient(to right, rgba(246,158,81,0.8), rgba(246,158,81,0))
--f7-range-knob-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3)
--f7-range-label-text-color: black
width: 100%
z-index: 99 !important
- component: f7-row
config:
class:
- display-flex
- justify-content-space-between
- align-items-center
style:
width: calc(100% + 20px)
margin-left: -10px
slots:
default:
- component: f7-icon
config:
f7: sun_min
size: 20
style:
color: var(--f7-block-header-text-color)
- component: Label
config:
text: =items[props.brightness].state + "%"
style:
color: var(--f7-block-header-text-color)
- component: f7-row
config:
class:
- display-flex
- justify-content-center
- align-items-center
style:
width: 100%
slots:
default:
- component: oh-slider
config:
color: white
label: true
item: =props.brightness
style:
--f7-range-bar-size: 18px
--f7-range-bar-border-radius: 10px
--f7-range-knob-size: 20px
--f7-range-bar-active-bg-color: rgba(246,246,0,0.5)
--f7-range-bar-bg-color: linear-gradient(to right, rgba(169,169,169,0.8), rgba(246,158,81,0))
--f7-range-knob-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3)
--f7-range-label-text-color: black
width: 100%
z-index: 99 !important
- component: f7-block
config:
visible: '=items[props.colorMode].state != "1" ? true : false'
class:
- no-margin
style:
animation: f7-fade-in 300ms
slots:
default:
- component: f7-row
config:
class:
- display-flex
- justify-content-center
slots:
default:
- component: f7-block
config:
style:
width: 180px
slots:
default:
- component: oh-colorpicker
config:
item: =props.color
modules:
- wheel
- component: f7-block
config:
class:
- display-flex
- justify-content-center
- align-items-center
- no-padding
- no-margin
style:
position: absolute
width: 40px
height: 40px
left: 10px
bottom: 10px
border-top: '=items[props.lampToggle].state == "ON" ? "none" : "2px solid #ddd"'
box-shadow: "inset 0px 1px 2px #eee"
background: white
border-radius: 50%
slots:
default:
- component: f7-block
config:
class:
- no-margin
style:
animation: '=items[props.shutdowntimer].state.split(" ")[0] > 0 ? "skeleton-effect-fade 2s linear infinite" : "none"'
position: absolute
width: 100%
height: 100%
box-shadow: '=items[props.lampToggle].state == "ON" ? "0 0 20px #fff, 0px 0px 30px rgba(0,255,0,0.5)" : "none"'
border-radius: 50%
transition: transform 0.2s
background: '=items[props.lampToggle].state == "ON" ? "rgba(124, 252, 0, 0.5)" : "transparent"'
transform: '=items[props.lampToggle].state =="ON" ? "scale(1,1)" : "scale(0,0)"'
- component: f7-block
config:
style:
position: absolute
width: calc(100% - 10px)
height: calc(100% - 10px)
background: rgba(255,255,255,0.8)
border-radius: 50%
- component: oh-link
config:
iconOnly: true
iconF7: power
iconSize: 17
action: toggle
actionItem: =props.lampToggle
actionCommand: '=items[props.lampToggle].state == "ON" ? "OFF" : "ON"'
style:
border: solid 2pt white
border-radius: 50%
background-color: "#f7f7f7"
background-image: "linear-gradient(135deg, #f7f7f7, #e7e7e7)"
color: "#a7a7a7"
width: calc(100% - 10px)
height: calc(100% - 10px)
text-align: center
box-shadow: 0px 3px 8px
backdrop-filter: opacity(88%)
z-index: 99 !important
- component: oh-link
config:
text: Timer
visible: "=props.shutdowntimer ? true : false"
action: popover
popoverOpen: .timerpopover
style:
position: absolute
bottom: 10px
slots:
default:
- component: f7-popover
config:
class:
- timerpopover
slots:
default:
- component: oh-stepper-card
config:
item: =props.shutdowntimer
title: Ausschalten in Minuten
- component: f7-block
config:
class:
- display-flex
- justify-content-center
- align-items-center
- no-padding
- no-margin
style:
position: absolute
bottom: 10px
right: 10px
width: 40px
height: 40px
border-top: '=items[props.colorMode].state == 2 ? "none" : "2px solid #ddd"'
box-shadow: "inset 0px 1px 2px #eee"
background: white
border-radius: 50%
slots:
default:
- component: f7-block
config:
class:
- no-margin
style:
position: absolute
width: 100%
height: 100%
box-shadow: '=items[props.colorMode].state == 2 ? "0 0 15px #fff, -7px -7px 15px rgba(255,0,0,0.5), 7px -7px 15px rgba(255,255,0,0.5), 7px 7px 15px rgba(0,255,0,0.5), -7px 7px 15px rgba(255,255,0,0.5)" : "none"'
border-radius: 50%
transition: transform 0.2s
background: '=items[props.colorMode].state == 2 ? "linear-gradient(135deg, red, orange, yellow, green, blue)" : "transparent"'
transform: '=items[props.colorMode].state == 2 ? "rotate(360deg) scale(1,1)" : "rotate(0deg) scale(0,0)"'
- component: f7-block
config:
style:
position: absolute
width: calc(100% - 10px)
height: calc(100% - 10px)
background: rgba(255,255,255,0.8)
border-radius: 50%
- component: oh-link
config:
iconOnly: true
iconF7: paintbrush
iconSize: 17
action: command
actionItem: =props.colorMode
actionCommand: 2
style:
display: '=items[props.colorMode].state == 1 ? "block" : "none"'
border: solid 2pt white
border-radius: 50%
background-color: "#f7f7f7"
background-image: "linear-gradient(135deg, #f7f7f7, #e7e7e7)"
color: "#a7a7a7"
width: calc(100% - 10px)
height: calc(100% - 10px)
text-align: center
box-shadow: 0px 3px 8px
backdrop-filter: opacity(88%)
class:
- nextSlide
- component: oh-link
config:
iconOnly: true
iconF7: paintbrush_fill
iconSize: 17
action: command
actionItem: =props.colorMode
actionCommand: 1
style:
display: '=items[props.colorMode].state == 2 ? "block" : "none"'
border: solid 2pt white
border-radius: 50%
background-color: "#f7f7f7"
background-image: "linear-gradient(135deg, #f7f7f7, #e7e7e7)"
color: "#a7a7a7"
width: calc(100% - 10px)
height: calc(100% - 10px)
text-align: center
box-shadow: 0px 3px 8px
backdrop-filter: opacity(88%)
class:
- previousSlide
- component: f7-card-footer
slots:
default:
- component: Label
config:
text: '=items[props.lampToggle].state == "ON" ? "Licht an" : "Licht aus"'
Hey,
I really like your widget.
I modified it a little bit, to work with the dimmer item for the hue bridge color temperature (0 - 100%). I also changed the text of the actual color temperature to the following one, because the item state is often NULL.
[...]
text: '=items[props.temperature].state == "NULL" ? "-" : items[props.temperature].state + "%"'
[...]
I have the problem, that sometimes the slider is out of the card (tested on Mac Safari and iPadOS Safari):
tardismechanic had the same issue (see above). He said that v2 fixed this for him (code also above). You may want to try to start with that and add your charges one by one to see what breaks the widget.
My approach to the color temp as a percent was to create a ColorTempK that’s “write only” to the percent channel item that I linked to the widget and this rule. My two items are LightName_ColorTemp and LightName_ColorTempK. There’s probably a better way to do it, or possibly in the widget itself but I don’t know much about doing stuff like that in widgets (yet) so this works for me.
#Get the base item name
tempName = event.itemName.split("_")[0]
#2700 is the lowest temp, so make that the new "0"
colorTempNormalized = float(str(ir.getItem(event.itemName).state)) - 2700
# Divide the "normalized" temp by the difference between the lowest and highest values
# In my case that's 2700 and 6500, so 3800 is the result. Make that a percent (*100)
# and invert that percent (100 -) because in my case 2700k should be 0% (on the left end of the slider) and 6500k
# should be 100% (on the right end of the slider)
pct = 100 - ((colorTempNormalized / 3800) * 100)
# round off the decimals because I don't care about them and post it to the true
# _ColorTemp to make the actual change
events.sendCommand(tempName + "_ColorTemp","{:.0f}".format(pct))
This way the widget shows 2700k - 6500k as a slider and doesn’t bounce around when you make a change like with mine (zwave bulbs) when I change the color temp, it posts the change to the binding and the binding immediately sets it to NULL when the change it made
FYI @DrRSatzteil You can set your own keyframe animations now (see Add stylesheet configuration to widgets by hubsif · Pull Request #979 · openhab/openhab-webui · GitHub)
That offers a whole new world of possibilities for the creation of custom widgets.
That’s really cool, thanks for pointing that out! I’m already looking forward for the first cool examples and probably something comes to my mind as well
By the way I stumbled upon the same problem a couple of days ago: the espmilight binding also uses a 0 - 100 range for the temperature. I still wanted the Kelvin value to be displayed and it can actually be done conpletely in the widget code: https://community.openhab.org/t/light-widget-with-temperature-control
You may of course stick with your version, I don’t see any disadvantages besides the additional item.
Thanks for sharing! I like having it all in the widget better, I just didn’t have the time to try and sort it out so I went with what I knew
I really like this widget.
Everything works fine, but when i press the color select button and the color wheel is displayed. It closes the color wheel card before I am able to chose a color…
Any suggestions or clues?
I’m not sure exactly what you mean. Would it be possible to post a gif file here?
Do you happen to use the miio binding? If so please try to set the profile of the color mode channel to “follow” and try if that works for you.