```html

Making Dashboard Cards Interactive: Routing UI State Changes Through Tab Navigation

One of the friction points in JADA's maintenance hub dashboard was that the "Total Tasks" summary card displayed aggregate data but wasn't actionable — users had to manually navigate to the Systems tab to see the actual task list. This post covers the refactor to make the card clickable and route users directly to the filtered task view.

What Was Done

The maintenance hub dashboard lives in an S3-backed CloudFront distribution. The index.html file at s3://jada-maintenance-hub/index.html contains a tabbed interface with multiple dashboard views. The Total Tasks info card needed to become a clickable element that programmatically switches to the Systems tab where the full task table renders.

The solution involved three discrete changes:

  • Wrapping the Total Tasks DOM element to make it semantically clickable
  • Wiring the click handler to the existing switchTab('systems') function
  • Adding CSS styles for cursor feedback and hover states to signal interactivity

Technical Details: The Tab Navigation Architecture

The maintenance hub uses a straightforward tab-switching pattern. Each tab has a data-tab attribute identifying it, and a central switchTab(tabName) function controls visibility:

// Existing tab switch logic in maintenance hub index.html
function switchTab(tabName) {
  const tabs = document.querySelectorAll('[data-tab]');
  tabs.forEach(tab => {
    tab.style.display = tab.getAttribute('data-tab') === tabName ? 'block' : 'none';
  });
  // Update active tab indicator if applicable
  updateActiveTabIndicator(tabName);
}

The task data renders in the Systems tab under a table element, populated by data fetched from the backend. By calling switchTab('systems') on the Total Tasks card, we reuse the existing navigation logic without duplicating any state management.

DOM and Event Handler Changes

The original card structure looked like:

<div class="info-card">
  <div class="card-title">Total Tasks</div>
  <div class="card-value">82</div>
</div>

To make it clickable while preserving semantics, we wrapped it in a button-like container with an onclick handler:

<div class="info-card info-card-link" onclick="switchTab('systems')">
  <div class="card-title">Total Tasks</div>
  <div class="card-value">82</div>
</div>

Note: We used a div with onclick rather than a semantic button to avoid disrupting the existing card CSS layout. In production, a better approach would refactor the card into a reusable component with a proper button variant, but this preserves backward compatibility with minimal changes.

CSS for Interactivity Feedback

To signal that the card is interactive, we added hover and active states:

.info-card-link {
  cursor: pointer;
  transition: all 0.2s ease;
}

.info-card-link:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
}

.info-card-link:active {
  transform: translateY(0);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

The subtle translateY and shadow changes provide tactile feedback on hover without overwhelming the dashboard. The transition property ensures smooth animation across browsers.

Infrastructure: S3 and CloudFront Deployment

The maintenance hub is deployed through a two-tier setup:

  • Origin: S3 bucket jada-maintenance-hub containing static assets
  • CDN: CloudFront distribution (ID: E2XYZABC123DEF) caching the origin with a 300-second TTL for HTML files
  • DNS: Route53 CNAME record pointing maintenance.sailjada.com to the CloudFront distribution domain

The deployment workflow after making index.html changes:

# Upload updated HTML to S3
aws s3 cp /tmp/maintenance_index.html s3://jada-maintenance-hub/index.html --content-type "text/html"

# Invalidate CloudFront cache for the file
aws cloudfront create-invalidation --distribution-id E2XYZABC123DEF --paths "/index.html"

CloudFront cache invalidation typically takes 30–60 seconds to propagate. During testing, we can append a cache-busting query parameter (?v=timestamp) to the script src, but for production deployments the invalidation command is the proper approach.

Why This Pattern Over Alternatives

Why not use a link or button element? The existing info-card CSS assumes a div-only structure. Wrapping in a button would require CSS resets and inheritance changes that increase regression risk. The onclick handler on a styled div is a pragmatic short-term solution.

Why not add a separate "View All" button? Users expect dashboard summary cards to be actionable — it's a convention across analytics UIs. A separate button adds visual clutter and requires an extra click.

Why switchTab() instead of a navigation event? The tab system is already implemented as a simple imperative function. Adding an event system would introduce complexity for no benefit when the existing pattern works. If the codebase scales to multiple tabs with complex state, a refactor to an event-driven architecture would be warranted.

Testing and Validation

After deployment, verify the interaction:

  • Hover over the Total Tasks card — should see cursor change to pointer and subtle shadow lift
  • Click the card — the page should navigate to the Systems tab and display the full task table
  • Check browser console for any JavaScript errors related to switchTab
  • Test on mobile: touch should activate the onclick handler without issues

The changes are backward compatible — users still see the same card data, and the Systems tab functionality is unchanged. The only delta is the new interactivity layer.

What's Next

Future improvements could include:

  • Refactor to component pattern: Extract info-card as a reusable Vue/React component with optional link modes
  • Track clicks in analytics: Log when users click summary cards to navigate; this data guides dashboard design decisions
  • Keyboard accessibility: Make the card focusable (tabindex="0") and respond to Enter/Space key presses for full a11y compliance
  • State preservation: Save the active tab to localStorage so users return to their last-viewed tab on page reload

The maintenance hub dashboard is iterating toward better UX through small, targeted interactions. This card refactor is one step in that direction — low risk, high usability gain.

```