Book. Pay. Done. Refreshing a booking widget checkout
· TicketingHub · 4 min read
- Role
- Design, frontend, accessibility, UX copy
- Team
- Solo on design and frontend, reviewed by Bartosz Blimke
- Timeline
- July to August 2026
- Outcome
- Merged on 26 August 2026 as one reviewed pull request of 222 files, with the custom CSS of 35 suppliers checked and updated on the day.
On this page · 6 sections
TicketingHub's booking widget is the piece of the product customers touch. It's embedded on the websites of hundreds of tour and attraction businesses. TicketingHub calls them suppliers. I'm its lead designer and frontend developer. Below is the full flow, screen by screen. Under it is the refresh that made the screens look like one product.
Products
Date and Time
Old Town Food Tour
21 Aug - 27 Aug 2026
Choose a time
Customer Details
Date and Time
17 Aug - 23 Aug 2026
Old Town Food Tour
Sunset Kayak Tour
Tickets Selection
Food Tour and Kayak Combo
adult
child
Questions
Please answer all questions to receive your tickets.
Ticket Adult
Ticket Adult
Products
Extras
Add extras or continue without - up to you!
Wine Pairing
Six matched local wines along the way.
Recipe Booklet
A booklet with every recipe from the tour.
Payment
Leave the checkout?
If you leave now, your reserved tickets will be released and your basket will be emptied. You can start again anytime.
Date & Time
Food Tour and Kayak Combo
Select date & time for each activity
1 of 2 scheduled
Old Town Food Tour
August 21 2026 @ 09:00
Sunset Kayak Tour
Select date
Your order has expired
The time limit for completing your order has expired
Gift Cards
Basket
Gift Card
Tickets
Old Town Food Tour
Adult
Ages 18+.
Student
Valid ID required.
Child
Under 12 — free.
Basket
Old Town Food Tour
Payment
Order Summary
Old Town Food Tour
Friday, 21 August 2026 @ 09:00
Thank you for your order!
Please check your email for purchase and ticket information.
Settings
Date & Time
Food Tour and Kayak Combo
Select date & time for each activity
2 of 2 scheduled
Old Town Food Tour
August 21 2026 @ 09:00
Sunset Kayak Tour
ScheduledSelect date
Select time
Basket
Your basket is empty
Ready to make your next booking? Browse available options and add them to your cart.
One foundation instead of many recipes
Each template in the widget carried its own stack of utility classes for a button, an input or an error. The same button was written out in many places.
The refresh I started in July 2026 defines each of those things once. Buttons, inputs, checkboxes and links became shared widget-* styles. So did badges, labels and error boxes. All buttons got one fixed height, and spacing moved to one scale. The font became Inter, and the calendar days became circles. The custom toggle for newsletter and terms became a native checkbox. Components with a state, such as the ticket stepper and the time buttons, keep their selected look in CSS. The JavaScript only switches a class.
I checked colour contrast against WCAG AA. I added focus rings and marked error boxes with role="alert". The generic "must be filled" became a message that names the field.
Some changes were about what the customer reads. The discount code field is always visible now. A long translation cannot break its layout. The dialog for leaving the checkout says what will happen: the tickets are released and the basket emptied. Staying is its primary action. A product without a photo is a compact text card, with no placeholder image.
A summary that follows the choice
The tickets step and the date step now repeat what has been chosen. The line sits right above the main button: "2 tickets · Thu, 29 Aug 2026 @ 14:00". On the tickets step it updates as the customer taps. It uses the correct plural form of "ticket" in each of the widget's languages. A timeslot that has a name shows the name. The line can then say "Afternoon tour" in place of a start time.
My version of that line also showed a "from" price. Before asking anyone to review the branch, I ran an automated code review on it. Two thirds of what it found came from that one feature, including all three real bugs. I took the price out. I kept the working code on a branch of its own and noted what it needs before it can ship. The pull request went back to being what its title says.
Making 222 files reviewable
The final diff touched 222 files across 100 commits. That is a lot to ask of a reviewer. So the description starts with a section called "How to review this". It says most of the diff is the same small change repeated. About 80 templates moved to the shared styles. About 45 translation files were regenerated, and 36 tests followed the new markup. All of that is safe to skim.
Then it lists the six places where behaviour changes. The riskiest comes first. The discount, gift card and voucher forms each submit a code and show an error. Each had its own copy of that code. Now they share one base, so a mistake there hits three forms at once. The list also flags the two changes that reach outside the widget. Product images are now cropped to 2:1, and that image address is part of the public API. And I removed a browser message that no first-party code listened to.
Server-side enforcement of the terms checkbox started on the same branch. It changes what API clients must send. So I split it into a pull request of its own, pending a product decision.
Bartosz Blimke reviewed it and left one inline comment. The summary component was strictly about tickets, so its name should say so. I renamed it. The refresh was merged on 26 August 2026.
The part nobody sees: 35 custom stylesheets
Suppliers can add their own CSS to a widget. A refresh that renames classes breaks stylesheets nobody on the team wrote. Before merging I listed every supplier with custom CSS. There were 35. I sorted them by what would happen:
| What would happen on day one | Suppliers |
|---|---|
| Visible breakage: styles aimed at the old blue, at deleted classes or at spacing that no longer exists | 17 |
| Partial impact, mostly the old toggle switch | 8 |
| Likely unaffected | 10 |
On the day of the merge I went through them and updated the stylesheets.
What is left
The follow-ups are written down in the pull request. One finishes the shared code for the three code forms. Another wires the ticket stepper the same way in the package flow. Two more are test guards. The "from" price and the server-side terms check each wait in their own pull request.
The same widget carries the quiet upsell in its basket. It also carries the package flow, with two bookings in one purchase. And a design experiment asks how few screens a booking could take.
Working together
I am the lead designer and frontend developer of this widget, from the first sketches to the components running in production.
I am open to full-time, part-time and contract work, whether that means joining a product team or taking on a project like this one. Write to hello@edigil.com or use the contact page.