# Small Navigation

Compact navigation for related equipment screens.

## Installation

Download: /api/catalog/small-navigation/download

Ignition Perspective 8.3. In a development project, choose Designer > File > Import and select the ZIP. Preserve the view and style-class paths. Review resource conflicts before replacing anything.

No separate stylesheet snippet is included.

Add an Embedded View (ia.display.view), set props.path to Nav/SmallNav, and configure props.params using the contract below. Connect your own data in the host view. The package does not include live tags, page configuration or Gateway settings.

## Parameters

Types are inferred from saved defaults; directions come from native propConfig. These are not full schemas or validated ranges.

| Parameter | Type | Direction | Default |

| --- | --- | --- | --- |

| item0Label | string | input | "Overview" |

| item1Label | string | input | "Analytics" |

| item2Label | string | input | "Reports" |

| item3Label | string | input | "Settings" |

| activeIndex | number | inout | 0 |

| orientation | string | input | "horizontal" |

| onSelectMessage | string | input | "viewcraft.smallnav.select" |

| instanceId | string | input | "" |

| selectedIndex | number | output | 0 |

| selectedLabel | string | output | "Overview" |

## Embedded View usage

```json

{
  "type": "ia.display.view",
  "props": {
    "path": "Nav/SmallNav",
    "params": {
      "item0Label": "Overview",
      "item1Label": "Analytics",
      "item2Label": "Reports",
      "item3Label": "Settings",
      "activeIndex": 0,
      "orientation": "horizontal",
      "onSelectMessage": "viewcraft.smallnav.select",
      "instanceId": ""
    },
    "useDefaultViewWidth": false,
    "useDefaultViewHeight": false
  }
}

```

## Verification

Source and archive hashes are checked. Designer import acceptance has not been completed for this archive; test in your development project before production.

## Files

### com.inductiveautomation.perspective/views/Nav/SmallNav/view.json

```json

{
  "custom": {},
  "params": {
    "item0Label": "Overview",
    "item1Label": "Analytics",
    "item2Label": "Reports",
    "item3Label": "Settings",
    "activeIndex": 0,
    "orientation": "horizontal",
    "onSelectMessage": "viewcraft.smallnav.select",
    "instanceId": "",
    "selectedIndex": 0,
    "selectedLabel": "Overview"
  },
  "propConfig": {
    "params.item0Label": {
      "paramDirection": "input"
    },
    "params.item1Label": {
      "paramDirection": "input"
    },
    "params.item2Label": {
      "paramDirection": "input"
    },
    "params.item3Label": {
      "paramDirection": "input"
    },
    "params.activeIndex": {
      "paramDirection": "inout"
    },
    "params.orientation": {
      "paramDirection": "input"
    },
    "params.onSelectMessage": {
      "paramDirection": "input"
    },
    "params.instanceId": {
      "paramDirection": "input"
    },
    "params.selectedIndex": {
      "paramDirection": "output",
      "binding": {
        "type": "expr",
        "config": {
          "expression": "{view.params.activeIndex}"
        }
      }
    },
    "params.selectedLabel": {
      "paramDirection": "output",
      "binding": {
        "type": "expr",
        "config": {
          "expression": "if({view.params.activeIndex}=0,{view.params.item0Label},if({view.params.activeIndex}=1,{view.params.item1Label},if({view.params.activeIndex}=2,{view.params.item2Label},{view.params.item3Label})))"
        }
      }
    }
  },
  "props": {
    "defaultSize": {
      "width": 420,
      "height": 40
    }
  },
  "root": {
    "type": "ia.container.flex",
    "version": 0,
    "meta": {
      "name": "Tabs"
    },
    "props": {
      "direction": "row",
      "style": {
        "classes": "vc2-tabs"
      }
    },
    "position": {
      "grow": 0,
      "shrink": 0,
      "basis": "auto"
    },
    "children": [
      {
        "type": "ia.input.button",
        "version": 0,
        "meta": {
          "name": "Tab0"
        },
        "props": {
          "text": "Overview",
          "style": {
            "classes": "vc2-tab"
          }
        },
        "position": {
          "grow": 1,
          "shrink": 1,
          "basis": "0px"
        },
        "events": {
          "component": {
            "onActionPerformed": {
              "type": "script",
              "scope": "G",
              "config": {
                "script": "\tlabels = [str(self.view.params[\"item\" + str(j) + \"Label\"]) for j in range(4)]\n\tindex = 0\n\tself.view.params.activeIndex = index\n\tif self.view.params.onSelectMessage:\n\t\tsystem.perspective.sendMessage(str(self.view.params.onSelectMessage), {\"index\":index,\"label\":labels[index],\"selectedIndex\":index,\"selectedLabel\":labels[index],\"instanceId\":str(self.view.params.instanceId)}, scope=\"page\")\n"
              }
            }
          },
          "dom": {
            "onKeyDown": {
              "type": "script",
              "scope": "G",
              "config": {
                "script": "\tlabels = [str(self.view.params[\"item\" + str(j) + \"Label\"]) for j in range(4)]\n\tkey = str(event.key)\n\tallowed = [\"ArrowUp\",\"ArrowDown\"] if self.view.params.orientation == \"vertical\" else [\"ArrowLeft\",\"ArrowRight\"]\n\tif key not in allowed + [\"Home\",\"End\"]:\n\t\treturn\n\tvisible = [j for j in range(4) if labels[j].strip()]\n\tif not visible:\n\t\treturn\n\tindex = visible[0] if key == \"Home\" else (visible[-1] if key == \"End\" else visible[(visible.index(0) + (-1 if key in [\"ArrowLeft\",\"ArrowUp\"] else 1)) % len(visible)])\n\tself.view.params.activeIndex = index\n\tif self.view.params.onSelectMessage:\n\t\tsystem.perspective.sendMessage(str(self.view.params.onSelectMessage), {\"index\":index,\"label\":labels[index],\"selectedIndex\":index,\"selectedLabel\":labels[index],\"instanceId\":str(self.view.params.instanceId)}, scope=\"page\")\n\tself.getSibling(\"Tab\" + str(index)).focus()\n"
              }
            }
          }
        },
        "propConfig": {
          "props.text": {
            "binding": {
              "type": "property",
              "config": {
                "path": "view.params.item0Label"
              }
            }
          },
          "props.style.classes": {
            "binding": {
              "type": "expr",
              "config": {
                "expression": "\"vc2-tab\" + if(trim({view.params.item0Label}) = \"\", \" vc2-hidden\", \"\") + if({view.params.activeIndex} = 0, \" vc2-tab-active\", \"\")"
              }
            }
          },
          "meta.tabIndex": {
            "binding": {
              "type": "expr",
              "config": {
                "expression": "if({view.params.activeIndex}=0,0,-1)"
              }
            }
          }
        }
      },
      {
        "type": "ia.input.button",
        "version": 0,
        "meta": {
          "name": "Tab1"
        },
        "props": {
          "text": "Analytics",
          "style": {
            "classes": "vc2-tab"
          }
        },
        "position": {
          "grow": 1,
          "shrink": 1,
          "basis": "0px"
        },
        "events": {
          "component": {
            "onActionPerformed": {
              "type": "script",
              "scope": "G",
              "config": {
                "script": "\tlabels = [str(self.view.params[\"item\" + str(j) + \"Label\"]) for j in range(4)]\n\tindex = 1\n\tself.view.params.activeIndex = index\n\tif self.view.params.onSelectMessage:\n\t\tsystem.perspective.sendMessage(str(self.view.params.onSelectMessage), {\"index\":index,\"label\":labels[index],\"selectedIndex\":index,\"selectedLabel\":labels[index],\"instanceId\":str(self.view.params.instanceId)}, scope=\"page\")\n"
              }
            }
          },
          "dom": {
            "onKeyDown": {
              "type": "script",
              "scope": "G",
              "config": {
                "script": "\tlabels = [str(self.view.params[\"item\" + str(j) + \"Label\"]) for j in range(4)]\n\tkey = str(event.key)\n\tallowed = [\"ArrowUp\",\"ArrowDown\"] if self.view.params.orientation == \"vertical\" else [\"ArrowLeft\",\"ArrowRight\"]\n\tif key not in allowed + [\"Home\",\"End\"]:\n\t\treturn\n\tvisible = [j for j in range(4) if labels[j].strip()]\n\tif not visible:\n\t\treturn\n\tindex = visible[0] if key == \"Home\" else (visible[-1] if key == \"End\" else visible[(visible.index(1) + (-1 if key in [\"ArrowLeft\",\"ArrowUp\"] else 1)) % len(visible)])\n\tself.view.params.activeIndex = index\n\tif self.view.params.onSelectMessage:\n\t\tsystem.perspective.sendMessage(str(self.view.params.onSelectMessage), {\"index\":index,\"label\":labels[index],\"selectedIndex\":index,\"selectedLabel\":labels[index],\"instanceId\":str(self.view.params.instanceId)}, scope=\"page\")\n\tself.getSibling(\"Tab\" + str(index)).focus()\n"
              }
            }
          }
        },
        "propConfig": {
          "props.text": {
            "binding": {
              "type": "property",
              "config": {
                "path": "view.params.item1Label"
              }
            }
          },
          "props.style.classes": {
            "binding": {
              "type": "expr",
              "config": {
                "expression": "\"vc2-tab\" + if(trim({view.params.item1Label}) = \"\", \" vc2-hidden\", \"\") + if({view.params.activeIndex} = 1, \" vc2-tab-active\", \"\")"
              }
            }
          },
          "meta.tabIndex": {
            "binding": {
              "type": "expr",
              "config": {
                "expression": "if({view.params.activeIndex}=1,0,-1)"
              }
            }
          }
        }
      },
      {
        "type": "ia.input.button",
        "version": 0,
        "meta": {
          "name": "Tab2"
        },
        "props": {
          "text": "Reports",
          "style": {
            "classes": "vc2-tab"
          }
        },
        "position": {
          "grow": 1,
          "shrink": 1,
          "basis": "0px"
        },
        "events": {
          "component": {
            "onActionPerformed": {
              "type": "script",
              "scope": "G",
              "config": {
                "script": "\tlabels = [str(self.view.params[\"item\" + str(j) + \"Label\"]) for j in range(4)]\n\tindex = 2\n\tself.view.params.activeIndex = index\n\tif self.view.params.onSelectMessage:\n\t\tsystem.perspective.sendMessage(str(self.view.params.onSelectMessage), {\"index\":index,\"label\":labels[index],\"selectedIndex\":index,\"selectedLabel\":labels[index],\"instanceId\":str(self.view.params.instanceId)}, scope=\"page\")\n"
              }
            }
          },
          "dom": {
            "onKeyDown": {
              "type": "script",
              "scope": "G",
              "config": {
                "script": "\tlabels = [str(self.view.params[\"item\" + str(j) + \"Label\"]) for j in range(4)]\n\tkey = str(event.key)\n\tallowed = [\"ArrowUp\",\"ArrowDown\"] if self.view.params.orientation == \"vertical\" else [\"ArrowLeft\",\"ArrowRight\"]\n\tif key not in allowed + [\"Home\",\"End\"]:\n\t\treturn\n\tvisible = [j for j in range(4) if labels[j].strip()]\n\tif not visible:\n\t\treturn\n\tindex = visible[0] if key == \"Home\" else (visible[-1] if key == \"End\" else visible[(visible.index(2) + (-1 if key in [\"ArrowLeft\",\"ArrowUp\"] else 1)) % len(visible)])\n\tself.view.params.activeIndex = index\n\tif self.view.params.onSelectMessage:\n\t\tsystem.perspective.sendMessage(str(self.view.params.onSelectMessage), {\"index\":index,\"label\":labels[index],\"selectedIndex\":index,\"selectedLabel\":labels[index],\"instanceId\":str(self.view.params.instanceId)}, scope=\"page\")\n\tself.getSibling(\"Tab\" + str(index)).focus()\n"
              }
            }
          }
        },
        "propConfig": {
          "props.text": {
            "binding": {
              "type": "property",
              "config": {
                "path": "view.params.item2Label"
              }
            }
          },
          "props.style.classes": {
            "binding": {
              "type": "expr",
              "config": {
                "expression": "\"vc2-tab\" + if(trim({view.params.item2Label}) = \"\", \" vc2-hidden\", \"\") + if({view.params.activeIndex} = 2, \" vc2-tab-active\", \"\")"
              }
            }
          },
          "meta.tabIndex": {
            "binding": {
              "type": "expr",
              "config": {
                "expression": "if({view.params.activeIndex}=2,0,-1)"
              }
            }
          }
        }
      },
      {
        "type": "ia.input.button",
        "version": 0,
        "meta": {
          "name": "Tab3"
        },
        "props": {
          "text": "Settings",
          "style": {
            "classes": "vc2-tab"
          }
        },
        "position": {
          "grow": 1,
          "shrink": 1,
          "basis": "0px"
        },
        "events": {
          "component": {
            "onActionPerformed": {
              "type": "script",
              "scope": "G",
              "config": {
                "script": "\tlabels = [str(self.view.params[\"item\" + str(j) + \"Label\"]) for j in range(4)]\n\tindex = 3\n\tself.view.params.activeIndex = index\n\tif self.view.params.onSelectMessage:\n\t\tsystem.perspective.sendMessage(str(self.view.params.onSelectMessage), {\"index\":index,\"label\":labels[index],\"selectedIndex\":index,\"selectedLabel\":labels[index],\"instanceId\":str(self.view.params.instanceId)}, scope=\"page\")\n"
              }
            }
          },
          "dom": {
            "onKeyDown": {
              "type": "script",
              "scope": "G",
              "config": {
                "script": "\tlabels = [str(self.view.params[\"item\" + str(j) + \"Label\"]) for j in range(4)]\n\tkey = str(event.key)\n\tallowed = [\"ArrowUp\",\"ArrowDown\"] if self.view.params.orientation == \"vertical\" else [\"ArrowLeft\",\"ArrowRight\"]\n\tif key not in allowed + [\"Home\",\"End\"]:\n\t\treturn\n\tvisible = [j for j in range(4) if labels[j].strip()]\n\tif not visible:\n\t\treturn\n\tindex = visible[0] if key == \"Home\" else (visible[-1] if key == \"End\" else visible[(visible.index(3) + (-1 if key in [\"ArrowLeft\",\"ArrowUp\"] else 1)) % len(visible)])\n\tself.view.params.activeIndex = index\n\tif self.view.params.onSelectMessage:\n\t\tsystem.perspective.sendMessage(str(self.view.params.onSelectMessage), {\"index\":index,\"label\":labels[index],\"selectedIndex\":index,\"selectedLabel\":labels[index],\"instanceId\":str(self.view.params.instanceId)}, scope=\"page\")\n\tself.getSibling(\"Tab\" + str(index)).focus()\n"
              }
            }
          }
        },
        "propConfig": {
          "props.text": {
            "binding": {
              "type": "property",
              "config": {
                "path": "view.params.item3Label"
              }
            }
          },
          "props.style.classes": {
            "binding": {
              "type": "expr",
              "config": {
                "expression": "\"vc2-tab\" + if(trim({view.params.item3Label}) = \"\", \" vc2-hidden\", \"\") + if({view.params.activeIndex} = 3, \" vc2-tab-active\", \"\")"
              }
            }
          },
          "meta.tabIndex": {
            "binding": {
              "type": "expr",
              "config": {
                "expression": "if({view.params.activeIndex}=3,0,-1)"
              }
            }
          }
        }
      }
    ],
    "propConfig": {
      "props.direction": {
        "binding": {
          "type": "expr",
          "config": {
            "expression": "if({view.params.orientation}=\"vertical\",\"column\",\"row\")"
          }
        }
      },
      "props.style.classes": {
        "binding": {
          "type": "expr",
          "config": {
            "expression": "\"vc2-tabs\" + if({view.params.orientation}=\"vertical\",\" vc2-tabs-vertical\",\"\")"
          }
        }
      }
    }
  }
}


```

### com.inductiveautomation.perspective/views/Nav/SmallNav/resource.json

```json

{
  "scope": "G",
  "version": 1,
  "restricted": false,
  "overridable": true,
  "files": [
    "view.json"
  ]
}

```