#51スコア 4/5物流・倉庫

AI に配車・積込を作らせてみた — 容量メーターが3回目で primitive 化、Badge の hydration バグも出た(やってみた #51)

ルート: /loading
デスクトップ表示
モバイル表示

375px のビューポートで撮影。縦長のページはフレーム内をスクロールします。

解説記事

AI に配車・積込を作らせてみた — 容量メーターが3回目で primitive 化、Badge の hydration バグも出た(やってみた #51)

やってみたシリーズ: 自作のデザインシステム @gunjo/ui群青)を、文脈ゼロの cold な AI に実 UI で作らせる連載。物流/倉庫(WMS)5枚目——配車 / 積込 / 配送ルート(便/車両 × トラック積載率メーター × 積込スキャン × 配送ルート/順序/ETA × 積み残し)。

#47-50 の倉庫内オペに続き、出庫の最後——トラックに積んでルートを組んで出発させる配送センターの配車画面。車両の重量・容積の積載率を見ながら出荷を割り当て、積込をスキャンし、配送順を並べて出発確定する。

結果 — 4/5

tsc/build 緑・console 0(Badge 修正後)・375px・閾値で色が変わる積載率メーター・出荷割当でメーターが「積んだら何%になるか」をプレビュー・超過は積み残しでブロック・積込スキャン・配送順の並べ替えで ETA 再計算・出発確定ゲート・h1 1個。

今回の本題① — 容量メーターが3回目 → primitive 化

倉庫の3画面(#48 棚の充填・#50 ロケーション充填・#51 トラック積載率)が、同じ容量メーターを毎回手組みしていた。Progresstone で平らなバーは出せても、容量メーターが本当に欲しい3つを Progress は持たない:

Missing higher-order primitive: a capacity Meter / Gauge. Progress は (a) 閾値からトーンを導出できない(毎画面 fillTone(pct) を書く)・(b) 現在+入荷分のオーバーレイで「これを積んだら超過するか」をプレビューできない・(c) テーブルセル内のコンパクト inline が無い。CapacityMeter.tsx を毎回手組み。

3回ルール発火Meter(#230)PR #235)を出荷:

<Meter label="重量積載率" value={2100} max={3000} incoming={350} unit="kg"
       thresholds={{ warning: 0.8, over: 1 }} />

<Meter size="inline" value={41} max={40} label="棚 D-03 充填" />
  • role="meter"thresholds からトーンを自動導出(満載間近→warning・超過→destructive)
  • incomingvalue の上に縞模様のオーバーレイを重ね、トーンも駆動——コミット前に超過を警告(読み上げは「2100kg + 350kg → 82%」に)
  • size="inline" はテーブルセル用の細バー+コンパクト%・unitlabel(accessible name)・aria-valuetext色だけに意味を乗せない・トークン駆動でダークモード無料

ブラウザ実証: 70%→success / 84%→warning / 100・102%→destructive、incoming で縞セグメント(left 70%・幅 11.67%=350/3000)+プレビュー読み上げ、inline がセル内に収まる。Progress は平バー用に tone(#229) を維持、Meter は容量特化の兄弟(role="meter" vs progressbar)。

今回の本題② — Badge の hydration バグ(🔴 実バグ)

cold AI が <Badge>到着 08:30</Badge><p> の中に置いたら、実行時に hydration クラッシュ——「div cannot be a descendant of p」。tscnext build も通り、ブラウザでだけ捕まった

Badge はデフォルト as="div" だった。status pill は phrasing content で、文章・段落・インライン行の中に常に置かれる。block の <div> デフォルトは footgun。Badge は inline-flex スタイルなので <span> で見た目は同一・flow content で valid(onRemove<button> も span 内で valid)。→ デフォルトを span に修正#233PR #234)。型チェックとビルドをすり抜けるバグは、cold テストで実際にブラウザに載せるからこそ出る

複利も全採用

  • ScanGate(#49 build) — 車両/便→カートンの2段積込スキャンに採用「used, excellent fit・advance:"stay" でカートンを連続スキャン」。#49→#50→#51 と3回連続で別画面に使われた。
  • Delta(残容量・空き=success/超過=destructive 上書き)・Statistic(残重量/容積・積載個数の KPI)・Badge/Alert(状態・積み残し読み上げ)・Progress tone も。

起票だけした穴(3回ルール未達)

  • 🟠 配送ルート/ストップリスト#2282回目=#47 ピッキングのウォークパス+#51 配送順)。順序付きの配送先(ETA 付き・並べ替え可)を Timeline(表示専用)/Stepper(固定 wizard) では組めず手組み。RouteStops(or TimelineonReorder+per-item time/eta)が理想。あと1回で build。

学び — 同じラウンドで「3回目を build」「実バグを fix」が両立した

build(3回目の合成穴): 容量 Meter #230(#48+#50+#51)
fix (ブラウザでだけ出た実バグ): Badge の <div> デフォルト #233
起票(2回目)        : ルートストップ #228

cold テストの価値は、(a) 頻度で primitive を浮かび上がらせるだけでなく、(b) tsc/build をすり抜ける実行時バグを実ブラウザで捕まえること。#51 はその両方が1回で出た回——容量メーターは3画面で育って Meter に、Badge は <p> の中という"普通の使い方"で初めてクラッシュした。規律(3回ルール)と検証(実ブラウザ)が、別々の穴を同時に拾う。

次回予告(やってみた #52)

  • 物流をもう1枚(返品入荷/リバース or 配送追跡)でルートストップ#228 を3回目=build 閾値へ、または別業界へ。方針: 1業界3〜5枚・可能な限り違う内容・業界特有UI最優先。

試す

まだ alpha。容量メーターが3回目で primitive 化し、Badge の hydration バグも実ブラウザで捕まえた回。


<!-- 公開前: 相互URL差込/スクショ確定/EN(dev.to)ミラー -->

使用した @gunjo/ui コンポーネント

この画面のソースが直接 import している部品です。

cold AI が組み上げた実コード

ファイル名をクリックでソースを展開できます。