またしても本当に AI に使わせてみた — モーダル告知バナーを @gunjo/ui で(やってみた #2)
/announce375px のビューポートで撮影。縦長のページはフレーム内をスクロールします。
解説記事
またしても本当に AI に使わせてみた — モーダル告知バナーを @gunjo/ui で(やってみた #2)
やってみたシリーズ: 自作のデザインシステム
@gunjo/ui(群青)を、文脈ゼロの cold な AI エージェントに毎回「実アプリ頻出の UI」を作らせていく連載。各回がそのまま「gunjo でこう作る」のハウツーになります。第1回(設定画面)に続いて、今回は モーダル告知バナー。
前回と同じ条件です。この文脈をまったく知らない AI エージェント1体に、公開済みの npm @gunjo/ui(alpha.2)と gunjo.jp の docs だけを渡す。ソースリポジトリは見せない。まっさらな Next.js(React 19 / Tailwind v4)で、npm run build が通るところまで自力で。
お題
新機能のお知らせ周りで誰もが作るやつ。
- 上部に閉じられる告知バナー(「v2 is live」+CTA+×ボタン)
- それを開く告知モーダル(タイトル・本文・主/副ボタン、初回自動オープン)
- 閉じた/確認したときのトースト確認(「You're all caught up」)
通すカテゴリは前回と別 —— Feedback(Banner / Toast)と Overlay(Modal)。シリーズが進むほどカタログの別スライスを cold AI に通すことになる。
結果 — 動いた(4/5)
npm run build 成功、/announce は static prerender、コンソールエラー0(自分でも実機確認した)。
一番効いたのは、今回も typed barrel export。エージェントは src/index.ts を一読しただけで Banner / Modal / Toast / ToastProvider / useToast という名前を掴み、import { Banner, Modal, ToastProvider, useToast } from "@gunjo/ui" がパス調整ゼロで解決した。さらに同梱の .tsx ソースから props 契約をそのまま読めた(Banner の action/onDismiss、Modal の isOpen/footer、useToast() → showToast(msg, type))。className の override は一度も要らなかった、と。
そして粗さ — 今回は2つ、しかも片方は痛いところを突かれた
① Banner が単体で SSR クラッシュする(ライブラリのバグ)
エージェントは build を一度落としています。
Error: `Tooltip` must be used within `TooltipProvider`
調べると——Banner の×ボタンは内部で Tooltip を使うのに、TooltipProvider を self-wrap していない。一方 Toast は同じ tooltip を <TooltipProvider> で包んでいる。同じ Feedback カテゴリ内で挙動が不整合で、素直な <Banner onDismiss> が prerender で死ぬ。エージェントの回避策はページを <TooltipProvider> で包むこと。
// エージェントが書き上げた最終形(抜粋)
export default function AnnouncePage() {
// Banner の dismiss が内部 Tooltip を使うが Provider を self-wrap しないため、
// 単体 Banner には ancestor の TooltipProvider が要る(Toast は要らない)。
return (
<TooltipProvider>
<ToastProvider>
<Announcement />
</ToastProvider>
</TooltipProvider>
)
}
これは使い方ミスではなくライブラリ側の落とし穴。報告を受けてソースを確認し、#49 として起票しました。直しは Banner を Toast と同様 self-wrap させる方向(SSOT 3軸そろえて、design:verify 緑で)。#47 と同じループです。
② 自分の docs が、エージェントには薄かった
こっちが正直キツかった。エージェントいわく——「docs のコード例は client widget で、WebFetch / markdown 抽出に乗ってこない。prop 説明は一部日本語のみ。結局いちばん信頼できた API の出典は docs ではなく、同梱の TypeScript 型だった」。
「AI から使える」を掲げておいて、docs サイト自体が機械可読として弱いという指摘。typed barrel と同梱型に救われて 4/5 に着地したけれど、ここは設計思想の根っこを突かれた。docs URL も /docs/feedback/banner を試して 404(実体は flat な /docs/components/banner)、install ガイドに ToastProvider の言及なし——細かいが、cold な相手はここで詰まる。
学び
AI に使わせる → 粗さが出る → SSOT で一貫して直す → また使わせる
#1 は固定幅、#2 は Banner の provider バグと**「docs の機械可読性」そのもの**。回を重ねるほど、ハッピーパスでは見えない粗さが別の角度から出てくる。AI-consumable は宣言ではなく、cold な相手に通し続けて潰すことでしか証明できない——という確信が、また一段濃くなりました。盛らない、隠さない。
次回予告(やってみた #3)
- カルーセル設置(Carousel / Card)—— LP のヒーローやメディア一覧で頻出のやつ。
試す
- gunjo.jp — docs・ショーケース・パターン
- npm:
@gunjo/ui/ GitHub - 前回: 本当に AI に使わせてみた #1(設定画面)
- 母艦: 群青(@gunjo/ui)— SSOT デザインシステム
- GunjoUI by UIXHERO
まだ alpha、粗削りな青です。粗さが出るたび直します。Issue 歓迎。
<!-- 公開前: #49 修正反映後に Banner 記述を更新/docs機械可読の別issue化/相互URL差込/EN(dev.to)ミラー -->
使用した @gunjo/ui コンポーネント
この画面のソースが直接 import している部品です。
cold AI が組み上げた実コード
ファイル名をクリックでソースを展開できます。
