Heating widget

Hi everyone,

after a little while, i would like to introduce a other heating widget today.
I looked for an example on the internet and transformed it into the main ui structure.

Reasons for development
The new main ui has become very beautiful and has a lot of potential. Thank’s @ysc for your work! :slight_smile:
I was looking for a nice widget to control a heater.
It is possible to use all components (oh-slider, oh-button etc.) to create a widget that has all the functions you need.
In my head, however, I imagined a widget with all the necessary functions in gauge design.
That is the main reason for developing this widget.

My target/goal

  • better understanding of F7 components and their structure
  • better understanding of yaml
  • nice widget in gauge design with the components (set-temperature, current-temperature, location name, air humidity, button for eg. boiler
  • test the possibilities of yaml and the main ui

Main UI restrictions
The main ui is very good and I just want to list the missing functions that would have helped in this example. (that should not represent a carp list :wink: )
@RGroll also noted a few things here:
https://community.openhab.org/t/wiki-building-pages-in-the-oh3-ui-documentation-draft-2-3/104392/11

It isn’t possible to:

  • interact with svg style elements
  • use css pseudo classes
  • use a own css stylesheet or define css styles in a head-area
  • use css animations

Maybe these functions can still be implemented sometime.

And now, here is the result and the first iteration of the heating-widget.

Check it out, improve it and style it however you want! :wink:
I think this is a good base for anyone who wants such a widget.

Feel free to contact me if you have any questions or feedback.

all the best,
Nico

20210122_220649

20210417_105935

Changelog:
v1.6

  • fix the issue if the items come with UoM (eg. Number:Temperature). Put split(’ ')[0] to the item states in transform expressions. Thanks @BobMiles for the fast improvement.
  • implement the min/max boundary to the increase/decrease buttons
  • fix the z-index of the current marker. Implement ,pointer-events: none’’ to the parent div.

@ysc can you please update the code on openHAB ? Thx

v1.7

  • the widget is now ready for a responsive design. Only the font-size is fix and must be adjust.
    → define the size in the props will fix the widget, without a size the container scale to the card width.

v1.8

Notes and YAML under
https://community.openhab.org/t/oh3-heating-widget-based-on-css/115107/33?u=nico_r
https://community.openhab.org/t/oh3-heating-widget-based-on-css/115107/34?u=nico_r

v1.8.1

v2.0.0

24 Likes

Looks great @Nico_R :heart_eyes:
Your missing features are noted, but I don’t know how or when they’ll be implemented.

1 Like

Added it to https://demo.openhab.org/#!/page/temperatures, hope you don’t mind!

I am glad that the widget can be found on the demo page.
I also hope that all users get along with the bugs in the code :smiley:

I found a bug :frowning:
I must fix/pass the max and min value of the buttons according the bar min/max value.
I will fix this in the next days.

Thank you so much for this amazing widget!
I was looking for something like this, but couldn’t put it together myself…
I experience a little issue though: My Temperature items and channels are Number:Temperature so they come with the UoM.
That makes the widget not accept the values:


I’ll try to look into it when I have the time!

All the best,
Bob

Edit:
Here’s a quick fix for people who use units of measurement on their temperature items:

fix was added to initial post - code removed

1 Like

Thanks’s @BobMiles! I’ve update the yaml with some other fixes in the first post.

Nico

1 Like

Hey @Nico_R

Great work! Just out of curiosity, what are these classes (like fill, bar, hold or left etc.) you’ve defined in the components? Are these just placeholders or do the serve a purpose in the functionality of the widget?

I’ m assuming that you digged deep into the underlying css to find the keyframes for the animations - very dedicated work! :+1:

Hey @RGroll

you are right. The classes are placeholders without function. It’s easier to keep track of things. Sorry for the confusion. :wink:
Maybe we can use custom classes in the future. :slight_smile:

Nico

Thanks for your quick answer!

No problem at all - I was just interested.

I try to use a random config parameters like `_COMMENT:’ or similar to keep track of different sections, since Yannick told me, that they will be ignored during the loading of the widget (and could therefore serve as a replacement for ‘standard’ commenting.

Yeah, that would be helpfull :slight_smile:
It would be also nice if we could add own keyframe animations in the future (or have a good library of pre-defined ones in the css for standard usecases)

2 Likes

Hi guys,

The Widget is fantastic. I started doing something similar but gave up along the way as this is very new to me and struggling to understand the concepts.

I am trying this widget on my phone as well, but it seems the “responsiveness” is not great (scaling on smaller screen is a bit off). I would like to contribute to this and improve it but, I would need a couple of hints where should I start and when needs to be done (then at least I will have an idea what to research).

Hi @Ghinet_Alexandru

i don’t fully understand the problem.
You must define the size in the widget settings. Thats the same procedure like with a knob widget.
The parent card widget scale with the column size but the child widget (here my heating widget or the OH-Knob) have a fix size.

A responsive design in this case is a bit heavy because of the lot of elements and the font size.

EDIT: I will test a responsive design. This will take a while.

best,

Nico

Hi @Nico_R

thank you for your great work on the widget.

Can you give me a hint as to what I have to change so that instead of the openhab logo I get a label field for the switch below.

Hi @Tallman ,

if you want only show a simple text label i can suggest the follow solution.

Change the oh-image component to a Label component at the same position.

                              - component: Label
                                config:
                                  text: Your Text
                                  style:
                                    position: absolute
                                    transform: translate(-50%)
                                    left: 50%
                                    width: 40%                                  
                              #- component: oh-image
                                #config:
                                  #url: https://community-openhab-org.s3-eu-central-1.amazonaws.com/original/2X/7/7d388a86c95471f89b1bb911d96d7609a3e3a059.svg
                                  #style:
                                    #position: absolute
                                    #transform: translate(-50%)
                                    #left: 50%
                                    #width: 40%

The result:

grafik

all the best,

Nico

Hey @Ghinet_Alexandru

look at the first post. I’ve updated the yaml.
The widget in v1.7 is now more responsive.

2 Likes

Hi @Nico_R
it works thank you

Cool looking and good working widget, thank you for that!

Hi Nico,
great work. I’m using the widget for all my AVM-thermostats.

As you can see I’m using a List-Card-Widget to get some other information and to rule several modes. Are these information interesting enough to you too, to integrate it in your widget ??? :wink:

Another point is that you have written above something about

Is it part of the widget, as I didn’t find anything in the widget ?

Thx again, and
Cheers,
Peter

1 Like

Hi @fibu-freak

thanks for the positive feedback.

Please post the little yaml extract of your list-component under the widget.

I will looking for a good solution.

best,
Nico

First of all, i wish to say big Thank You for you excellent work! Widget just beautiful!
I use it with MAX! thermostats and it get big thumbs up, especially from my wife :slight_smile: .
I made few improvements, may be it will be useful for someone.
First, operations of my thermostats linked to windows open state, so I added icon representing window state. It accept ether item or group and expect states OPEN or CLOSED. Unfortunately, f7 icon set does not include windows icons, so I use icons from openhab classic set.
Next, I added ability to display thermostat mode. It expect string item and display it as is. Maybe it need to be made as a menu, but I’m almost never switch thermostat mode manually.
Last but not least I added ability to display heating status, like it is done in OH locations badges. But I’m don’t like default OH HVAC icon, so instead string “HEATING” change color then heating active. Expect simple binary item with ON/OFF state.
Screenshots:


Code:

uid: HeatingCSS_1.8
tags:
  - heating
props:
  parameters:
    - description: eg. living room
      label: location
      name: location
      required: false
      type: TEXT
    - description: Visual size of the control in px (default 400px), without a size the design is responsive
      label: size [px]
      name: size
      required: false
      type: TEXT
    - description: Minimum value
      label: minTemp
      name: minTemp
      required: true
      type: TEXT
    - description: Maximum value
      label: maxTemp
      name: maxTemp
      required: true
    - context: item
      description: Item to control
      label: Set point Item
      name: setPointItem
      required: true
      type: TEXT
    - context: item
      label: Item for current temperature
      name: currentPointItem
      required: true
      type: TEXT
    - context: item
      label: Item to toggle something
      name: toggleItem
      required: false
      type: TEXT
    - context: item
      label: Item to display window state
      name: windowItem
      required: false
      type: TEXT
    - context: item
      label: Item to display thermostat mode
      name: modeItem
      required: false
      type: TEXT
    - context: item
      label: Item to display heater state
      name: heaterItem
      required: false
      type: TEXT
    - description: Control item unit eg °C
      label: unit
      name: unit
      required: false
      type: TEXT
    - label: Main-Color Thermostat
      name: colorThermostat
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color control ring
      name: colorControlRing
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color buttons
      name: colorButton
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color center
      name: colorCenter
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color Typo
      name: colorTypo
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color setPoint Marker
      name: colorSetMarker
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color currentPoint Marker
      name: colorCurrentMarker
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color bar linear gradient startPoint
      name: colorBarStartPoint
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color bar linear gradient endPoint
      name: colorBarEndPoint
      required: false
      type: TEXT
      groupName: colors
      advanced: true
  parameterGroups:
    - name: colors
      label: Color-Settings
timestamp: Feb 12, 2021, 4:56:28 PM
component: f7-card
config:
  title: "=(props.location) ? 'Klima ' + props.location : ''"
slots:
  default:
    - component: f7-card-content
      slots:
        default:
          - component: f7-row
            config:
              resizableFixed: true
              resizable-absolute: true
              class:
                - justify-content-center
            slots:
              default:
                - component: f7-block
                  config:
                    class: thermostat
                    style:
                      flex-shrink: 0
                      --f7-block-margin-vertical: 0px
                      --f7-block-padding-vertical: 0px
                      --f7-block-padding-horizontal: 0px
                      padding-left: 0px
                      padding-top: "=props.size ? '': '100%'"
                      width: "=props.size ? Number(props.size)+'px' : '100%'"
                      height: "=props.size ? Number(props.size)+'px' : '100%'"
                      background: "=props.colorThermostat ? props.colorThermostat : 'var(--f7-toggle-inactive-color)'"
                      border-radius: 50%
                      border: 2px solid rgb(64, 60, 77)
                  slots:
                    default:
                      - component: f7-block
                        config:
                          class: bar
                          style:
                            margin-top: 0px
                            position: absolute
                            width: "=props.size ? (Number(props.size)*0.89) +'px' : '89%'"
                            height: "=props.size ? (Number(props.size)*0.89) +'px' : '89%'"
                            top: 50%
                            left: 50%
                            transform: translate(-50%, -50%)
                            border-radius: 50%
                        slots:
                          default:
                            - component: f7-block
                              config:
                                class: inner_bar
                                style:
                                  margin-top: 0
                                  position: absolute
                                  top: 50%
                                  left: 50%
                                  transform: translate(-50%, -50%)
                                  width: "=props.size ? (Number(props.size)*0.86) +'px' : '97%'"
                                  height: "=props.size ? (Number(props.size)*0.86) +'px' : '97%'"
                                  border-radius: 100%
                                  background-color: "=props.colorThermostat ? props.colorThermostat : 'var(--f7-toggle-inactive-color)'"
                                  z-index: 4 !important
                              slots:
                                default:
                                  - component: f7-block
                                    config:
                                      style:
                                        background: "='conic-gradient(transparent 0deg 160deg, ' + (props.colorThermostat ? props.colorThermostat : 'var(--f7-toggle-inactive-color)') + ' 160deg 200deg, transparent 200deg 360deg)'"
                                        content: ""
                                        display: block
                                        position: absolute
                                        width: 100%
                                        height: 100%
                                        bottom: "=props.size ? '-7px' : '-7px'"
                                        left: 50%
                                        transform: translate(-50%)
                            - component: f7-block
                              config:
                                class: hold left
                                style:
                                  margin-top: 0px
                                  position: absolute
                                  width: 100%
                                  height: 100%
                                  clip-path: "=props.size ? 'inset(0px 0px 0px ' + (Number(props.size)*0.89/2) + 'px)' : 'inset(0% 0% 0% 50%)'"
                                  border-radius: 100%
                                  background-color: rgb(58, 55, 73)
                              slots:
                                default:
                                  - component: f7-block
                                    config:
                                      class: fill fill1
                                      style:
                                        margin-top: 0px
                                        position: absolute
                                        width: 100%
                                        height: 100%
                                        border-radius: 100%
                                        clip-path: "=props.size ? 'inset(0px ' + (Number(props.size)*0.89/2) + 'px 0px 0px)' : 'inset(0% 50% 0% 0%)'"
                                        background: "=props.colorBarStartPoint && props.colorBarEndPoint ? '-webkit-linear-gradient(top, ' + props.colorBarEndPoint + ' 20%,' + props.colorBarEndPoint + ' 100%)' : '-webkit-linear-gradient(top, rgb(255, 73, 0) 20%,rgb(255, 73, 0) 100%)'"
                                        z-index: 1 !important
                                        animation: left 0.3s linear both
                                        animation-delay: 1s
                                        transition: transform 0.6s
                                        transform: "=(items[props.setPointItem].state.split(' ')[0] >= (((Number(props.maxTemp) - Number(props.minTemp)) / 2) + Number(props.minTemp)) && items[props.setPointItem].state.split(' ')[0] <= Number(props.maxTemp) ? 'rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.setPointItem].state.split(' ')[0]-Number(props.minTemp))-160)+'deg)' : (items[props.setPointItem].state.split(' ')[0] > Number(props.maxTemp)) ? 'rotate(180deg)' : '')"
                            - component: f7-block
                              config:
                                class: hold right
                                style:
                                  margin-top: 0px
                                  position: absolute
                                  width: 100%
                                  height: 100%
                                  clip-path: "=props.size ? 'inset(0px 0px 0px ' + (Number(props.size)*0.89/2) + 'px)' : 'inset(0% 0% 0% 50%)'"
                                  border-radius: 100%
                                  background-color: rgb(58, 55, 73)
                                  z-index: 3 !important
                                  transform: rotate(180deg)
                              slots:
                                default:
                                  - component: f7-block
                                    config:
                                      class: fill
                                      style:
                                        margin-top: 0px
                                        position: absolute
                                        width: 100%
                                        height: 100%
                                        border-radius: 100%
                                        z-index: 3 !important
                                        animation: right 1s linear both
                                        transition: transform 0.6s
                                  - component: f7-block
                                    config:
                                      class: fill fill2
                                      style:
                                        position: absolute
                                        margin-top: 0px
                                        width: 100%
                                        height: 100%
                                        border-radius: 50%
                                        z-index: 3 !important
                                        clip-path: "=props.size ? 'inset(0px '+ (Number(props.size)*0.89/2) + 'px 0px 0px)' : 'inset(0% 50% 0% 0%)'"
                                        background: "=props.colorBarStartPoint && props.colorBarEndPoint ? '-webkit-linear-gradient(top, ' + props.colorBarEndPoint + ' 40%,' + props.colorBarStartPoint + ' 100%)' : '-webkit-linear-gradient(top, rgb(255, 73, 0) 40%,rgb(255, 158, 35) 100%)'"
                                        transform: "=(items[props.setPointItem].state.split(' ')[0] <= (((Number(props.maxTemp) - Number(props.minTemp)) / 2) + Number(props.minTemp)) && items[props.setPointItem].state.split(' ')[0] >= Number(props.minTemp) ? 'rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.setPointItem].state.split(' ')[0]-Number(props.minTemp))+20)+'deg)' : (items[props.setPointItem].state.split(' ')[0] > (((Number(props.maxTemp) - Number(props.minTemp)) / 2) + Number(props.minTemp))) ? 'rotate(180deg)' :  '')"
                            - component: f7-block
                              config:
                                class: span
                                style:
                                  margin-top: 0px
                                  width: "=props.size ? (Number(props.size)*0.89) +'px' : '100%'"
                                  font-weight: "=props.size ? (Number(props.size)*2) +'px' : 'calc(var(--f7-list-item-title-font-weight)*2)'"
                                  position: absolute
                                  bottom: 0px
                                  text-align: center
                                  text-transform: uppercase
                                  font-size: "=props.size ? (Number(props.size)*0.0375) +'px' : '1em'"
                                  color: "=props.colorTypo ? props.colorTypo : 'rgb(87, 84, 95)'"
                                  z-index: 99 !important
                              slots:
                                default:
                                  - component: Label
                                    config:
                                      text: Heating
                                      style:
                                        color: "=(items[props.heaterItem].state === 'ON') ? 'orange' : 'black'"
                      - component: f7-block
                        config:
                          class: shadow
                          style:
                            margin-top: 0px
                            position: absolute
                            top: 50%
                            left: 50%
                            transform: "=(items[props.setPointItem].state.split(' ')[0] >= Number(props.minTemp) && items[props.setPointItem].state.split(' ')[0] <= Number(props.maxTemp) ? 'translate(-50%, -50%) rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.setPointItem].state.split(' ')[0]-Number(props.minTemp))-160)+'deg)' : 'translate(-50%, -50%) rotate(0deg)')"
                            width: "=props.size ? (Number(props.size)*0.0625) +'px' : '6.25%'"
                            height: 86%
                            text-align: center
                            transition: 0.7s ease
                            animation: shadow 1.4s ease-out both
                        slots:
                          default:
                            - component: f7-block
                              config:
                                class: shadow-cube
                                style:
                                  margin-top: 0px
                                  position: absolute
                                  top: 0
                                  width: "=props.size ? (Number(props.size)*0.0625) +'px' : '100%'"
                                  height: 0px
                                  box-shadow: "=props.size ? '0 0 ' + (Number(props.size)*0.1125) +'px ' + (Number(props.size)*0.0325) + 'px ' + (props.colorSetMarker ? props.colorSetMarker : 'rgba(255, 158, 35, 0.5)'): '0 0 45px 13px rgba(255, 158, 35, 0.5)'"
                      - component: f7-block
                        config:
                          class: markerContainer
                          style:
                            pointer-events: none
                            margin-top: 0px
                            position: absolute
                            top: 50%
                            left: 50%
                            transform: "=(items[props.currentPointItem].state.split(' ')[0] >= Number(props.minTemp) && items[props.currentPointItem].state.split(' ')[0] <= Number(props.maxTemp) ? 'translate(-50%, -50%) rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.currentPointItem].state.split(' ')[0]-Number(props.minTemp))-160)+'deg)' : 'translate(-50%, -50%) rotate(0deg)')"
                            width: "=props.size ? (Number(props.size)*0.1) +'px' : '10%'"
                            height: 100%
                            text-align: center
                            transition: 0.7s ease
                            opacity: 1
                            z-index: 99 !important
                        slots:
                          default:
                            - component: f7-block
                              config:
                                class: markerCurrent
                                style:
                                  margin-top: 0px
                                  width: "=props.size ? (Number(props.size)*0.1) +'px' : '100%'"
                                  height: "=props.size ? (Number(props.size)*0.1) +'px' : ''"
                                  padding-top: "=props.size ? '' : '100%'"
                                  background: "=props.colorCurrentMarker ? props.colorCurrentMarker : 'rgb(33, 150, 243)'"
                                  position: absolute
                                  transform: translate(-50%,-50%) rotate(45deg)
                                  left: 50%
                                  top: "=props.size ? (Number(props.size)*0.14) +'px' : '15%'"
                                  border-radius: 0% 50% 50% 50%
                                  box-shadow: 0 0 5px 1px rgb(48, 46, 56)
                              slots:
                                default:
                                  - component: f7-block
                                    config:
                                      class: number
                                      style:
                                        margin-top: 0px
                                        position: absolute
                                        top: 50%
                                        left: 50%
                                        transform: translate(-50%, -50%) rotate(-45deg)
                                        text-align: center
                                    slots:
                                      default:
                                        - component: Label
                                          config:
                                            text: =items[props.currentPointItem].state.split(' ')[0]
                                            style:
                                              font-size: "=props.size ? (Number(props.size)*0.04) +'px' : '14px'"
                                              color: white
                                              font-weight: bold
                      - component: f7-block
                        config:
                          class: markerContainer
                          style:
                            pointer-events: none
                            margin-top: 0px
                            position: absolute
                            top: 50%
                            left: 50%
                            transform: "=(items[props.setPointItem].state.split(' ')[0] >= Number(props.minTemp) && items[props.setPointItem].state.split(' ')[0] <= Number(props.maxTemp) ? 'translate(-50%, -50%) rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.setPointItem].state.split(' ')[0]-Number(props.minTemp))-160)+'deg)' : 'translate(-50%, -50%) rotate(0deg)')"
                            width: "=props.size ? (Number(props.size)*0.1) +'px' : '10%'"
                            height: 100%
                            text-align: center
                            transition: 0.7s ease
                            opacity: 1
                            z-index: 99 !important
                        slots:
                          default:
                            - component: f7-block
                              config:
                                class: markerSet
                                style:
                                  margin-top: 0px
                                  width: "=props.size ? (Number(props.size)*0.1) +'px' : '100%'"
                                  height: "=props.size ? (Number(props.size)*0.1) +'px' : ''"
                                  padding-top: "=props.size ? '' : '100%'"
                                  background: "=props.colorSetMarker ? props.colorSetMarker : 'rgb(230, 74, 25)'"
                                  position: absolute
                                  transform: translate(-50%,-50%) rotate(-45deg)
                                  left: 50%
                                  top: "=props.size ?  (Number(props.size)*Number(-0.0125)) +'px': '-2%'"
                                  border-radius: 50% 50% 50% 0
                                  box-shadow: 0 0 5px 1px rgb(48, 46, 56)
                                  z-index: 100 !important
                              slots:
                                default:
                                  - component: f7-block
                                    config:
                                      class: number
                                      style:
                                        margin-top: 0px
                                        position: absolute
                                        top: 50%
                                        left: 50%
                                        transform: translate(-50%, -50%) rotate(45deg)
                                        text-align: center
                                    slots:
                                      default:
                                        - component: Label
                                          config:
                                            text: =items[props.setPointItem].state.split(' ')[0]
                                            style:
                                              font-size: "=props.size ? (Number(props.size)*0.04) +'px' : '14px'"
                                              color: white
                                              font-weight: bold
                      - component: f7-block
                        config:
                          class: center
                          style:
                            margin-top: 0px
                            position: absolute
                            width: "=props.size ? (Number(props.size)*0.65) +'px' : '65%'"
                            height: "=props.size ? (Number(props.size)*0.65) +'px' : '65%'"
                            background: "=props.colorControlRing ? props.colorControlRing : 'rgb(227, 228, 237)'"
                            animation: bound-in 0.6s ease forwards
                            top: 50%
                            left: 50%
                            transform: translate(-50%, -50%)
                            border-radius: 50%
                            box-shadow: 0px 15px 35px 11px rgba(46, 44, 58,0.60)
                        slots:
                          default:
                            - component: oh-toggle
                              config:
                                visible: "=props.toggleItem ? true : false"
                                item: =props.toggleItem
                                style:
                                  position: absolute
                                  bottom: 0%
                                  left: 50%
                                  transform: translate(-50%,-50%)
                                  color: "=props.colorButton ? props.colorButton + ' !important': ''"
                            - component: oh-icon
                              config:
                                visible: "=props.windowItem ? true : false"
                                icon: "=(items[props.windowItem].state === 'OPEN') ? 'window-open' : 'window-closed'"
                                style:
                                  position: absolute
                                  bottom: 40%
                                  left: 50%
                                  transform: translate(-50%,-50%)
                                  width: 20%
                                  height: 50%
                            - component: oh-button
                              config:
                                visible: "=props.modeItem ? true : false"
                                item: =props.toggleItem
                                text: =items[props.modeItem].state
                                style:
                                  position: absolute
                                  bottom: 5%
                                  left: 50%
                                  transform: translate(-50%,-50%)
                                  color: "=props.colorButton ? props.colorButton + ' !important': ''"
                            - component: oh-button
                              config:
                                style:
                                  --f7-button-hover-bg-color: transparent
                                  --f7-button-pressed-bg-color: transparent
                                  width: 30%
                                  height: 50%
                                  position: absolute
                                  margin-top: 0px
                                  top: 50%
                                  left: 10%
                                  transform: translate(-50%, -50%)
                                  color: "=props.colorButton ? props.colorButton : ''"
                                action: command
                                actionItem: =props.setPointItem
                                actionCommand: "=Number(items[props.setPointItem].state.split(' ')[0]) > Number(props.minTemp) ? Number(items[props.setPointItem].state.split(' ')[0]) - 0.5 : ''"
                              slots:
                                default:
                                  - component: f7-icon
                                    config:
                                      size: "=props.size ? (Number(props.size)*0.075) : '30'"
                                      style:
                                        position: absolute
                                        transform: translate(-50%, -50%)
                                        top: 50%
                                        margin-top: auto
                                      f7: arrow_turn_left_down
                            - component: oh-button
                              config:
                                style:
                                  --f7-button-hover-bg-color: transparent
                                  --f7-button-pressed-bg-color: transparent
                                  width: 30%
                                  height: 50%
                                  position: relative
                                  margin-top: 0px
                                  top: 50%
                                  left: 90%
                                  transform: translate(-50%, -50%)
                                  color: "=props.colorButton ? props.colorButton : ''"
                                action: command
                                actionItem: =props.setPointItem
                                actionCommand: "=Number(items[props.setPointItem].state.split(' ')[0]) < Number(props.maxTemp) ? Number(items[props.setPointItem].state.split(' ')[0]) + 0.5 : ''"
                              slots:
                                default:
                                  - component: f7-icon
                                    config:
                                      size: "=props.size ? (Number(props.size)*0.075) : '30'"
                                      style:
                                        position: absolute
                                        transform: translate(-50%, -50%)
                                        top: 50%
                                        margin-top: auto
                                      f7: arrow_turn_right_up
                            - component: f7-block
                              config:
                                class: small
                                style:
                                  margin-top: 0px
                                  position: absolute
                                  width: "=props.size ? (Number(props.size)*0.375) +'px' : '57.6%'"
                                  height: "=props.size ? (Number(props.size)*0.375) +'px' : '57.6%'"
                                  background: "=props.colorCenter ? props.colorCenter : 'rgb(248, 249, 250)'"
                                  text-align: center
                                  animation: bound-in-small 0.6s ease forwards
                                  top: 50%
                                  left: 50%
                                  transform: translate(-50%, -50%)
                                  border-radius: 50%
                                  box-shadow: 0px 5px 10px 5px rgba(96, 93, 111,0.19)
                              slots:
                                default:
                                  - component: f7-block
                                    config:
                                      class: heat
                                      style:
                                        font-size: "=props.size ? (Number(props.size)*0.0375) +'px' : '14px'"
                                        color: "=props.colorTypo ? props.colorTypo : 'rgb(87, 84, 95)'"
                                        font-weight: 300
                                    slots:
                                      default:
                                        - component: Label
                                          config:
                                            text: =props.location
                                  - component: f7-block
                                    config:
                                      class: heat
                                      style:
                                        font-size: "=props.size ? (Number(props.size)*0.1125) +'px' : '2.5em'"
                                        color: "=props.colorTypo ? props.colorTypo : 'rgb(87, 84, 95)'"
                                        font-weight: 300
                                    slots:
                                      default:
                                        - component: Label
                                          config:
                                            text: "=props.unit ? items[props.setPointItem].state.split(' ')[0] + '' + props.unit : items[props.setPointItem].state.split(' ')[0]"
                                  - component: oh-image
                                    config:
                                      url: https://community-openhab-org.s3-eu-central-1.amazonaws.com/original/2X/7/7d388a86c95471f89b1bb911d96d7609a3e3a059.svg
                                      style:
                                        position: absolute
                                        transform: translate(-50%)
                                        left: 50%
                                        width: 40%

3 Likes