# Desk Directory Contact

> A Swiss grid contact section: pick what your enquiry is about and a column of ink crosses the grid to reveal who answers, their direct line and which door to use.

Canonical: https://gsapvault.com/sections/desk-directory-contact-section
Live demo: https://gsapvault.com/demos/desk-directory-contact-section/index.html

| Property | Value |
|----------|-------|
| Type | section |
| Tier | paid |
| Price | Included only in the Vault |
| Difficulty | intermediate |
| Plugins | Core GSAP only |
| Techniques | accessible-tabs, clip-path-reveal, sliding-indicator-tabs, interruptible-transitions, form-validation, progressive-enhancement, keyboard-navigation, container-queries, responsive-section |
| Uses Lenis | No |

## Overview

Desk Directory Contact is a contact section for organisations where different questions go to different people and often to different doors. It is set like a Swiss poster on a flat vermilion field: a visible 12-column grid, one large grotesk set flush left, black and white photography cropped to the columns and a desk index laid along the grid.

Choosing a desk sends a single column of ink across the stage one grid column at a time. Behind it the chosen desk appears: its photograph, a direct line set large, an email address, who answers and which entrance to use in person. The black index marker travels in the same steps. Change your mind halfway and the shutter reverses; pick a third desk and the current sweep finishes quickly before the next one runs. Below, a real form routes the message to the chosen team, with inline validation and a documented endpoint.

The fictional Farrant Hall example is a concert hall with a box office, access line, learning team, hire office and stage door. The same structure suits a university, a hospital, a council office, a museum or any organisation with more than one front desk. Replace the fictional copy, generated concept photography and example contact details with your own.

## Features

- Visible 12-column grid that the whole layout, the index and the shutter snap to
- A column of ink crosses the stage a column at a time, revealing the chosen desk behind it
- Index marker moves in the same steps, over an inverted copy of the labels so text never clashes
- Reversing mid-sweep runs the shutter back; a third choice finishes the sweep quickly and queues the next
- Each desk shows who answers, a large tap-to-call number, email, hours and the entrance to use in person
- Form routes to the chosen desk, with a routing line, desk-specific hint and inline validation
- Documented POST endpoint; with none set the form says plainly that nothing was sent
- Works without JavaScript: desk links show their own panel and the form submits natively
- 4-column phone layout with the index as a short two-column set directly above the panel
- Independent instances, change event, programmatic go() and exact teardown

## Use Cases

- Concert halls, theatres and venues with a box office, access line and stage door
- Universities and schools routing admissions, accommodation and press enquiries
- Hospitals, councils and public services with separate desks and entrances
- Museums and galleries with groups, hire, press and visitor information

## Vibe-Code Ready Setup

This website section includes `START-HERE-AI.md`, a product-specific copy-paste setup prompt for Cursor, Claude Code, ChatGPT, GitHub Copilot, Windsurf, and other coding assistants. It tells the assistant to inspect the existing stack, integrate the supplied files, preserve the design, scope selectors, retain accessibility and responsive behaviour, add framework-appropriate GSAP cleanup, and report what it tested.

[How AI-assisted setup works](https://gsapvault.com/vibe-coding)

## How It Works

Each desk is an article with its heading, photograph and a list of contact facts, and a link in the index points at it. Without the script the first desk shows and each index link reveals its own panel through the URL fragment, so every desk stays reachable. With the script the links become ARIA tabs with arrow-key, Home and End navigation.

All panels share one grid cell, so the stage keeps the height of the tallest desk and nothing below it jumps. Choosing a desk starts one GSAP tween of a position measured in grid columns. The script reads the real column widths and gutter from the visible grid, and on each update clips the outgoing panel ahead of the shutter and the incoming panel behind it. Each column step holds briefly and then moves, so the shutter reads as a mechanism rather than a glide. The index marker interpolates between the two tab cells in the same steps and carries an inverted copy of the labels, so the text under it changes colour exactly at its edge.

Choosing the previous desk mid-sweep reverses the same tween; choosing a third speeds the current sweep up and queues the new one, so fast input always settles on the last choice. Reduced motion, or no GSAP, makes every change instant, including when the preference changes while the page is open. The form validates on submit, marks fields with aria-invalid and linked messages, and POSTs FormData to the URL in data-dsk-endpoint.

## Documentation

How this website section works and how it goes into a page. The reference you use once you own the files (worked examples, events, the programmatic API, the class list) ships with the download.

### Quick Start

1. Copy `assets/style.css`, `assets/script.js` and `assets/img/` into your project.
2. Load the font, the stylesheet, GSAP 3.15.0 and the script:

_Code snippet omitted: it ships with the download._

3. Copy the markup between the `Desk Directory Contact: copy from here` and
   `copy to here` comments in `index.html`. Everything outside
   `<section class="dsk">` is demo page.

GSAP is optional: without it every change is instant. Without JavaScript the
first desk shows, each index link shows its own desk, and the form submits
natively to its `action`.

### Make it yours

#### Text and links

- **Masthead:** the four `.dsk__mast` paragraphs (name, subject, address,
  switchboard). Each sits on three grid columns; remove one and the rest keep
  their columns.
- **Title:** `.dsk__title` (an `h2`). Change the tag freely; styles use the
  class. It is set on one line per `<br>`; keep lines short, as the size is
  large on purpose.
- **Lede:** `.dsk__lede`.
- **Index label:** `.dsk__index-label`.
- **Each desk** is one `<article class="dsk__panel">`:
  - `.dsk__name` (an `h3`) and `.dsk__about`.
  - `.dsk__facts`: one `<div class="dsk__fact">` per fact. The
    `dsk__fact--call` modifier sets the number large; `tel:` links use the full
    international number. Delete or add facts freely.
  - `.dsk__write`: the link to the form. It selects this desk and moves focus
    to the form.
  - `data-dsk-team` and `data-dsk-email`: used in the form's routing line
    ("Goes to ...").
  - `data-dsk-hint`: the help text shown under the message field for this desk.
- **Fine print:** `.dsk__fine`. Remove it once the content is yours.

#### Photos

One photo per desk, in `.dsk__figure`:

| Desk | File | Size |
|---|---|---|
| Tickets | `assets/img/tickets.webp` | 1536 x 1024 |
| Access | `assets/img/access.webp` | 1536 x 1024 |
| Schools | `assets/img/schools.webp` | 1536 x 1024 |
| Hiring the hall | `assets/img/hire.webp` | 1536 x 1024 |
| Stage door | `assets/img/stage-door.webp` | 1536 x 1024 |

To replace one, save any ordinary photo (1400 to 2000 px wide works well),
change `src`, `width`, `height` and `alt` on its `<img>`, and adjust
`style="object-position: 50% 50%"` to keep the subject in frame. Frames are
cropped to `--dsk-photo-ratio` (3:2), so portrait or square photos are cropped
too; set `object-position` so the person or doorway stays in view. The first
desk's photo has `fetchpriority="high"`; the rest are `loading="lazy"`. The
demo photos are black and white, which suits the flat colour field; colour
photos work as well.

#### Adding, removing or reordering desks

Desks are matched by key: the index link's `data-dsk-for`, the panel's
`data-dsk-key` and the form option's `value` must be the same word.

- **Add:** copy a panel and an index link, give both a new key and a new `id`
  and `href`, and add a matching `<option>` to the form's select.
- **Remove:** delete the panel, its link and its option.
- **Reorder:** reorder the panels, links and options the same way. Numbers in
  the index are automatic, and the shutter's direction follows panel order.

Five desks line up exactly with columns 3 to 12. Two to eight work: other
counts share that span equally. With a single desk, delete the index; the panel
and form still work.

#### Brand variables

All on `.dsk`:

| Variable | Default | Use |
|---|---|---|
| `--dsk-ground` | `#f25c34` | The colour field, and the text on black buttons |
| `--dsk-ink` | `#111111` | Type, rules, the shutter and the active desk |
| `--dsk-field` | `#ffffff` | Form field fill |
| `--dsk-rule` | `rgba(17,17,17,.16)` | The visible grid lines |
| `--dsk-font` | Host Grotesk | Every text role |
| `--dsk-max` | `1440px` | Maximum width including side padding |
| `--dsk-pad` / `--dsk-gap` | fluid | Side padding and column gutter |
| `--dsk-photo-ratio` | `3 / 2` | Photo frame proportion |

Rebrand example, a hospital's outpatients desk in green:

_Code snippet omitted: it ships with the download._

Check contrast when you change the ground: body text is `--dsk-ink` on
`--dsk-ground`, and buttons use `--dsk-ground` on `--dsk-ink`; both need 4.5:1.
The default pair measures 5.7:1. To hide the visible grid, set `--dsk-rule:
transparent`; the layout keeps its columns.

### Behaviour and options

- `data-dsk-duration="0.72"` on `.dsk`: seconds for one full sweep.
- `root.deskDirectory.go('access')` selects a desk; `{ instant: true }` skips
  the sweep.
- `root.addEventListener('dsk:change', e => e.detail.key)` fires on each new
  choice.
- `root.deskDirectory.destroy()` removes everything the script added (tabs
  roles, marker, shutter, form handling) and restores the plain links;
  `DeskDirectory.mount(root)` starts it again, for instance after injecting the
  markup later.
- Choosing the previous desk during a sweep reverses it; choosing a third lets
  the current one finish quickly and then runs the next. Input always settles
  on the last choice.
- A link to `#<panel id>` in the page URL opens that desk first.

#### The form

Set `data-dsk-endpoint` on the `<form>` to a URL that accepts a POST of
`FormData` (a form service such as Formspree, Basin or your own handler), and
set `action` to the same URL for visitors without JavaScript. Fields posted:
`desk`, `reference`, `name`, `email`, `message`.

With no endpoint, the form validates and then says plainly that nothing was
sent. Nothing in this section stores or sends data by itself, and there is no
backend included.

### Accessibility and integration

- The index becomes an ARIA tablist: Tab reaches the selected desk, arrow
  keys, Home and End move and select. Links, buttons and fields have visible
  focus rings.
- Every desk is readable without JavaScript. Reduced motion makes changes
  instant, including if the setting changes while the page is open.
- Form errors appear next to their field, are linked with
  `aria-describedby`, set `aria-invalid`, and focus moves to the first one.
  The result is announced from a `role="status"` line.
- The title is an `h2` and desk names are `h3`s; change the tags to fit your
  page.
- The section is full width with its own background and needs no sticky or
  scroll behaviour. It works in narrow columns: below 720 px of its own width
  it switches to a 4-column grid.
- Two instances need different `id`s on panels and form fields; the script
  scopes everything else to each section.

### Dependencies and credits

- [GSAP 3.15.0](https://gsap.com) (optional; free for all uses).
- [Host Grotesk](https://fonts.google.com/specimen/Host+Grotesk) from Google
  Fonts, SIL Open Font License.
- Photographs are AI-generated concept images made for this demo, provided for
  use with this section. Farrant Hall, its people, numbers
  (Ofcom drama range) and addresses are fictional.

## What You Get

- `index.html`: working demo page
- `assets/script.js`: commented, readable source
- `assets/style.css`: effect styles
- `README.md`: full documentation with examples and framework integration notes
- `START-HERE-AI.md`: product-specific copy-paste prompt for AI-assisted setup
- `LICENSE.txt`: standard license terms
- Lifetime updates: re-download anytime from your library

## Get the Code

This website section is included only in the Vault, for existing and new owners. It is not sold individually. The standard licence covers unlimited personal and commercial projects; bundled assets retain their own licence requirements.

- [Get the Vault](https://gsapvault.com/pricing)
- [The Vault (£99 one-time, best value): every collection in the Vault library, plus future items added to those collections](https://gsapvault.com/effects)

---

From [GSAP Vault](https://gsapvault.com): production-ready GSAP animation effects. Full catalog for agents: https://gsapvault.com/llms-full.txt
