The parts

Greenroom is 8 sections and 3 primitives on 128 design tokens, in light and dark. The calendar is tt-ui’s event-calendar, wearing this theme’s recipe — behaviour shared, appearance entirely ours.

Tokens

--background

--surface-sunken

--card

--foreground

--muted-foreground

--border

--primary

--primary-hover

--accent

--ring

--selection

--hold-line

--text-d4August
--text-d3August at Quarry Hall
--text-d2This week, hour by hour
--text-d1Holds waiting on a decision
--text-leadEvery booking, and the hours it really takes.
--text-bodySolid blocks are the public hours.
--text-smallRoom held 14:00–23:30 (9h 30m)
--text-captionMain Hall · 387 / 420 (92%)

rounded-themed-sm

rounded-themed

rounded-themed-lg

rounded-themed-xl

rounded-themed-pill

LiveWorkshopMatineeCommunityRehearsalHire

Primitives

ui/event-calendar

src/components/ui/event-calendar.tsx

Keyboard: arrows move day by day, ↑/↓ a week, PageUp/PageDown a month, Home/End the week's ends. Enter steps into a day and moves focus to its first event; ↑/↓ then move between that day's events and Escape leaves the cell. In the week view ←/→ move between days and ↑/↓ within one. The agenda's rows are in the normal tab order.

month

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
Press Enter to step into this day, then use up and down arrows to move between its bookings. Escape leaves the day.

week

24–30 August

Mon 24 AugTue 25 AugWed 26 AugThu 27 AugFri 28 AugSat 29 AugSun 30 Aug

agenda

August 2026

empty — a legitimate zero, not a failure

August 2026

Nothing is booked in this period. The building is free.

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
Press Enter to step into this day, then use up and down arrows to move between its bookings. Escape leaves the day.

overflow — one lane, so every busy day shows +N more

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
Press Enter to step into this day, then use up and down arrows to move between its bookings. Escape leaves the day.

bounded — min/max really disable, so paging stops

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
Press Enter to step into this day, then use up and down arrows to move between its bookings. Escape leaves the day.

live — the real thing, driveable

August 2026

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
Press Enter to step into this day, then use up and down arrows to move between its bookings. Escape leaves the day.

ui

src/components/ui/ (primitives)

Buttons, status marks, fields and focus. Every interactive element shows its rest, hover-equivalent, disabled and invalid states; focus is never transitioned.

actions

status marks — a word, an icon and a tone; never colour alone

PencilledConfirmedAnnouncedDoneCancelled

fields — rest, filled, read-only, invalid

ui/accordion-disclosure

src/components/ui/accordion-disclosure.tsx

Progressive disclosure, and the reason /programme fits on a screen. The row keeps the number a reader came for; the panel holds the story behind it. Native <details>, so it is keyboard-operable without a line of script, and the chevron's angle carries the state rather than its transition.

closed — the row still carries its figure

Live

6 booked · 52h held

Touring and local bills, doors at 19:30.

open

Workshop

5 booked · 22h held

Daytime skills sessions, 12 to 24 places. The panel is where the blurb, the tickets and the room list live.

ui/dashboard-layout

src/components/ui/dashboard-layout.tsx

Shell geometry only — sidebar, rail, topbar, header, footer. The document owns the scroll; the week view's hour body is the theme's one nested scroll region.

sidebar
header
children
rail
footer

ui/dialog

src/components/ui/dialog.tsx

The modal layer. Escape closes it, focus is trapped inside and returns to the trigger, and the page behind it locks its scroll exactly once. Its one job in this theme is placing a booking without leaving the calendar.

default — the panel, no layer around it

live — a critical-tone question, with its trigger

ui/sheet-drawer

src/components/ui/sheet-drawer.tsx

The same layer behaviour anchored to an edge. It opens from the right so the calendar stays legible down the left — which is the whole reason inspecting a booking is an overlay rather than a route.

default — the panel, no layer around it

live — opens from the right, focus returns to the trigger

Sections

booking-dialog

src/components/booking-dialog.tsx

The primary action, everywhere it appears. It opens the booking form in a dialog rather than navigating: a programmer fills a gap while looking at it, and a route change would throw away the month they were reading. /new is the same form as a permalink.

event-panel

src/components/event-panel.tsx

What a calendar chip opens. The booking's status block and its hold ledger in a right-hand sheet, so the grid stays legible beside it. /event is the same two sections as a permalink.

app-shell

src/components/app-shell.tsx

Navigation and the strand legend — the key to every colour on the calendar.

Strands

  • Live
  • Workshop
  • Matinee
  • Community
  • Rehearsal
  • Hire

today-rail

src/components/today-rail.tsx

Tonight's run order — the calendar's counterweight, and content rather than a stat strip.

Today

Wednesday 26 August 2026

  • Letterpress for beginners10:00
    Strand
    Workshop
    Room
    Studio
    Sold
    22 / 90 (24%)

    Room held 09:0013:45(4h 45m)

  • Strings, closed rehearsal13:00
    Strand
    Rehearsal
    Room
    Main Hall

    Room held 12:3016:30(4h)

  • Hollow Bell19:30
    Strand
    Live
    Room
    Main Hall
    Sold
    387 / 420 (92%)

    Room held 13:3024:00(10h 30m)

  • Sheet Metal Choir20:00
    Strand
    Live
    Room
    Bar Stage
    Sold
    54 / 60 (90%)

    Room held 17:3023:00(5h 30m)

4 bookings, holding the rooms for 24.8 hours in total.

hold-ledger

src/components/hold-ledger.tsx

The signature in its third form. The second pane is a booking with no load-in recorded — the absence is the information.

a full hold

Room hold

10h 30m held for 3h of public time

  1. Load-in13:30Crew call. Main Hall is taken from here.
  2. Doors19:30Public admitted.
  3. Curfew22:30Public out.
  4. Strike24:00Main Hall free again.

The calendar draws the hold, not the doors. A booking that shows 19:30 on a poster occupies Main Hall from 13:30.

no hold recorded

Room hold

No hold recorded

No load-in time recorded — the hirer has not confirmed a crew call. Until it does, Main Hall reads as free before doors — and it is not.

event-detail

src/components/event-detail.tsx

Status, capacity and promoter. The read-only pane explains the permission boundary rather than showing a dead disabled button.

programmer

Live

Hollow Bell

Wednesday 26 August 2026 · doors 19:30 · Main Hall

Announced

On sale. Moving this now costs the box office.

Room
Main Hall
Capacity
420
Sold
387 (92%)
Promoter
Northfold

promoter — read-only, explained

Hire

Bower & Sons, staff conference

Tuesday 25 August 2026 · doors 09:00 · Main Hall

Confirmed

Agreed with the promoter. Not announced publicly yet.

Room
Main Hall
Capacity
420
Sold
210 (50%)
Promoter
In-house

You are signed in as a promoter, so you can see this booking but not change it. Confirmations and cancellations are the programmer’s. Ask the desk to move a date.

holds-queue

src/components/holds-queue.tsx

The work queue and this theme's filter state. Filters are visible as text, removable one at a time, and a no-result is distinguished from first use.

Pencilled bookings

Strand

3 of 3 shown

Pencilled bookings waiting on a decision, in date order
DateBookingStrandRoomHeldStatus
Thu 27 AugLighting desk clinic

doors 14:00

WorkshopMain Hall3.8hPencilled
Thu 27 AugVoice clinic

doors 17:00

WorkshopStudio3hPencilled
Wed 2 SepSongwriters in the round

doors 19:30

LiveStudio4.8hPencilled

booking-form

src/components/booking-form.tsx

The whole form state layer: persistent labels, validation on submit, an error summary that takes focus, and a durable receipt rather than a toast.

Place a booking

ISO, so it sorts

The room is taken from here, not from doors

This holds the room from 17:30 to 22:30 5h, not the 3h the poster will say.

Pencilling holds the room. Nothing is announced and nothing goes on sale.

load-chart

src/components/load-chart.tsx

The theme's one recharts figure: held hours per week, stacked by strand. Series take the strand tokens the calendar already uses, and the non-colour cue is texture — six SVG patterns — because a stacked segment has nowhere for a direct label. No tooltip: the table beside it is the keyboard-reachable peer and holds the exact values.

Load by week

The building is fullest in the week of 24 Aug at 67h held, and Live carries 48% of it. Hours are load-in to strike, in whole hours, for the weeks that overlap August.

  • Live
  • Workshop
  • Matinee
  • Community
  • Rehearsal
  • Hire

Show the numbers

4 weeks
Hours the building is held each week, by strand
Week ofLiveWorkshopMatineeCommunityRehearsalHireTotal
3 Aug10h4h4h4h0h0h22h
10 Aug5h6h0h9h0h4h24h
17 Aug5h0h2h0h0h0h7h
24 Aug32h12h4h15h4h0h67h

strand-list

src/components/strand-list.tsx

Where the calendar's colour key is defined. The bars are an authored drawing from the fixture spine, not a chart library.

Strands

Six of them, and the colour on every chip in the calendar comes from this list. Open one for what it books and where.

  • Live

    6 booked · 52h held

    Touring and local bills, doors at 19:30.

    Tickets sold
    2,023
    Rooms used
    Main Hall, Bar Stage
    • 8 AugLowfieldMain Hall
    • 13 AugTape LoopsBar Stage
    • 20 AugFolk ClubBar Stage
    • 26 AugHollow BellMain Hall
    • 26 AugSheet Metal ChoirBar Stage
    • 28 AugQuarry WeekenderMain Hall
  • Workshop

    5 booked · 22h held

    Daytime skills sessions, 12 to 24 places.

    Tickets sold
    75
    Rooms used
    Studio, Main Hall
    • 4 AugSound desk clinicStudio
    • 10 AugSummer school, week oneStudio
    • 26 AugLetterpress for beginnersStudio
    • 27 AugLighting desk clinicMain Hall
    • 27 AugVoice clinicStudio
  • Matinee

    3 booked · 10h held

    Afternoon shows for schools and families.

    Tickets sold
    546
    Rooms used
    Main Hall, Studio
    • 9 AugFamily SundayMain Hall
    • 19 AugStory timeStudio
    • 27 AugThe Tin Forest, schools matineeMain Hall
  • Community

    5 booked · 28h held

    Free-entry programme with partner groups.

    Tickets sold
    476
    Rooms used
    Studio, Bar Stage, Main Hall
    • 6 AugFirst Thursday: spoken wordBar Stage
    • 15 AugSmall Press FairMain Hall
    • 25 AugOpen DecksBar Stage
    • 27 AugRepair CaféStudio
    • 27 AugAttercliffe BrassBar Stage
  • Rehearsal

    3 booked · 4h held

    Held space, no public access.

    Tickets sold
    not on sale
    Rooms used
    Main Hall, Studio
    • 17 AugAutumn tech weekMain Hall
    • 26 AugStrings, closed rehearsalMain Hall
    • 31 AugPanto build, heldStudio
  • Hire

    2 booked · 4h held

    Commercial lets. The building is not the promoter.

    Tickets sold
    252
    Rooms used
    Main Hall, Studio
    • 12 AugSheffield Chorale, rehearsal hireStudio
    • 25 AugBower & Sons, staff conferenceMain Hall

Rooms

Capacity is per room and never the building total — a sold-out Bar Stage is 60 people, not a bad night in the Main Hall.

  • Main Hall

    10 booked · 61h held
    Capacity
    420
    Average full
    87%
    Strands
  • Studio

    8 booked · 30h held
    Capacity
    90
    Average full
    27%
    Strands
  • Bar Stage

    6 booked · 29h held
    Capacity
    60
    Average full
    85%
    Strands

schedule

src/components/schedule.tsx

The fixture spine projected onto the library part, including the hold row every public booking generates.

Rendered in full under ui/event-calendar above — 27 bookings, 27 rows in the month view.