Making Dashboard Cards Interactive: Wiring UI Components to Tab Navigation in the JADA Maintenance Hub
One of the most common friction points in dashboard design is when visual summary cards sit inert—clickable in appearance but leading nowhere. The "Total Tasks: 82" card on the JADA Maintenance Hub was doing exactly that. This post covers the approach taken to make that card functionally interactive, routing users directly to the Tasks view with a single click.
What Was Done
The Total Tasks summary card on the maintenance dashboard's home view was refactored to become a clickable navigation element that switches the active tab to the Systems tab (where the task table lives). The change involved three distinct layers:
- HTML structure: wrapping the card in a semantic clickable element
- CSS styling: adding hover states and cursor feedback
- JavaScript event binding: wiring the onclick handler to the existing tab-switching function
This required coordination between the local development environment, the S3 storage layer, and CloudFront cache invalidation.
Technical Details
File Location and Storage Architecture
The maintenance hub's primary file is stored in an S3 bucket rather than as a static git repository. The canonical source is:
s3://[maintenance-bucket]/index.html
This design choice allows the dashboard to be deployed and cached independently of the main site repository, with CloudFront serving as the CDN layer. The current development workflow involves:
- Pulling the file from S3 to a local working directory (e.g.,
/tmp/maintenance_index.html) - Making edits locally
- Uploading the modified file back to S3
- Invalidating the CloudFront distribution to clear cached versions
Tab Navigation Architecture
The maintenance hub uses a tab-based UI pattern implemented in vanilla JavaScript. The core navigation function is:
switchTab(tabName)
This function:
- Accepts a tab identifier string (e.g., 'systems', 'overview', 'logs')
- Hides all currently visible tab content panels
- Shows the target tab's content panel
- Updates visual indicators (active class states on tab buttons)
The task list itself is rendered within the Systems tab, accessed via data attributes in the HTML structure:
<div data-tab="systems" class="tab-content">
<!-- task table markup -->
</div>
When switchTab('systems') is called, this container becomes visible and the task table is displayed to the user.
HTML Structure Changes
The Total Tasks card was originally a static <div> with informational content:
<div class="info-card">
<h3>Total Tasks</h3>
<p class="stat-value">82</p>
</div>
To make it interactive, the card was wrapped in a clickable container with semantic HTML and an onclick handler:
<div class="info-card info-card-link" onclick="switchTab('systems')">
<h3>Total Tasks</h3>
<p class="stat-value">82</p>
</div>
The additional class info-card-link allows CSS targeting of interactive cards separately from static informational cards.
CSS Enhancements
User feedback on interactivity requires visual cues. Two CSS additions signal that the card is clickable:
.info-card-link {
cursor: pointer;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.info-card-link:hover {
transform: translateY(-2px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
}
These properties provide immediate feedback:
- The cursor changes from the default pointer to indicate clickability
- On hover, the card subtly elevates (translateY) and gains shadow depth, following material design principles
- The transition timing (200ms) is fast enough to feel responsive without being jarring
Infrastructure and Deployment
S3 Bucket Configuration
The maintenance hub content is stored in a private S3 bucket configured for CloudFront distribution. The deployment pipeline involves:
aws s3 cp /tmp/maintenance_index.html s3://[maintenance-bucket]/index.html
The bucket does not have public read access; instead, access is mediated entirely through CloudFront via Origin Access Identity (OAI).
CloudFront Distribution and Cache Invalidation
The CloudFront distribution ID for the maintenance subdomain was identified during the session. After uploading the modified index.html to S3, cache invalidation is essential to ensure users see the updated file immediately:
aws cloudfront create-invalidation --distribution-id [DISTRIBUTION-ID] --paths "/*"
This invalidation clears all cached content in the CDN, forcing an edge refresh from the S3 origin on the next request. Without this step, users may see the stale cached version for up to 24 hours (depending on TTL configuration).
DNS Resolution
The maintenance subdomain is configured in Route53 to point to the CloudFront distribution via a CNAME or A record (depending on whether a root domain or subdomain). The alias record structure ensures traffic is routed through CloudFront before reaching S3, providing caching, compression, and DDoS protection.
Key Decisions and Rationale
Why Not Refactor to a Modern Framework?
The maintenance hub uses vanilla JavaScript rather than React or Vue. This decision keeps the single-file deployable artifact small, eliminates build-step complexity, and allows direct HTML file edits to take effect after a simple S3 upload and CloudFront invalidation. For a dashboard with modest interactivity needs, this tradeoff is favorable—deployment is instantaneous and debugging is straightforward.
Why Wrap in a New CSS Class Rather Than Modify the Base Card Style?
The info-card-link class preserves the existing info-card styling while adding interactive-specific properties. This approach allows future cards to remain static informational elements without unintended hover effects. It's a form of composition over modification: both static and interactive cards inherit base styling, but interactive cards get additional behavior.
Why CloudFront Invalidation Over Cache Headers?
While the S3 object could be tagged with shorter TTL headers (e.g., Cache-Control: max-age=300), explicit invalidation ensures immediate propagation across all edge nodes. For a maintenance dashboard where users may be tracking time-sensitive tasks, stale content is unacceptable. The tradeoff is one additional CLI call per deployment, which is negligible.
What's Next
Future iterations could include:
- Adding similar onclick handlers to other summary cards (Systems,