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
  1. 01One foundation instead of many recipes
  2. 02A summary that follows the choice
  3. 03Making 222 files reviewable
  4. 04The part nobody sees: 35 custom stylesheets
  5. 05What is left
  6. 06Working together

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

⏰ Time remaining:5:24

Date and Time

17 Aug - 23 Aug 2026

MON17
TUE18
WED19
THU20

Old Town Food Tour

Sunset Kayak Tour

Tickets Selection

🛍️ Package

Food Tour and Kayak Combo

adult

from €79.00
1

child

from €17.00
0

Questions

Please answer all questions to receive your tickets.

Ticket Adult

Ticket Adult

⏰ Time remaining:8:15

Products

Extras

Add extras or continue without - up to you!

Wine Pairing

€12.50

Six matched local wines along the way.

0

Recipe Booklet

€10.00

A booklet with every recipe from the tour.

0

Payment

You will be charged
€98.00
If you have a gift card,
⏰ Time remaining:3:45

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

🛍️ Package

Food Tour and Kayak Combo

Select date & time for each activity

1 of 2 scheduled

Old Town Food Tour

August 21 2026 @ 09:00

Scheduled
2

Sunset Kayak Tour

Select date

Your order has expired

The time limit for completing your order has expired

Gift Cards

Basket

Gift card added to your basket successfully!

Gift Card

Gift Card €50.00€50.00
Total to pay€50.00
⏰ Time remaining:9:52

Tickets

Old Town Food Tour

Adult

from €49.00

Ages 18+.

1

Student

from €39.00

Valid ID required.

0

Child

from €0.00

Under 12 — free.

0

Basket

Old Town Food Tour

Friday, 21 August 2026 @ 09:00
2xAdult
€98.00
VAT 20%€16.33
Total to pay€98.00
⏰ Time remaining:9:37

Payment

Order Summary

Old Town Food Tour

2x Adult€98.00
1x Wine Pairing€12.50

Friday, 21 August 2026 @ 09:00

VAT 20%€18.42
Total to pay€110.50

Thank you for your order!

Please check your email for purchase and ticket information.

Settings

Date & Time

🛍️ Package

Food Tour and Kayak Combo

Select date & time for each activity

2 of 2 scheduled

Old Town Food Tour

August 21 2026 @ 09:00

Scheduled

Sunset Kayak Tour

Scheduled

Select date

Select time

Basket

Your basket is empty

Ready to make your next booking? Browse available options and add them to your cart.

Total to pay€0.00

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 oneSuppliers
Visible breakage: styles aimed at the old blue, at deleted classes or at spacing that no longer exists17
Partial impact, mostly the old toggle switch8
Likely unaffected10

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.