openHAB widget: card-expandable placement

Hello,

currently I’m learning how to create own widgets in openHAB. Therefore, I tried to configure a lightning switch widget with an optional dimmer popup.

uid: widget_lightdimmer_v1.0
tags:
  - light
  - dimmer
props:
  parameters:
    - description: Item Name
      name: itemname
      required: true
      type: TEXT
    - context: item
      description: Dimmer Item
      label: Item
      name: dimmeritem
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Dec 3, 2022, 4:48:54 PM
component: f7-card
config:
  expandable: true
  swipeToClose: false
  backdrop: true
  noShadow: true
  class:
    - card-expandable-animate-width
  style:
    max-height: 90px
    min-width: 300px
    margin: 5px
slots:
  default:
    - component: oh-button
      config:
        iconF7: gear
        iconSize: 25px
        color: black
        style:
          position: absolute
          top: 0
          right: 0
          padding-top: 30px
          padding-bottom: 65px
          z-index: 999
        class:
          - cell-open-button
          - card-opened-fade-out
    - component: f7-card-content
      slots:
        default:
          - component: oh-button
            config:
              iconF7: xmark_circle_fill
              iconSize: 25px
              color: black
              style:
                position: absolute
                top: 0
                right: 0
                padding-top: 30px
                padding-bottom: 65px
                z-index: 999
              class:
                - card-opened-fade-in
                - cell-close-button
                - card-close
          - component: f7-block
            config:
              class:
                - no-padding
                - card-prevent-open
              style:
                margin: 0px
                height: 135px
            slots:
              default:
                - component: f7-row
                  slots:
                    default:
                      - component: f7-col
                        config:
                          style:
                            width: 30%
                        slots:
                          default:
                            - component: oh-button
                              config:
                                iconF7: lightbulb_fill
                                iconSize: 65px
                                color: white
                                iconColor: "=items[props.dimmeritem].state != '0' ? 'yellow' : 'gray'"
                                action: toggle
                                actionItem: =props.dimmeritem
                                actionCommand: ON
                                actionCommandAlt: OFF
                                class:
                                  - card-prevent-open
                                style:
                                  padding-top: 0px
                                  height: 85px
                      - component: f7-col
                        config:
                          style:
                            width: 70%
                        slots:
                          default:
                            - component: Label
                              config:
                                text: '=props.itemname ? props.itemname : "Bitte Namen eingeben."'
                                class:
                                  - card-prevent-open
                                style:
                                  padding-top: 15px
                                  padding-left: 5px
                                  font-size: 15px
                                  font-weight: 650
                            - component: Label
                              config:
                                text: "=items[props.dimmeritem].state != '0' ? 'Eingeschalten' : 'Ausgeschalten'"
                                class:
                                  - card-prevent-open
                                style:
                                  padding-left: 5px
          - component: f7-block
            config:
              class:
                - card-prevent-open
                - card-content-padding
            slots:
              default:
                - component: f7-row
                  slots:
                    default:
                      - component: f7-col
                        config:
                          style:
                            padding-left: calc(50% - 100px)
                        slots:
                          default:
                            - component: oh-slider
                              config:
                                title: Leuchtintensität
                                vertical: 1
                                label: true
                                scale: true
                                releaseOnly: true
                                item: =props.dimmeritem
                                style:
                                  width: 200px
                                  height: 400px
                                  --f7-range-bar-active-bg-color: rgba(255,204,0,255)
                                  --f7-range-bar-size: 150px
                                  --f7-range-bar-border-radius: 20px
                                  --f7-range-knob-color: transparent
                                  --f7-range-label-bg-color: white
                                  --f7-range-knob-size: 0px
                                  --f7-range-label-border-radius: 5px
                                  --f7-range-label-font-size: 25px
                                  --f7-range-label-font-weight: 400
                                  --f7-range-label-padding: 0px 2px
                                  --f7-range-label-size: 40px
                                  --f7-range-label-text-color: black

On desktops it looks like:

If the light is dimmable, it’s possible to control the light level with this little gear icon. By clicking on this gear icon, an additional popup will appear:

So far so good. Unfortunately, the popup looks on iPhones (with this little notch on top) a bit misplaced.


To mitigate this issue, I have some ideas, but I don’t know how to implement them:

  • Detect if the popup has been opened and move the content (text and icon) a little bit down
  • Don’t open the popup on smartphones in full screen (don’t know if this is even possible)

Do you have a better idea, or do you know how to implement one of my ideas into this widget?
Your help is appreciated!

This is the better way to go, but it requires reconfiguring your widget just little. You can’t really detect the card expansion if you are using the card-open-button and card-close-button f7 classes. What you can do instead is to take advantage of the fact that the card has an expandableOpened property. If this property is true, then the card is in its expanded state and if the property is false the card is collapsed.

I would use a variable, such as cardOpened, and set the expandableOpened property to that variable value:

expandableOpened: =!!vars.cardOpened

(the !! just gives slightly better null handling before the variable is used the first time).

Then just change your buttons. Remove the card-open/-close class and set the button action to modify the cardOpened variable:

action: variable
actionVariable: cardOpened
actionVariableValue: true

Set the variable value to true on the gear button and it will cause the card to open. Set it to false on the close button.

Now you have an easily accessible variable that tells you whether the card is opened or not and you can use this variable however you wish to change the styling of your content block. Here’s an example that just changes the top margin when the card is opened:

          - component: f7-block
            config:
              class:
                - no-padding
                - card-prevent-open
              style:
                margin: 0px
                margin-top: =(!!vars.cardOpened)?('25px'):('')
                height: 135px
1 Like

Great, thank you very much for your help! It’s working as expected :slight_smile:

Another quick question, maybe you have a clue for it too:
Currently, I’m setting the colour for the gear icon to black. If I don’t specify a colour, the gear icon will be displayed orange.

    - component: oh-button
      config:
        iconF7: gear
        iconSize: 25px
        color: black

The problem here is, that if I use dark mode on specific devices the gear icon is still black and therefore, not very user friendly. Is it possible to create (or use an existing variable) to check the user’s theme and set the colour of the icon accordingly? Something like “if darkmode → gear colour white, otherwise gear colour black”

There are two basic options here:

  1. There is a way for you to get the darkmode information inside a widget. The widget has a themeOptions object with a dark property. So, to make the icon color depend on the theme, you use the a ternary statement similar to the one in the post above with margin-top.
- component: oh-button
  config:
    color: =(themeOptions.dark == "dark")?('white'):('black')
  1. The widgets use many built-in css variables for their styling including one that automatically determines if text should be black (in light mode) or white (in dark mode): --f7-text-color. However, you cannot use css variables in the standard component properties, they have to be used in the style config of the component because the style property if for direct css manipulation:
- component: oh-button
  config:
    style:
      color: var(--f7-text-color)
2 Likes

Hello,

i have had the same issue than @derSchweiger and with your approach @JustinG i was able to solve it. But there is still a small problem.

I have enabled the properity “swipeToClose: true”. When I use swipe to close, the change in the margin-top properity is not undone.

When i push the close button everything works fine.

Do you may have a clue for this issue?

Thanks a lot!

If you have followed the directions above, then it is the widget variable cardOpened that determines the opened or closed state of the card AND controls the different css settings. However, when you swipe to close, there is no way for that action to change the widget variable so you close the card without resetting cardOpened and therefore you dn’t reset the css. This system is simply not compatible with swipe-to-close.