Four hand-built mobile action bars finally became one component
/taxi-rideCaptured 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
Four hand-built mobile action bars finally became one component
Build log series: I give an AI that has never seen Gunjo (
@gunjo/ui) only the public npm package and the gunjo.jp docs, then ask it to build a real screen. This first passenger-facing taxi round, after six staff screens, covered a ride-hailing app: requesting a car, arrival estimates, driver and vehicle details, fares, and payment. It began deeper passenger coverage because one passenger screen would not balance six staff screens.
Result: 4/5, and a gap accumulated across four rounds triggered a build
The screen passed tsc and fit a 375px mobile-first layout. The agent reported:
This was a complete mobile passenger toolkit.
PageHeader,RadioCard,AmountBreakdown,ListCard,LoyaltySummaryCard, andPersonCellincluded targets at least 44px tall, Japanese and yen defaults, and cues beyond color. Only the fixed action bar that every transactional or real-time consumer screen needs was missing.
The core observation: BottomActionBar returned for the fourth time
The agent again hand-rolled a fixed bottom bar with a ride summary and primary action:
There is no
BottomBar,ActionBar, orBottomActionBarin the@gunjo/uientry point or docs, and the catalog admits no dedicated component exists.StatusBarsounds promising but is a fixed-width desktop status strip usingw-[640px], two grid columns, and a primary background. I hand-rolledbottom-0, a top border, backdrop blur, safe-area inset, fare or ETA on the left, and a large button on the right. The highest-value addition isBottomActionBar: a fixed button dock with a fare or ETA slot and safe-area handling, needed in payments, ride hailing, booking, and food ordering.
Disruption rebooking in #125, refunds in #129, intercity bus booking in #139, and ride hailing here meant four independent agents had hand-rolled it. I had already passed the threshold at three and deferred the build. The fourth case removed any doubt.
What I built: BottomActionBar, the fifteenth component
<BottomActionBar actions={<Button size="lg" onClick={call}>Request this ride</Button>}>
<div className="flex flex-col">
<span className="text-xs text-muted-foreground">Estimated fare</span>
<span className="font-semibold tabular-nums">¥1,200 and up, 4 min arrival</span>
</div>
</BottomActionBar>
<BottomActionBar stack actions={<Button size="lg">Pay</Button>}>Summary</BottomActionBar>
childrenholds the ride summary,actionsholds buttons,stackplaces a full-width action above the summary,stickyis the default, andmaxWidthcenters the bar on tablets. A top border, translucent background, backdrop blur, andpb-[env(safe-area-inset-bottom)]clear the home indicator.- It is safe for server rendering and has no hooks or handlers of its own. Callers put
onClickon their buttons. - It is the bottom counterpart to
PageHeader, the fixed top app bar. I replaced the catalog's unsupported note withBottomActionBarand documented why the fixed-width desktopStatusBaris not the same thing. - PR#401 verified the button, estimated fare, four-minute ETA, top border, and clean console at 375px.
What I built under src this round: BottomActionBar, on its fourth observed case and as the fifteenth component. It resolved the BottomActionBar half of issue #391.
What I took away: a top app bar predicts its bottom counterpart
The screen in #125 that produced PageHeader also had hand-rolled layers at both the top and bottom. The top app bar settled after three cases; the bottom action dock took four. Mobile screens are framed by two fixed regions, navigation above and the primary action below. Once one half of a pair settles, the other tends to follow later.
Gunjo has seen the same paired pattern elsewhere: PageHeader and BottomActionBar, ScanInput and TicketStub for reading and presenting a code, and RouteStops and Itinerary for tracking and planning. The foundation often finishes in pairs.
📊 Component scoreboard (15 built)
AmountBreakdown / ActionQueue / ListCard / Gantt-segments / SeatMap / LoyaltySummaryCard / RadioCard / FilterChips / PageHeader / Itinerary / TicketStub / Stringline / StatusBoard / ExpiryBadge / BottomActionBar In progress: ApproachCard for one live ETA, StatusLevel at two of three, TransitItinerary at two of three, LineChip at two of three, and Leaderboard or CaseTable.
📋 Mode progress: passenger-facing taxi coverage begins
- ✈️ Air and 🚆 rail: five staff + six passenger screens each ✅ / 🚌 Bus: two staff + three passenger screens
- 🚕 Taxi: six staff + one passenger screen (ride hailing), with passenger coverage continuing ✅
Next up: build log #148
- I'll decide among deeper passenger bus coverage, trucking with staff operations and customer tracking, or another direction before the next round.
The run
- gunjo.jp / BottomActionBar / PageHeader / npm
@gunjo/ui/ GitHub / previous rounds #1 through #146 - GunjoUI by UIXHERO
Four hand-built bottom action docks became one component, and deeper passenger taxi coverage began. The bottom counterpart to PageHeader had finally arrived.
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.