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
rounded-themed-sm
rounded-themed
rounded-themed-lg
rounded-themed-xl
rounded-themed-pill
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
week
24–30 August
agenda
August 2026
empty — a legitimate zero, not a failure
August 2026
Nothing is booked in this period. The building is free.
overflow — one lane, so every busy day shows +N more
August 2026
bounded — min/max really disable, so paging stops
August 2026
live — the real thing, driveable
August 2026
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
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.
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:00–13:45(4h 45m)
- Strings, closed rehearsal13:00
- Strand
- Rehearsal
- Room
- Main Hall
Room held 12:30–16:30(4h)
- Hollow Bell19:30
- Strand
- Live
- Room
- Main Hall
- Sold
- 387 / 420 (92%)
Room held 13:30–24:00(10h 30m)
- Sheet Metal Choir20:00
- Strand
- Live
- Room
- Bar Stage
- Sold
- 54 / 60 (90%)
Room held 17:30–23: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
- Load-in13:30Crew call. Main Hall is taken from here.
- Doors19:30Public admitted.
- Curfew22:30Public out.
- 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
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
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
3 of 3 shown
| Date | Booking | Strand | Room | Held | Status |
|---|---|---|---|---|---|
| Thu 27 Aug | Lighting desk clinic doors 14:00 | Workshop | Main Hall | 3.8h | Pencilled |
| Thu 27 Aug | Voice clinic doors 17:00 | Workshop | Studio | 3h | Pencilled |
| Wed 2 Sep | Songwriters in the round doors 19:30 | Live | Studio | 4.8h | Pencilled |
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
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
| Week of | Live | Workshop | Matinee | Community | Rehearsal | Hire | Total |
|---|---|---|---|---|---|---|---|
| 3 Aug | 10h | 4h | 4h | 4h | 0h | 0h | 22h |
| 10 Aug | 5h | 6h | 0h | 9h | 0h | 4h | 24h |
| 17 Aug | 5h | 0h | 2h | 0h | 0h | 0h | 7h |
| 24 Aug | 32h | 12h | 4h | 15h | 4h | 0h | 67h |
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 heldTouring 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 heldDaytime 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 heldAfternoon 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 heldFree-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 heldHeld 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 heldCommercial 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.