Enable dynamic tilesets that can be used across dashboards

I have a row that I want to include at the bottom of all my dashboards that includes icons for each dashboard and the forward and back navigation arrows. Maintaining this across all dashboards is already becoming cumbersome and I would love a way to be able to share it across dashboards in a way that editing it would affect how it displays on all dashboards dynamically.

It seems like a common use case for this is to have a navigation menu across dashboards. I don’t have the idea fully fleshed out in my head, but some sort of concept where you could add a ‘navigation’ to your dashboard where you could choose to have the menu on the top, left, bottom, etc… some basic options around styling the menu and options for choosing which items show in the menu. Then you could edit that menu one place and have it flow through to your dashboards.

4 Likes

This would be a great idea to combine with the ability to choose the type of transition/display animation of the dashboard, which I posted earlier.

Global navigation functionality should be an area of focus, IMO.

3 Likes

I concur. As my system has grown and capabilities increase, I find multiple dashboards for a tablet is better than scrolling. This allows me to have a “main” dashboard with a really nice looking, uncluttered layout that gives me weather, radar, album art from my music, clock, and a couple of basic things. On the left, I have links to “sub” dashboards for lighting, security, etc. Those are very functional, but kind of cluttered an not nice to look at. I have the tablet reload the “main” after 30 seconds of not being touched. It is awesome and I love everything about it, except the animation where the tiles “fly” into position from the top left every time the dashboard switches. Getting rid of this animation so that it just flashes from one to the next would be ideal.

2 Likes

I agree - I would prefer if the animation between dashboards wasn’t there.

I think one way to possibly think about this is if one dashboard can be included as a “tile” inside another dashboard. Then if the user has a standard 1x7 strip of tiles they like on all their dashboards, they just include an “embedded dashboard” tile that points to it, and set its dimensions to 1x7 in each of their main dashboards.

What would be really cool is if the user set the size of this embedded dashboard tile in a given dashboard to only be (say) 1x4, then you could scroll within the embedded dashboard to see the other elements. I imagine a media selection dashboard that consists of a tall 1-wide strip of dozens of radio stations, albums, etc. that is then embedded or the right side of a media player dashboard that lets me scroll among options in the selection sub-dashboard along the right hand side without scrolling the media player controls or the like in the including dashboard.

2 Likes

We need this ASAP, can we get this feature? It’s icing on the cake in terms of menu reuse across dashboards. Cuts out so much maintenance when changing your parent menu. Please!

1 Like

I am building out dashboards right now and it is tedious because of the number of devices and detail I have. I would really like to have this added.

Hey @Tom_Prendergast - thanks for the update. Is the main use-case here still a navigation bar that you’d like to have shared across dashboards?

2 Likes

@josh yes! I may find other ways to leverage it too but that is the main thing I have in mind at the moment

I think @Ben_Iffland started playing with the concept of using a Custom Tile to create a special navigation bar. Not sure if anything came of that?

Yeah I did get something working using a custom tile with HTML etc. It does what I want but user experience could be better as the custom tiles don’t load as fast as standard ones. This is the code:

<!-- Do not edit below -->
<script type="application/json" id="tile-settings">
{
  "schema": "0.1.0",
  "settings": [
    {"name": "defaultTile", "label": "Default Tile", "type": "STRING"}
  ],
  "name": "Navigation Menu",
  "dimensions": {"width": 1, "height": 3}
}
</script>
<script src="https://cdn.sharptools.io/js/custom-tiles.js"></script>
<style>
  body {
    background-color: black;
    border-style: none;
    margin-top: 0px;
    margin: 0px;
  }
  .nav-container {
    display: flex;
    flex-direction: column;
    align-items:center;
    overflow: hidden;
    overflow-y: scroll;
    padding-right: 17px;
    box-sizing: content-box;
    width: 100%;
    height: 100%;
    background-color:black;
  }

   nav-container:hover{background-color:orange;}

   nav-container:focus{background-color:red;}
  
  .tile {   
    display: flex;
    align-items: center;
    top: 0;
    position: relative;
    width: 100px;
    height: 100px;
    min-height:80px;
    margin-bottom: 4px;    
    padding: 1em;
    -o-user-select: none;
    -khtml-user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    flex:1;
    color: white;
    background-color: black;
    text-align:center;
    flex-direction: column;
    cursor: pointer;
  }
  
.tile:active {
    opacity: 0.9;
    background: gray;
    color: white;
    width: 100%;
}
  
  .tile > svg {
    width:62px;
    height:62px;
    margin-top: 6px;
  }
  
  .bulb{
    position: relative;
    left: 9px;
  }
  
  .title{
    font-size: 1em;
    display:block;
  }

  .selected{
    opacity: 0.9;
    background: gray;
    color: white;
    width: 100%;
  }
</style>

<div class="nav-container">
  <div id="YBDCwfRLYEcCfJsHYsRz" class="tile" onclick="openDashboard(this)"> 
   <div class="title">Home</div>
   <svg data-v-3037d865="" data-v-38b58a7b="" aria-hidden="true" focusable="false" data-prefix="fa" data-icon="home" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="fa-4x fa-fw svg-inline--fa fa-home fa-w-18"><path data-v-3037d865="" data-v-38b58a7b="" fill="currentColor" d="M280.37 148.26L96 300.11V464a16 16 0 0 0 16 16l112.06-.29a16 16 0 0 0 15.92-16V368a16 16 0 0 1 16-16h64a16 16 0 0 1 16 16v95.64a16 16 0 0 0 16 16.05L464 480a16 16 0 0 0 16-16V300L295.67 148.26a12.19 12.19 0 0 0-15.3 0zM571.6 251.47L488 182.56V44.05a12 12 0 0 0-12-12h-56a12 12 0 0 0-12 12v72.61L318.47 43a48 48 0 0 0-61 0L4.34 251.47a12 12 0 0 0-1.6 16.9l25.5 31A12 12 0 0 0 45.15 301l235.22-193.74a12.19 12.19 0 0 1 15.3 0L530.9 301a12 12 0 0 0 16.9-1.6l25.5-31a12 12 0 0 0-1.7-16.93z" class=""></path></svg>
  </div>
  <div id="C0VRMKFnL8K0l5Q8rrzp" class="tile" onclick="openDashboard(this)"> 
    <div class="title">Lounge</div>
    <svg data-v-3037d865="" data-v-38b58a7b="" aria-hidden="true" focusable="false" data-prefix="fa" data-icon="couch" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 676 512" class="fa-4x fa-fw svg-inline--fa fa-couch fa-w-20"><path data-v-3037d865="" data-v-38b58a7b="" fill="currentColor" d="M160 224v64h320v-64c0-35.3 28.7-64 64-64h32c0-53-43-96-96-96H160c-53 0-96 43-96 96h32c35.3 0 64 28.7 64 64zm416-32h-32c-17.7 0-32 14.3-32 32v96H128v-96c0-17.7-14.3-32-32-32H64c-35.3 0-64 28.7-64 64 0 23.6 13 44 32 55.1V432c0 8.8 7.2 16 16 16h64c8.8 0 16-7.2 16-16v-16h384v16c0 8.8 7.2 16 16 16h64c8.8 0 16-7.2 16-16V311.1c19-11.1 32-31.5 32-55.1 0-35.3-28.7-64-64-64z" class=""></path></svg>
  </div> 
  <div id="MoRLVBgWtaM6QZzqK0Gz" class="tile" onclick="openDashboard(this)">
    <div class="title">Vacuum</div>
    <svg data-v-3037d865="" data-v-38b58a7b="" aria-hidden="true" focusable="false" data-prefix="stio" data-icon="vacuum" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="fa-4x fa-fw svg-inline--fa fa-vacuum fa-w-16"><path data-v-3037d865="" data-v-38b58a7b="" fill="currentColor" d="M472 458c-12 0-24-9-26-22-7-31-31-42-70-42l-91 1c-2 0-4-1-5-3L156 21c-4-12-15-20-28-20H42C31 1 22 9 22 21v2c0 11 9 20 20 20h61c10 0 18 6 21 15l122 368c3 8 2 16-1 23a161980 161980 0 0 1-10 25v18c0 11 9 20 20 20h215c11 0 20-9 20-20v-16c0-10-8-18-18-18zM286 339c3 8 10 13 19 13h48a20 20 0 0 0 20-25l-50-160c-9-28-45-59-80-77a21 21 0 0 0-30 25l73 224z" class=""></path></svg>
  </div> 
  <div id="hTourpDgs5nlPpu1mf3v" class="tile" onclick="openDashboard(this)">
    <div class="title">Lights</div>
    <svg class="bulb" data-v-3037d865="" data-v-38b58a7b="" aria-hidden="true" focusable="false" data-prefix="fa" data-icon="lightbulb" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path data-v-3037d865="" data-v-38b58a7b="" fill="currentColor" d="M96.06 454.35c.01 6.29 1.87 12.45 5.36 17.69l17.09 25.69a31.99 31.99 0 0 0 26.64 14.28h61.71a31.99 31.99 0 0 0 26.64-14.28l17.09-25.69a31.989 31.989 0 0 0 5.36-17.69l.04-38.35H96.01l.05 38.35zM0 176c0 44.37 16.45 84.85 43.56 115.78 16.52 18.85 42.36 58.23 52.21 91.45.04.26.07.52.11.78h160.24c.04-.26.07-.51.11-.78 9.85-33.22 35.69-72.6 52.21-91.45C335.55 260.85 352 220.37 352 176 352 78.61 272.91-.3 175.45 0 73.44.31 0 82.97 0 176zm176-80c-44.11 0-80 35.89-80 80 0 8.84-7.16 16-16 16s-16-7.16-16-16c0-61.76 50.24-112 112-112 8.84 0 16 7.16 16 16s-7.16 16-16 16z" class=""></path></svg>
  </div>  
  <div id="xp05Oj8vTCLz6DQqU930" class="tile" onclick="openDashboard(this)">
    <div class="title">Blinds</div>
    <svg data-v-3037d865="" data-v-38b58a7b="" aria-hidden="true" focusable="false" data-prefix="fa" data-icon="blinds" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="fa-4x fa-fw svg-inline--fa fa-blinds fa-w-16"><path data-v-3037d865="" data-v-38b58a7b="" fill="currentColor" d="M96,226.94V160H16L0,256H66.94A47.82,47.82,0,0,1,96,226.94ZM157.06,288a47.73,47.73,0,0,1-90.12,0H16L0,384H512l-16-96ZM16,416,0,512H512l-16-96ZM512,48V16A16,16,0,0,0,496,0H16A16,16,0,0,0,0,16V48A15.85,15.85,0,0,0,10.84,63L0,128H96V64h32v64H512L501.16,63A15.85,15.85,0,0,0,512,48ZM128,160v66.94A47.82,47.82,0,0,1,157.06,256H512l-16-96Z" class=""></path></svg>
  </div>   
  <div id="v9MDq9XjjMsCEVbiq223" class="tile" onclick="openDashboard(this)">
    <div class="title">Music</div>
    <svg data-v-3037d865="" data-v-38b58a7b="" aria-hidden="true" focusable="false" data-prefix="fa" data-icon="headphones" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="fa-4x fa-fw svg-inline--fa fa-headphones fa-w-16"><path data-v-3037d865="" data-v-38b58a7b="" fill="currentColor" d="M256 32C114.52 32 0 146.496 0 288v48a32 32 0 0 0 17.689 28.622l14.383 7.191C34.083 431.903 83.421 480 144 480h24c13.255 0 24-10.745 24-24V280c0-13.255-10.745-24-24-24h-24c-31.342 0-59.671 12.879-80 33.627V288c0-105.869 86.131-192 192-192s192 86.131 192 192v1.627C427.671 268.879 399.342 256 368 256h-24c-13.255 0-24 10.745-24 24v176c0 13.255 10.745 24 24 24h24c60.579 0 109.917-48.098 111.928-108.187l14.382-7.191A32 32 0 0 0 512 336v-48c0-141.479-114.496-256-256-256z" class=""></path></svg>
  </div>
  <div id="PZbEXTADiA6tVuLSloyF" class="tile" onclick="openDashboard(this)">
    <div class="title">Cameras</div>
    <svg data-v-3037d865="" data-v-38b58a7b="" aria-hidden="true" focusable="false" data-prefix="stio" data-icon="security-camera" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="fa-4x fa-fw svg-inline--fa fa-security-camera fa-w-16"><path data-v-3037d865="" data-v-38b58a7b="" fill="currentColor" d="M395.928,187.794l-272.1-135.687c-5.358-2.669-11.866-0.494-14.538,4.864L51.24,173.379    c-1.283,2.573-1.491,5.55-0.579,8.276c0.912,2.727,2.869,4.979,5.443,6.262l81.242,40.511l-7.208,14.455    c-2.671,5.358-0.494,11.866,4.864,14.538l2.561,1.278l-13.998,24.929H41.027C33.351,268.782,17.867,258.626,0,258.626v92.338    c17.454,0,32.642-9.688,40.49-23.978h95.766c7.838,0,15.065-4.229,18.903-11.063l21.255-37.85l3.695,1.842    c5.357,2.671,11.867,0.493,14.539-4.863l7.208-14.455l60.7,30.271c3.501,1.746,7.671,1.471,10.911-0.723l16.753-11.332    l29.912,14.916c1.518,0.758,3.174,1.14,4.837,1.14c1.159,0,2.32-0.188,3.439-0.562c2.727-0.91,4.979-2.869,6.262-5.441    l30.624-61.413l31.757-20.903c3.239-2.132,5.092-5.832,4.86-9.702C401.679,192.976,399.397,189.525,395.928,187.794z" class=""></path></svg>
  </div> 
</div>

<script>
  var home = document.getElementById("YBDCwfRLYEcCfJsHYsRz"); //home
  var lounge = document.getElementById("C0VRMKFnL8K0l5Q8rrzp"); //lounge
  var vacuum = document.getElementById("MoRLVBgWtaM6QZzqK0Gz"); //vacuum
  var lights = document.getElementById("hTourpDgs5nlPpu1mf3v"); //lights
  var blinds = document.getElementById("xp05Oj8vTCLz6DQqU930"); //blinds
  var music = document.getElementById("v9MDq9XjjMsCEVbiq223"); //music
  var camera = document.getElementById("PZbEXTADiA6tVuLSloyF"); //camera

  stio.ready().then(function(data) {   
    var defaultTile = data.settings.defaultTile;
    switch (defaultTile) {
  		case 'YBDCwfRLYEcCfJsHYsRz':
    		setSelected(home);
    	break;
        case 'C0VRMKFnL8K0l5Q8rrzp':
    		setSelected(lounge);
    	break;
        case 'MoRLVBgWtaM6QZzqK0Gz':
    		setSelected(vacuum);
    	break;
        case 'hTourpDgs5nlPpu1mf3v':
    		setSelected(lights);
    	break;   
        case 'xp05Oj8vTCLz6DQqU930':
    		setSelected(blinds);
    	break;
        case 'v9MDq9XjjMsCEVbiq223':
    		setSelected(music);
    	break; 
        case 'PZbEXTADiA6tVuLSloyF':
			setSelected(camera);
    	break; 
    }
  });

  function setSelected(el) {
    el.classList.toggle("selected");
  }
  
  function openDashboard(ev) {
    window.parent.postMessage(
      {
        action:'navigate', 
        route: { path: `/dashboard/view/${ev.id}`}
      }, "*")
  }
</script>

dash

2 Likes

Thanks, Ben, for sharing. That was exactly what I had tried to do by manual methods in the past to manage navigation and it got tiring to maintain. I am not a coder, so I barely can comprehend this workaround solution. I had suggested in past a SharpTools method to ‘containerize’ several tiles to be a group which may work for the more drag and drop crowd.

4 Likes

Has there been any progress on this OOTB? I am definitely looking for a reusable navigation. I would also like to group and reuse tiles for other purposes, e.g. my temperature controls.

There’s a few options for reusable navigation. One approach is to use a Super Tile - the following blog post has an example of that:

That same approach could apply to groups of data / controls as well.

1 Like


Got it! Thank you!

1 Like