ennui-lab-main 2025-12-17 開発日記
今日の開発内容
本日は ennui-lab-main におけるデザインシステム全体の大規模な刷新作業を実施しました。 これまでの実装では、ページ単位やコンポーネント単位でデザインの揺れが発生しており、視覚的一貫性や再利用性の面で改善の余地がありました。 そこで今回、Google が提唱する Material Design 3(MD3) を全面的に導入し、UI の基盤そのものを再設計しました。
MD3 の導入により、カラーシステム、タイポグラフィ、スペーシング、コンポーネントの状態管理が明確に定義されました。 その結果、全ページで統一感のあるモダンな UI を実現することができました。 デザインと実装の乖離も減り、今後の機能追加や保守においても扱いやすい構成になっています。
問題1:Next.js Server/Client Component境界エラー
問題: Next.js App Router 環境において、MDCard.Body という compound component を使用していた際、Server Component から Client Component へデータを渡す部分で型エラーが発生しました。 一見すると問題なく動作しているように見えましたが、設計上は Server / Client Component の境界ルールに違反しており、将来的なビルドエラーや不具合につながる可能性がある状態でした。
原因: MDCard.Body が Server Component と Client Component の境界をまたぐ構造になっており、内部的にシリアライズ不可能な props が渡されていました。 Next.js App Router では、Server Component から Client Component に渡せる値が厳密に制限されています。 この制約に引っかかっていたことが、今回のエラーの根本原因でした。
解決策: MDCard.Body を compound component の一部として扱うのをやめ、 MDCardBody_Component として独立した Client Component に切り出しました。 これにより、Server Component からは安全にシリアライズ可能な props のみを渡す構成に変更できました。 結果として、Server / Client Component 境界に関するエラーは完全に解消されました。
問題2:TypeScriptビルドエラー(children.props is unknown)
問題: MDButton コンポーネントで asChild パターンを採用し、子要素側にスタイルを適用する実装を行っていました。 その際、children.props.className にアクセスしようとすると、 「children.props is of type 'unknown'」という TypeScript のビルドエラーが発生しました。 この問題により、Vercel の本番ビルドが失敗し、デプロイできない状態になっていました。
原因: React.isValidElement を用いて children のチェックは行っていたものの、 TypeScript 側では children の型が unknown のまま扱われていました。 ランタイム上は安全であっても、型システム上は明示的な型情報が不足していたことが原因です。
解決策: (children as React.ReactElement).props.className という形で型アサーションを追加しました。 これにより、TypeScript に対して children が ReactElement であることを明示できました。 結果としてビルドエラーは解消され、Vercel へのデプロイも正常に完了しました。
実装内容
今回のリニューアルでは、Material Design 3 システムの完全導入を実施しました。
新規コンポーネント作成: MDButton、MDCard、MDTextField、MDChip の 4 つの MD3 準拠コンポーネントを新規作成しました。 いずれもデザイン仕様と実装ルールを統一し、再利用しやすい構成になっています。
デザイントークン: globals.css に MD3 のカラートークンとタイポグラフィシステムを統合しました。 ハードコードされた値を排除し、意味ベースでスタイルを管理できるようになりました。
ページリニューアル: home、about、contact、blog ページをすべて MD3 デザインに更新しました。 ページ間のトーンや情報密度の差が解消され、統一感のある体験を提供できています。
既存コンポーネント更新: Header、Footer、AppCard、BlogCard を MD3 スタイルに合わせて再設計しました。 既存資産を活かしつつ、デザインのズレを最小限に抑えています。
今回の変更規模は、 27 ファイル変更、4,210 行追加、346 行削除という大規模な更新となりました。
成果と学び
Material Design 3 の導入により、アプリケーション全体の視覚的統一性が大きく向上しました。 デザインシステムを明確に定義したことで、今後の機能追加や UI 改修時の判断コストが下がります。 結果として、開発効率と品質の両立が可能な状態になりました。
また今回の対応を通じて、 Next.js App Router における Server / Client Component 設計の重要性 をより深く理解できました。 加えて、TypeScript の型システムと実装の関係についても実践的な知見を得ることができました。
モダンな Web 開発におけるベストプラクティスを、 実際のプロジェクトで適用できたことは非常に有意義な経験でした。