# Gallery index.html Tabbed Interface Architecture Explained

> Explore the three-layer architecture of the gallery tabbed interface in cathrynlavery/diagram-design. Learn how CSS presentation, JS state, and event handlers manage diagram selection and navigation.

- Repository: [Cathryn Lavery/diagram-design](https://github.com/cathrynlavery/diagram-design)
- Tags: architecture
- Published: 2026-09-11

---

**The gallery tabbed interface in `cathrynlavery/diagram-design` implements a three-layer architecture separating presentation CSS, a centralized JavaScript state object, and reusable event handlers to manage diagram type selection, variant switching, and accessible keyboard navigation.**

The repository `cathrynlavery/diagram-design` provides a lightweight, framework-free solution for browsing diagram variations through an interactive gallery. The core implementation resides in [`skills/diagram-design/assets/index.html`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/assets/index.html), where vanilla JavaScript handles complex UI state management, ARIA accessibility, and responsive layout through a clean separation of concerns.

## The Three-Layer Architecture

The tabbed interface is organized into distinct layers that handle specific responsibilities:

- **Presentation Layer**: CSS rules defined in the `<style>` block (lines 11-78) control the visual appearance of `.tab` elements, the `.topbar` container, and the responsive behavior of the preview `iframe`.

- **State Management Layer**: A global `state` object declared at lines 5-6 tracks the currently selected diagram type and visual variant.

- **Interaction Logic Layer**: The `bindTabs()` and `update()` functions (lines 9-38 and 40-82) handle event binding, state updates, DOM synchronization, and accessibility attribute management.

## State Management and the Update Cycle

The interface relies on a mutable **state object** that serves as the single source of truth for the current view configuration.

The state is initialized with default values:

```javascript
const state = { type: "architecture", variant: "" };

```

When users interact with the interface, the `update()` function (lines 9-38) executes the following synchronization steps:

1. Identifies the active type button and checks for the `data-single` attribute to determine if variant selection should be disabled.
2. Toggles the `active` class and updates `aria-checked` attributes on both type and variant tabs.
3. Constructs the preview URL using the pattern `example-${state.type}${state.variant}.html`.
4. Sets the `<iframe>` element's `src` attribute and updates the "open raw" link to point to the constructed URL.
5. Updates `aria-labelledby` on the iframe to reference the currently selected tabs for screen reader context.

## Tab Layout and Accessibility Structure

The DOM structure implements the **ARIA radio group pattern** to ensure full accessibility for assistive technologies.

Two distinct tab groups are rendered:

- **Type tabs**: A `<div id="type-tabs">` container holding buttons with `data-type` attributes (e.g., "architecture", "flowchart"). The first button receives `class="tab active"` on initialization.
- **Variant tabs**: A `<div id="variant-tabs">` container with buttons defining `data-variant` attributes including empty string `""`, `"-dark"`, and `"-full"`.

The `bindTabs()` function dynamically assigns `role="radio"` to each tab button and `role="radiogroup"` to the containers. Each tab receives `aria-controls="preview"` to establish a relationship with the iframe element. Disabled states are applied both visually and via the `disabled` property when single-variant types are selected.

## Event Binding and Keyboard Navigation

The `bindTabs(containerId, key)` function (lines 40-82) provides a reusable abstraction for connecting DOM elements to the state management system.

This function implements several critical features:

- **Programmatic ID assignment**: Generates unique identifiers for each tab to support precise ARIA labeling.
- **Activation closure**: The inner `activate()` function updates `state[key]` with the selected value, invokes `update()` to refresh the UI, and manages focus states.
- **Input handling**: Registers listeners for both `click` events and `keydown` events to support ArrowRight, ArrowLeft, Home, and End key navigation.
- **Boundary management**: Keyboard navigation wraps logically at the first and last enabled tabs within each group.

The function is instantiated twice during initialization: once for the type tabs with `key="type"` and once for variant tabs with `key="variant"`.

## Styling and Responsive Behavior

The presentation layer uses standard CSS with specific considerations for mobile accessibility.

Key styling rules include:

- Flexbox-based layout for the `.topbar` containing the tab groups.
- Visual distinction for `.tab.active` states using border and background color changes.
- Media queries (lines 66-76) that enable horizontal scrolling for the type tab row on narrow viewports while maintaining touch target sizes.

The iframe element occupies the remaining viewport height below the topbar, providing a seamless preview of the selected diagram file.

## Programmatic Interaction Examples

Developers can manipulate the gallery state directly through the global `state` object and `update()` function.

To switch diagram types programmatically:

```javascript
// Change to flowchart type and refresh the preview
state.type = "flowchart";
update();  // Loads example-flowchart.html in the iframe

```

To simulate selecting a single-variant tab that disables other options:

```javascript
// Activate the "Import · draw.io" tab which uses data-single
document.querySelector('[data-type="import-drawio"]').click();
// Automatically clears state.variant and disables variant tabs

```

To test keyboard navigation programmatically:

```javascript
// Focus first variant and emulate right arrow key
const firstVariant = document.querySelector('#variant-tabs .tab');
firstVariant.focus();
const event = new KeyboardEvent('keydown', { key: 'ArrowRight' });
firstVariant.dispatchEvent(event);
// Advances to the next variant and triggers update()

```

## Summary

- The gallery interface in [`skills/diagram-design/assets/index.html`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/assets/index.html) separates concerns into presentation, state management, and interaction layers for maintainability.
- The global `state` object tracks `type` and `variant` selections, with the `update()` function synchronizing DOM elements, iframe sources, and ARIA attributes.
- `bindTabs()` provides reusable, accessible tab functionality including full keyboard navigation (Arrow keys, Home/End) and ARIA radio group semantics.
- CSS media queries ensure the interface remains functional on mobile devices while preserving accessibility requirements for touch targets and screen readers.
- Diagram previews follow the naming convention `example-{type}{variant}.html`, enabling straightforward extension for new diagram categories.

## Frequently Asked Questions

### Where is the tabbed interface logic implemented in the repository?

The core logic resides in [`skills/diagram-design/assets/index.html`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/assets/index.html) within the `cathrynlavery/diagram-design` repository. This single file contains the HTML structure, CSS styling (lines 11-78), and JavaScript functions including `bindTabs()` and `update()` that power the interactive gallery.

### How does the interface communicate the current state to assistive technologies?

The implementation uses ARIA radio group patterns: tab containers receive `role="radiogroup"` while individual buttons get `role="radio"` and `aria-checked` attributes that reflect the active state. The preview iframe uses `aria-labelledby` to reference the selected tabs, providing context about which diagram variant is currently displayed.

### What happens when a user selects a diagram type marked as single-variant?

When a tab with the `data-single` attribute is activated, the `update()` function automatically clears `state.variant`, disables all variant tab buttons via the `disabled` property, and updates their `aria-checked` status. This prevents users from selecting incompatible visual variants for diagram types that only support one presentation mode.

### Can the gallery support keyboard navigation without a mouse?

Yes, the `bindTabs()` function explicitly handles keyboard events including ArrowRight, ArrowLeft, Home, and End keys. Focus management moves between enabled tabs only, wrapping at the ends of the tab list, and pressing Space or Enter activates the focused tab—ensuring full WCAG-compliant keyboard accessibility.