A booking screen showed where date UI gets genuinely hard
/bookingCaptured at a 375px viewport. Long pages scroll inside the frame.
The screenshots stay in Japanese. Every round is a real screen for a real Japanese industry, so an English re-render would no longer be the screen the agent actually produced.
Write-up
A booking screen showed where date UI gets genuinely hard
Build log series: I hand a real screen to an AI that has never seen Gunjo (
@gunjo/ui) and let it build. The third complex-screen round covered calendar booking.
The cold-test boundary did not change. The agent had the shipped package and docs, with no source access. The /booking assignment included a date picker that disables past and fully booked dates, time-slot and service selection, name and email fields, and a confirmation summary. Dates and times are where UI complexity gets real. They combine server/browser rendering mismatches with locale-specific behavior.
Result: 4/5
npm run build passed, the page rendered statically, and the console stayed clear.
One strong result was that Calendar defaults to Japanese: Japanese weekday labels, a Japanese year-month heading, and Japanese holidays. An English app needs only locale={enUS}. Gunjo describes itself as a Japanese design system that AI can use, so this quiet default matters.
The getDisabledReason API was even better. Hovering or focusing an unavailable date reveals a tooltip explaining why, such as "This date has passed," and the same reason enters the cell's aria-label. The tooltip provides its own provider, so no outer TooltipProvider is required. That confirmed the issue #52 fix again. TimePicker and Select are based on the native <select>, which also keeps server-side rendering safe.
Rough edges that only a date-heavy screen revealed
1. DatePicker could not disable individual dates
The most common booking rule is disable past dates and specific fully booked dates at the same time. DatePicker could not express it. Its disabled prop only enabled or disabled the entire component, and it did not pass a date matcher to the internal calendar. The lower-level Calendar accepts disabled: Matcher[], so the cold agent abandoned DatePicker and composed the screen from Calendar instead. The main date component failed at the central booking use case. I logged issue #64, and date-matcher forwarding landed in PR#65.
2. Dates create a server/browser mismatch that the library does not help prevent
Disabling past dates depends on new Date(), the current date. Computing that value naively during rendering can give the server and browser different calendars, causing the classic hydration mismatch. The cold agent avoided it by setting today in a browser-only useEffect and rendering a placeholder until then. Gunjo provides no helper for this trap. A recurring failure mode on complex screens needs either documentation or a utility.
3. The docs' code examples still did not appear in machine-fetched content
The known issue #50 returned. The agent learned the controls from bundled TypeScript types instead.
What I took away
Each complex screen exposed something simpler screens could not. Round nine found an absent capability, drag and drop. Round ten found a half-built FileUploader. Round eleven found an API gap: DatePicker lacked the control booking needed most. It also hit the date-specific server/browser mismatch.
The same round also proved two strengths: Japanese by default and accessible explanations for disabled dates. A complex screen can validate what works while revealing what does not. Both belong in the score. The findings were still not exhausted.
Next up: build log #12
- A chat interface using
ChatInputand a message list, another complex screen.
The run
- gunjo.jp / npm
@gunjo/ui/ GitHub - Earlier rounds: #1 through #10
- Overview: Gunjo (
@gunjo/ui) / Why it exists: Design systems in the age of AI - GunjoUI by UIXHERO
Gunjo was still in early alpha at the time; issues are welcome.
This series is co-created with AI (Claude and Codex). A human designs the experiments, makes the calls, and fact-checks before publishing; the AI does the hands-on work and drafting.
Components from @gunjo/ui
The components this screen's source imports directly.
The code the agent actually wrote
Click a file to expand its source.
