Repository navigation
fix(nav): allow out-of-bounds or unset activeIndex without throwing - #154
Conversation
🚀 Deploying Preview to Cloudflare 🚀Preview URL: https://fix-nav-bar-active-index-material.treeder.workers.dev (commit f7db644)This URL reflects your latest Preview deploymentPreview Deployments by commit
|
There was a problem hiding this comment.
📋 Review Summary
This pull request updates NavigationBar (md-nav-bar) and Rail (md-nav-rail) to support an unselected state by changing the default activeIndex from 0 to -1. It introduces a custom attribute converter to parse active-index, eliminates the runtime error thrown when activeIndex is out of bounds, and adds defensive guards and optional chaining to keyboard navigation handlers. In addition, slot change listeners are connected to trigger layout recalculation dynamically, and the documentation has been kept in sync with the new default.
🔍 General Feedback
- Removing the unhandled exception in
onActiveIndexChangewhenthis.tabs[value]is undefined is a great fix; previously, empty tab arrays or negative indices would immediately crash during component lifecycle execution. - The defensive checks and optional chaining (
?.focus()) added tohandleKeydownsignificantly improve resilience when focus is outside the tabs or when the bar contains no items. - The documentation updates in
nav/README.mdaccurately document-1as the new default for unselected states.
📊 Token Usage & Cost Efficiency
| Metric | Value |
|---|---|
| Input Tokens (uncached) | 16,466 |
| Input Tokens (cached) | 434,764 (⚡ 96.2% cached) |
| PR Comments History Tokens | 532 |
| Thinking / Reasoning Tokens | 32,385 |
| Output Tokens | 688 |
| Total Session Tokens | 484,835 |
| Cost (uncached input) | $0.0127 |
| Cost (cached input) | $0.0326 |
| Cost (thinking / reasoning) | $0.1214 |
| Cost (response output) | $0.0026 |
| Estimated Total Cost | $0.1694 |
Gemini 3.8 Flash: introductory rate $0.75/$3.75 per 1M applied; reverts to $1.5/$7.5 after 2026-12-31.
Gemini 3.8 Flash: standard tier; batch and flex are half again, priority is higher.
Cache reads are priced here, but context-cache STORAGE, where the model charges for it separately per token-hour, is not included, so the figure can run slightly low.
There was a problem hiding this comment.
📋 Review Summary
This pull request refactors and fixes active index handling in <md-nav-bar> and <md-nav-rail>. It introduces a default activeIndex of -1 (indicating no active selection) with a custom attribute converter, safeguards navigation event dispatching, and removes the out-of-bounds error throw in onActiveIndexChange. In addition, child tab management is streamlined across <md-nav-bar> and <md-nav-rail> with slotchange listeners and shared reactive property definitions, and documentation tables in nav/README.md have been updated accordingly.
✅ Resolved Items from Prior Reviews
- Converted
tabsinNavigationBar.propertiesto internal reactive state (state: true) and cleaned up redundant property re-declarations inRailto prevent exposingtabsas an observed HTML attribute. (nav/bar.js:20) - Added a guard (
this.activeIndex >= 0 && this.tabs[this.activeIndex]) to thenavigation-bar-activatedevent dispatch inupdated()so it only fires when an active destination item exists. (nav/bar.js:24)
🔍 General Feedback
- Defaulting
activeIndexto-1and usingactiveIndexConverterprovides a clean way to represent an unselected state across navigation bars and rails. - Removing the out-of-bounds
Errorthrow inonActiveIndexChangeprevents runtime crashes when tabs are dynamically populated or cleared. - Spreading
...NavigationBar.propertiesinRailnicely eliminates property duplication while keeping reactive configurations in sync.
📊 Token Usage & Cost Efficiency
| Metric | Value |
|---|---|
| Input Tokens (uncached) | 16,849 |
| Input Tokens (cached) | 434,764 (⚡ 96.1% cached) |
| PR Comments History Tokens | 978 |
| Thinking / Reasoning Tokens | 22,564 |
| Output Tokens | 406 |
| Total Session Tokens | 475,561 |
| Cost (uncached input) | $0.0134 |
| Cost (cached input) | $0.0326 |
| Cost (thinking / reasoning) | $0.0846 |
| Cost (response output) | $0.0015 |
| Estimated Total Cost | $0.1321 |
Gemini 3.8 Flash: introductory rate $0.75/$3.75 per 1M applied; reverts to $1.5/$7.5 after 2026-12-31.
Gemini 3.8 Flash: standard tier; batch and flex are half again, priority is higher.
Cache reads are priced here, but context-cache STORAGE, where the model charges for it separately per token-hour, is not included, so the figure can run slightly low.
Summary
Fixes
Uncaught (in promise) Error: NavigationBar: activeIndex is out of bounds.whenmd-nav-barormd-nav-railhas no active tab (e.g.,active-index="-1"or an empty/unsetactive-indexattribute) or updates before slotted tab items are populated.Key Changes
NavigationBar.onActiveIndexChangeso that out-of-bounds or negativeactiveIndexvalues cleanly mark all tabs inactive.activeIndexto-1and add an attribute converter so empty/missing/non-numericactive-indexvalues (such asactive-index=""when interpolatingundefined) resolve to-1instead of0orNaN.tabstoNavigationBar.propertiesand attach@slotchangeto keep slotted tab items synchronized in bothNavigationBarandRail.handleKeydownandtabsElement.Verification
onActiveIndexChangewith-1, emptyactive-index, and valid indices0..nonmd-nav-barandmd-nav-rail.