[OH3] Main UI - New „main_widget“ - development and testing [deprecated]

OK, here’s a pretty elegant solution to the wrapping menu. Using the map property of the repeater instead of the filter property we can reorder the array of menu options based on the button index. Then instead of the filter we use the flex version of the clean menu trick to keep things down to just what fits in the space. Here’s what it looks like in action:
menu_loop

Here’s the code:

uid: demo:looping_menu
props:
  parameterGroups: []
  parameters: []
tags: []
component: f7-row
config:
  style:
    display: flex
    flex-direction: row
    justify-content: space-between
    align-items: center
    flex-wrap: nowrap
    width: 100%
    height: 2em
slots:
  default:
    - component: oh-button
      config:
        action: variable
        actionVariable: buttonIndex
        actionVariableValue: =(vars.buttonIndex || 0) - 1
        iconF7: chevron_left
        style:
          flex: 0 0 auto
    - component: f7-row
      config:
        style:
          display: flex
          justify-content: center
          overflow: hidden
      slots:
        default:
          - component: oh-repeater
            config:
              for: menuButton
              in:
                - Al's Room
                - Betty's Room
                - Charlie's Room
                - Dining Room
                - Elizabeth's Room
                - Front Room
              itemTags: bedroom
              map: loop.menuButton_source[(((vars.buttonIndex || 0) % loop.menuButton_source.length) + loop.menuButton_source.length + loop.menuButton_idx) % loop.menuButton_source.length]
              fragment: true
            slots:
              default:
                - component: oh-button
                  config:
                    text: =loop.menuButton
                    style:
                      flex: 0 0 auto
                      order:
    - component: oh-button
      config:
        action: variable
        actionVariable: buttonIndex
        actionVariableValue: =(vars.buttonIndex || 0) + 1
        iconF7: chevron_right
        style:
          flex: 0 0 auto

This system has the advantage of being very responsive to the screen width with little extra work at this point as well as not running into the end of menu list issues. hmerk’s swiper version has the advantage of actually responding to scrolling (and swiping on a mobile screen).

2 Likes

Thanks @JustinG .
As I sm only trying to help with some logic issues, @Nic0205 and @Dimitris should finally decide how to move forward.
Segmented or swiper menu.
In the meantime, I will try to spend some time on displaying the cards in the middle part.
Already have something in mind ….

Masterpiece.

The ball is in your hands now @Nic0205 . From a design/UX point of view, this is exactly what i had in my mind.
@JustinG @hmerk. I’m running out of thanks…

That looks like a really really great solution !!!

I will try to integrate this in the existing code this later / this evening. If this works we will go further with this approach.

@Nic0205 What i really like from the swiper approach, is the auto-configure navbar trick with tags. Don’t know if you can work with a hybrid solution: a wrapping auto configure menu? :face_with_open_eyes_and_hand_over_mouth:

@Dimitris : Perhaps I do not understand you right. Do you mean the “auto-populating” so that the Menu is automated generated by the items with tags?

@Nic0205 Yes Sir. Please forgive the designer for missing a dev brain!

This is also possible with the segmented approach.
I am already working on the logic for automatically creating the list entrys, sow we only need fancy widgets, e.g. for the lights…

1 Like

Hey @Dimitris

I tried it for the floors. Please have a look if it works in your setup. if so I will style it “Dimitri-Style”-conform :wink:

Please note - I implemented the logic just for the floors. Rooms and Home comes next…

uid: demo:responsive_navbar2_ext
tags: []
props:
  parameterGroups: []
timestamp: Sep 4, 2022, 8:40:48 AM
component: f7-block
config:
  style:
    display: flex
    flex-direction: column
    height: calc(100vh - var(--f7-toolbar-height) - var(--f7-safe-area-bottom) - var(--f7-navbar-height) - var(--f7-safe-area-top))
    justify-content: space-between
    margin: 0
    padding: 0
    widht: 100vh
slots:
  default:
    - component: f7-block
      config:
        style:
          flex: 0 0 auto
          overflow: scroll
      slots:
        default:
          - component: f7-segmented
            config:
              style:
                flex: 1 1 auto
            slots:
              default:
                - component: oh-repeater
                  config:
                    fragment: true
                    for: baseMenu
                    sourceType: array
                    in:
                      - name: Home
                      - name: Floors
                      - name: Rooms
                    map: loop.baseMenu.name
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: variable
                          actionVariable: selectSection
                          actionVariableValue: ="SECTION" + loop.baseMenu_idx
                          large: true
                          style:
                            color: '=vars.selectSection=="SECTION" + loop.baseMenu_idx ? "black" : "#8C8C8C"'
                            font-size: 30px
                            font-weight: 200
                            text-decoration: underline
                            text-decoration-color: '=vars.selectSection=="SECTION" + loop.baseMenu_idx ? "#F8BB00" : "transparent"'
                            text-underline-offset: 4px
                          text: =loop.baseMenu


          - component: f7-row
            config:
              visible: =!!(vars.selectSection == "SECTION0")
              style:
                display: flex
                flex-direction: row
                justify-content: space-between
                align-items: center
                flex-wrap: nowrap
                width: 100%
                height: 2em
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexHome
                    actionVariableValue: =(vars.buttonIndexHome || 0) - 1
                    iconF7: chevron_left
                    style:
                      flex: 0 0 auto
                      color: "#F8BB00"
                - component: f7-row
                  config:
                    style:
                      display: flex
                      justify-content: center
                      overflow: hidden
                  slots:
                    default:
                      - component: oh-repeater
                        config:
                          fetchMetadata: semantics,uiSemantics
                          fragment: true
                          for: menuButtonHome
                          itemTags: Home
                          sourceType: itemsWithTags  
                          map: loop.menuButtonHome_source[(((vars.buttonIndexHome || 0) % loop.menuButtonHome_source.length) + loop.menuButtonHome_source.length + loop.menuButtonHome_idx) % loop.menuButtonHome_source.length]
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: variable
                                actionVariable: floor
                                actionVariableValue: =loop.menuButtonHome.name                              
                                text: =loop.menuButtonHome.name
                                style:
                                  flex: 0 0 auto
                                  color: '=vars.floor ==loop.menuButtonHome.name ? "black" : "#8C8C8C"'
                                  text-decoration: underline
                                  text-decoration-color: '=vars.floor ==loop.menuButtonHome.name ? "#F8BB00" : "transparent"'
                                  text-underline-offset: 4px
                                  order:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexHome
                    actionVariableValue: =(vars.buttonIndexHome || 0) + 1
                    iconF7: chevron_right
                    style:
                      flex: 0 0 auto
                      color: "#F8BB00"











          - component: f7-row
            config:
              visible: =!!(vars.selectSection == "SECTION1")
              style:
                display: flex
                flex-direction: row
                justify-content: space-between
                align-items: center
                flex-wrap: nowrap
                width: 100%
                height: 2em
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexFloor
                    actionVariableValue: =(vars.buttonIndexFloor || 0) - 1
                    iconF7: chevron_left
                    style:
                      flex: 0 0 auto
                      color: "#F8BB00"
                - component: f7-row
                  config:
                    style:
                      display: flex
                      justify-content: center
                      overflow: hidden
                  slots:
                    default:
                      - component: oh-repeater
                        config:
                          fetchMetadata: semantics,uiSemantics
                          fragment: true
                          for: menuButtonFloor
                          itemTags: Floor
                          sourceType: itemsWithTags  
                          map: loop.menuButtonFloor_source[(((vars.buttonIndexFloor || 0) % loop.menuButtonFloor_source.length) + loop.menuButtonFloor_source.length + loop.menuButtonFloor_idx) % loop.menuButtonFloor_source.length]
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: variable
                                actionVariable: floor
                                actionVariableValue: =loop.menuButtonFloor.name                              
                                text: =loop.menuButtonFloor.name
                                style:
                                  flex: 0 0 auto
                                  color: '=vars.floor ==loop.menuButtonFloor.name ? "black" : "#8C8C8C"'
                                  text-decoration: underline
                                  text-decoration-color: '=vars.floor ==loop.menuButtonFloor.name ? "#F8BB00" : "transparent"'
                                  text-underline-offset: 4px




                                  order:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexFloor
                    actionVariableValue: =(vars.buttonIndexFloor || 0) + 1
                    iconF7: chevron_right
                    style:
                      flex: 0 0 auto
                      color: "#F8BB00"

          - component: f7-row
            config:
              visible: =!!(vars.selectSection == "SECTION2")
              style:
                display: flex
                flex-direction: row
                justify-content: space-between
                align-items: center
                flex-wrap: nowrap
                width: 100%
                height: 2em
            slots:
              default:
                - component: oh-button
                  visible: =!!(vars.selectSection == "SECTION2")
                  config:
                    action: variable
                    actionVariable: buttonIndexRoom
                    actionVariableValue: =(vars.buttonIndexRoom || 0) - 1
                    iconF7: chevron_left
                    style:
                      flex: 0 0 auto
                      color: "#F8BB00"
                - component: f7-row
                  config:
                    style:
                      display: flex
                      justify-content: center
                      overflow: hidden
                  slots:
                    default:
                      - component: oh-repeater
                        config:
                          fetchMetadata: semantics,uiSemantics
                          fragment: true
                          for: menuButtonRoom
                          itemTags: Room
                          sourceType: itemsWithTags  
                          map: loop.menuButtonRoom_source[(((vars.buttonIndexRoom || 0) % loop.menuButtonRoom_source.length) + loop.menuButtonRoom_source.length + loop.menuButtonRoom_idx) % loop.menuButtonRoom_source.length]
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: variable
                                actionVariable: floor
                                actionVariableValue: =loop.menuButtonRoom.name                              
                                text: =loop.menuButtonRoom.name
                                style:
                                  flex: 0 0 auto
                                  color: '=vars.floor ==loop.menuButtonRoom.name ? "black" : "#8C8C8C"'
                                  text-decoration: underline
                                  text-decoration-color: '=vars.floor ==loop.menuButtonRoom.name ? "#F8BB00" : "transparent"'
                                  text-underline-offset: 4px




                                  order:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexRoom
                    actionVariableValue: =(vars.buttonIndexRoom || 0) + 1
                    iconF7: chevron_right
                    style:
                      flex: 0 0 auto
                      color: "#F8BB00"




    - component: f7-block
      config:
        style:
          flex: 1 1 auto
          overflow: scroll
      slots:
        default:
          - component: widget:Temp_Control
            config:
              style:
                flex: 1 1 auto
                overflow-y: auto
                position: relative
              visible: =!!(vars.selectSection + vars.selectDivision + vars.selectThing == "SECTION1DIV2Climate")
              widgettrend: HeizungWohnzimmer_Temperature
          - component: widget:Temp_Control
            config:
              style:
                flex: 1 1 auto
                overflow-y: auto
                position: relative
              visible: =!!(vars.selectSection + vars.selectDivision + vars.selectThing == "SECTION2DIV2Climate")
              widgettrend: HeizungWohnzimmer_Temperature
          - component: widget:Temp_Control
            config:
              style:
                flex: 1 1 auto
                overflow-y: auto
                position: relative
              visible: =!!(vars.selectSection + vars.selectDivision + vars.selectThing == "SECTION2DIV2Climate")
              widgettrend: HeizungWohnzimmer_Temperature
          - component: widget:Temp_Control
            config:
              style:
                flex: 1 1 auto
                overflow-y: auto
                position: relative
              visible: =!!(vars.selectSection + vars.selectDivision + vars.selectThing == "SECTION2DIV2Climate")
              widgettrend: HeizungWohnzimmer_Temperature
          - component: widget:Temp_Control
            config:
              style:
                flex: 1 1 auto
                overflow-y: auto
                position: relative
              visible: =!!(vars.selectSection + vars.selectDivision + vars.selectThing == "SECTION2DIV2Climate")
              widgettrend: HeizungWohnzimmer_Temperature
          - component: oh-cell
            config:
              icon: f7:lightbulb
              style:
                flex: 1 1 auto
                overflow-y: auto
                position: relative
              subtitle: only for testing
              title: I am a light card in the Bedroom
              visible: =!!(vars.selectSection + vars.selectDivision + vars.selectThing == "SECTION2DIV2Lights")
          - component: oh-cell
            config:
              icon: f7:lightbulb
              style:
                flex: 1 1 auto
                overflow-y: auto
                position: relative
              subtitle: only for testing
              title: I am a light card in the Home
              visible: =!!(vars.selectSection == "SECTION1")
          - component: Label
            config:
              style:
                flex: 1 1 auto
                overflow-y: auto
                position: relative
              text: =vars.selectSection + vars.floor

    - component: f7-block
      config:
        style:
          flex: 0 0 auto
          overflow: scroll
      slots:
        default:
          - component: f7-segmented
            config:
              class:
                - segmented-strong
              style:
                --f7-segmented-strong-between-buttons: 0px
                --f7-segmented-strong-bg-color: transparent
                --f7-segmented-strong-button-font-weight: 300
                --f7-segmented-strong-button-hover-bg-color: rgba(255, 255, 255, 0.15)
                --f7-segmented-strong-padding: 0px
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: selectThing
                    actionVariableValue: Lights
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.selectThing=="Lights" ? true : false'
                    icon-f7: lightbulb
                    iconColor: black
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.selectThing=="Lights" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.selectThing=="Lights" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.selectThing=="Lights" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Lights
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: selectThing
                    actionVariableValue: Climate
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.selectThing=="Climate" ? true : false'
                    icon-f7: snow
                    iconColor: black
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.selectThing=="Climate" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.selectThing=="Climate" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.selectThing=="Climate" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Climate
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: selectThing
                    actionVariableValue: Rollers
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.selectThing=="Rollers" ? true : false'
                    icon-f7: archivebox
                    iconColor: black
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.selectThing=="Rollers" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.selectThing=="Rollers" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.selectThing=="Rollers" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Rollers
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: selectThing
                    actionVariableValue: Security
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.selectThing=="Security" ? true : false'
                    icon-f7: camera
                    iconColor: black
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.selectThing=="Security" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.selectThing=="Security" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.selectThing=="Security" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Security

                

        
           # config:
            #  visible: =!!(vars.selectSection == "SECTION1")



1 Like

Yeap. It works for me -in a form of endless scrolling

That sound pretty cool. I am curious to see your logic.
It’s great to see how this project grows :slight_smile:

@Dimitris - I update the code above with your Design and now for all the categories (home, floors, rooms).

1 Like

@JustinG I combined your code with the rest of our project - works like a charm :wink: .

And as usual: Another question…

Is it possible to set two variables at the same time within the actionVariable part of the oh-button?

No, that‘s not possible.

cc @Dimitris
I have a question regarding the page content.
Should the room selection show all equipment in a room ? And pressing the Lights button filters the result to only show the lights? Or should it show all lights in the house ignoring the room selection?
Same for other equipments.

It’s not possible to set two different variables, but you can set a variable to an object with as many different keys as you’d like:

- component: oh-button
  config:
    action: variable
    actionVariable: objVar
    actionVariableValue:
      animalHeight: 16 ft.
      animalName: Giraffe
    text: Object button

Then you can access the different keys just as you would any other object. For example: vars.objVar.animalName

I am not Dimitris and not as good in UX as him but I would prefer that the room selection shows the content of the room (perhaps grouped by type) and when pressing lights then only the lights are shown.

For future perhaps we can create something like a favorite collection for the rooms-overview page. but one thin after the next… :wink:

That’s pretty cool and could help much! Thank you!

Indeed, very helpfull, did not know that.

@Nic0205 We should move all actionVariableValues into an object, could make the content filtering easier.
BTW, would be good if you can publish your latest code on github.

That’s exactly what I had in mind. But will be still a hard way to get all work - but it’s fun to see it grow… and to see oneself learning so much…

Just published the actual state of the code on GitHub:

1 Like

Hmmm. That was a really good question: Tabs is same for floors and rooms. So, if you are in a floor or a room, filters in the same way.
I understand, what if you want to filter grouped equipment ie lights in all floors (ie house)? Yes, there is a design gap here… Let me think (i have not design yet the Tabs for Home menu :face_with_hand_over_mouth:…)