クロスプラットフォームおよびモバイルUI · 新しいリソース

gluestack UI デザインシステム.

gluestack の実際のコア Button と Input クリエーター、明示的な v5 セマンティックカラー、完全な React Native Web ソースを使って、フィールドキットのチェックリストを作成してください。入力検証、キーボード操作、安定した項目識別、ローカルデータから算出されるパッキングの進捗を確認してください。

OpenDesign ガイド8章参考項目33件オリジナルアプリケーションガイド
01

gluestack UI デザインシステムのインターフェースプレビュー

固有の項目を追加し、梱包済みにして、算出された進捗を確認します。

フィールドキットを梱包完全な例を開く
React Native Web 0.21.3 上での、実際の @gluestack-ui/core 5.0.15 の動作です。フィールドキットのレイアウト、アートワーク、状態モデルはオリジナルの OpenDesign によるものです。このブラウザー例ではクリエーターを直接使用し、スタイルを明示的に指定しています。CLI が生成する NativeWind/Uniwind コンポーネント一式ではなく、iOS や Android でのテストも行っていません。 · 実装リファレンス
02

gluestack UI デザインシステムのデザインリファレンス

このリファレンスでは、ドキュメントに記載された v5 のライトカラーと、インストール済み core クリエーター API を分けて示しています。クリエーターを直接使う場合、CLI のテーマは自動適用されません。プレビューでは、記載されたカラーをオリジナルのスタイルに明示的に割り当て、より強調したカスタムのフォーカスアウトラインを使用しています。形状やアートワークはアプリケーション側で選択したものです。

ドキュメントに記載された v5 のライトカラーの役割

ソース
名前 / ルール値 / 設定用途
background#ffffff ページの背景。
foreground#0a0a0a 通常の読みやすいテキスト。
card#ffffff カードの背景面。
popover#ffffff オーバーレイの背景面。この例ではポップオーバーを使用していません。
popover-foreground#0a0a0a オーバーレイの背景面に重ねるテキスト。
muted#f5f5f5 オリジナルのアートワークパネルなどに使う補助的な背景面。
muted-foreground#737373 補足説明やステータスの詳細。
destructive#e7000b 無効な入力を示します。エラーはテキストでも表示されます。
border#e5e5e5 カードの輪郭線とリストの区切り線。
input#e5e5e5 通常時のフィールドの境界線。
ring#d4d4d4 ドキュメントに記載されたデフォルトのリングカラー。この例では、オリジナルの、より強調した #737373 のフォーカスアウトラインを使用しています。
primary#171717 主要アクションの背景面と進捗バーの塗り。
primary-foreground#fafafa 暗いアクション背景面に重ねるテキスト。
secondary#f5f5f5 強調度を抑えたアクションの背景面。
secondary-foreground#171717 補助的な背景面に重ねるテキスト。
accent#f7f7f7 追加のアクセント用背景面。
accent-foreground#343434 アクセントに重ねるテキスト。

core Button ファクトリーと状態

ソース
名前 / ルール値 / 設定用途
createButton{ Root, Text, Group, Spinner, Icon }実際のホストコンポーネントを渡します。クリエーターが追加するのは動作であり、テーマ全体ではありません。
Button.TextText hostボタンのテキストを、その状態のコンテキスト内に保ちます。
Button.GroupGroup hostボタンをグループ化するための生成サブコンポーネント。このレイアウトでは使用していません。
Button.SpinnerSpinner host生成されるローディング表示です。ローカルで即時に完了するアクションには表示しないでください。
Button.IconIcon host生成されるアイコン用サブコンポーネント。プレビューでは、テキストによるアクションを明示的に指定しています。
Button isDisabledboolean見た目だけでなく、実際の押下動作を無効にします。
Button data-focus-visibletrue / falseオリジナルの CSS では、キーボードフォーカス時に視認できるアウトラインを表示します。
Button data-activetrue / falseスタイル設定に使える押下時のインタラクション状態を公開します。

core Input のコンテキストとホストプロパティ

ソース
名前 / ルール値 / 設定用途
createInput{ Root, Icon, Slot, Input }フィールドのコンテキストと関連スロットを作成します。
Input.InputTextInput hostクリエーターが返すテキスト入力コンポーネント。
isInvalidInput root boolean無効な状態のコンテキストと aria-invalid をフィールドに引き継ぎます。
isRequiredInput root boolean必須状態を引き継ぎます。アプリケーション側でも独自に trim バリデーションを行います。
value / onChangeTextControlled TextInput props入力中のテキストを React の状態として保持します。
onSubmitEditingTextInput callbackこのブラウザー例では、Enter キーを押すと項目を追加します。
maxLength60 in the original studyこのアプリケーションで設定した TextInput の上限です。gluestack のデフォルト値ではありません。
aria-labelItem name in the original study画面に表示するラベルとともに、入力欄に名前を付けます。
03

gluestack UI デザインシステム完全ガイド

実際のインターフェースで、このデザインシステムを選び、適用し、レビューするための実践ガイドです。

DESIGN-gluestack-ui.md

詳しいガイダンス、実装の出発点、ソースへのリンクをまとめています。

ガイドをダウンロード

gluestack UI デザインシステムのバージョン、クリエーター、生成コンポーネント

実際に使用する実装方法を選ぶ

gluestack には複数のレイヤーがあります。標準のインストール手順では、スタイル付きコンポーネントをアプリケーション内に生成します。この例では代わりに、インストール済みの core パッケージから createButton と createInput をインポートし、React Native Web のホストコンポーネントを渡しています。この違いは重要です。core をインストールしただけでは、生成済みのボタンバリアントやテーマ全体は提供されません。

この OpenDesign ガイドから

実行例では core 5.0.15 と utils 5.0.6 にバージョンを固定しています。React Native Web のアダプターは実際のコンポーネントで、シェルと状態管理はオリジナルです。Expo または Next.js のアプリケーション全体を構築する場合はインストールのドキュメントを、このブラウザー例を再現する場合はここにある完全なファイルを使用してください。

gluestack UI デザインシステムのセマンティックカラーと明示的なスタイリング

装飾を選ぶ前に、色の役割を組み合わせる

ページには白い背景、濃色の主要アクション、彩度を抑えた補助領域、視認できる境界線を使用しています。色の値はドキュメントに記載された v5 のライトパレットから引用し、React Native のスタイルと通常の CSS を使って明示的に割り当てています。ランタイムプロバイダーが暗黙に色を適用することはありません。

無効なフィールドでは、破壊的な操作を示す色のアウトラインに、読みやすい説明を添え、フォーカスをフィールドに戻します。元のフォーカスアウトラインは、ドキュメントに記載されたデフォルトのリングより濃いため、スタイルシートではライブラリのトークンとして示すのではなく、その選択を明記しています。

移行は慎重に進める

数値のパレット名を使った古い例を、v5のセマンティックな語彙と安易に混在させないでください。トークン名を置き換える前に、インストール済みの生成設定とアップグレードガイドを確認してください。クリエーターを使った個別の検証で動作を示すことはできますが、アプリケーション全体の移行が完了した証明にはなりません。

gluestack UI デザインシステムのボタン構成とキーボード操作

クリエーターに必要なホストをすべて渡す

createButtonには、Pressable、Text、View、ActivityIndicator、アイコン用のホストを渡します。返されるのはButtonと、Text、Group、Spinner、Iconの各サブコンポーネントです。完全な例では、Pressableのルートに文字列を直接置かず、Button.Textを使用します。

パッキングは同期的な状態遷移のため、見せかけのスピナーや保存待ち時間はありません。各アクションのアクセシブルなラベルにはアイテム名を含めています。表示されるアクションは「Pack item」と「Unpack」で切り替わるため、次に起こることが明確です。

描画された動作を確認する

  1. Tabキーで「Pack item」アクションに移動し、Spaceキーを押します。
  2. パック済みであることを示すテキストと進捗値の両方が変わることを確認します。
  3. 「Unpack」を使い、同じアイテムがリストに残っていることを確認します。
  4. マウスのホバーだけでキーボード操作に対応していると判断せず、フォーカスアウトラインを確認します。

gluestack UI デザインシステムの入力コンテキストと完全なバリデーション

保存する値を検証する

入力値はvalueとonChangeTextを使って制御します。追加時にはまず下書きの前後の空白を取り除き、空文字列を拒否してから、大文字と小文字を区別せずに名前を比較します。入力が拒否された場合も、ユーザーが修正できるよう値をフィールドに残します。

ルートにはisInvalidとisRequiredを渡し、実際のフィールドにはラベル、説明への参照、フォーカスを戻すためのrefを渡します。バリデーションはアプリケーション側の責務です。コア入力を必須に設定しても、名前の重複を検出するルールが自動で追加されるわけではありません。

表示されるすべてのフィールド状態に対応する

  • 初期状態:フィールドは空で、文字数のヒントが表示されます。
  • 無効な状態:説明がアラートに表示され、フィールドにフォーカスが移ります。
  • 編集中:ユーザーが下書きを変更すると、古いエラーテキストが消えます。
  • 受け付け済み:未パックの新しい行が追加され、フィールドが空になり、追加したことがステータスで通知されます。

gluestack UI デザインシステムの安定した識別子と派生する進捗

アイテムを保存し、概要を算出する

各アイテムは、安定した数値のid、名前、パック済みかどうかを示すフラグを持ちます。新しいidの生成にはrefを使い、表示名をReactキーとして使うことはありません。切り替え時にはidでマッピングするため、無関係なUIの更新によって別の行が誤って変更されることはありません。

進捗の分子はパック済みフラグから、分母は現在のリストから算出します。未パックのアイテムを追加すると、パック済みのアイテムを失わずにパーセンテージが下がることがあります。これはチェックリストが大きくなった結果であり、アニメーションの不具合ではありません。

リセットを明示的なローカル操作にする

リセットすると、サンプルの3項目に戻り、下書きとエラーが消去され、次のidがリセットされ、結果が通知されます。再読み込みした場合もサンプルの状態から始まります。このプレビューの裏側にサーバー、アカウント同期、永続ストレージはありません。

gluestack UI デザインシステムのレスポンシブレイアウトとオリジナルのイラスト

ホストの動作とページのレイアウトを区別する

デスクトップでは、チェックリストの横に入力パネルを配置します。幅が700ピクセルになると1列になります。必要に応じて行を折り返し、長いアイテム名も利用可能な幅の中で改行します。固定幅のアクションによって、ドキュメント全体が横にはみ出さないようにします。

ノートと鉛筆はオリジナルのCSSシェイプであり、gluestackのブランドアセットをコピーしたものではありません。カードの半径14ピクセル、パネル間隔24ピクセル、見出しのスケールは、この検証用に選んだものです。参照表では、これらをドキュメントに記載された色の役割とは分けて扱っています。

gluestack UI デザインシステムのブラウザーアクセシビリティと対象プラットフォーム

実際に示されている環境でテストする

プレビューはReact Native Webで描画され、ブラウザーで確認済みです。ネイティブのiOSやAndroidでの動作を保証するものではありません。Expoアプリケーションでは、タッチターゲット、スクリーンリーダーによる通知、キーボード表示時の画面調整、プラットフォームのナビゲーションを別途確認する必要があります。

進捗要素には、名前、最小値、最大値、現在値を含めています。ライブステータスでは、チェックリストから読み手を移動させずに、完了した操作を説明します。フォームは入力が拒否されても下書きを保持し、フィールドにフォーカスを戻します。これらは、ネイティブのコア動作に重ねて実装する、アプリケーション側の責務です。

gluestack UI デザインシステムの完全なビルドと依存関係の境界

この検証をそのまま再現する

Component Examplesにある4つのファイルをすべて同じディレクトリに保存し、以下に示す固定バージョンのパッケージをインストールします。コアの内部でネイティブモジュール名が使われるため、ビルドではreact-nativeをreact-native-webにエイリアスします。ソースではブラウザー用ホストを直接インポートし、Expoランタイムは読み込みません。

このWeb専用サブセットのパッケージインストールでは、レガシーのピア依存関係解決を使用します。これは、ネイティブアプリケーション全体への推奨ではありません。ライブラリ全体ではネイティブ、SVG、セーフエリア関連のピア依存関係が提示されますが、この2つのクリエーターからなるバンドルでは使用しません。コンポーネントを追加する際は、適切なピア依存関係も追加してください。

一度に変更するレイヤーは1つにする

  1. ファイルを変更せずにビルドし、追加、重複の拒否、パック、リセットを確認します。
  2. クリエーターの配線はそのままにして、元のレイアウトまたはアプリケーションのコンテンツを変更します。
  3. 生成されたNativeWindコンポーネントを導入する場合は、スタイルとプロバイダーの設定を別の統合作業として置き換えます。
  4. 変更後にキーボードの動作と実際の対象プラットフォームを再確認します。

gluestack UI デザインシステムのコンポーネント例

app.jsx — コアコンポーネントを使った完全な検証例

実際のクリエーター配線と、チェックリストの状態モデル全体。

jsx
import React,{useState,useRef} from 'react';
import{createRoot}from'react-dom/client';
import{Pressable,Text,View,TextInput,ActivityIndicator}from'react-native-web';
import{createButton}from'@gluestack-ui/core/button/creator';
import{createInput}from'@gluestack-ui/core/input/creator';
const Button=createButton({Root:Pressable,Text,Group:View,Spinner:ActivityIndicator,Icon:View});
const Input=createInput({Root:View,Input:TextInput,Slot:Pressable,Icon:View});
const seed=[{id:1,name:'Sketchbook',packed:true},{id:2,name:'Pencil roll',packed:false},{id:3,name:'Water bottle',packed:false}];
function App(){const[items,setItems]=useState(seed),[name,setName]=useState(''),[error,setError]=useState(''),[message,setMessage]=useState('Pack each item when it is ready.');const next=useRef(4),field=useRef(null);const count=items.filter(x=>x.packed).length;
function add(){const v=name.trim();if(!v||items.some(x=>x.name.toLowerCase()===v.toLowerCase())){setError(!v?'Enter the name of an item.':'That item is already in the kit.');field.current.focus();return}setItems([...items,{id:next.current++,name:v,packed:false}]);setName('');setError('');setMessage(v+' added to this local kit.')}
return <main><header><p className="eyebrow">GLUESTACK UI / CORE COMPONENT STUDY</p><h1>A small kit.<br/>A clearer start.</h1><p className="intro">Prepare a drawing kit with actual gluestack core Button and Input creators. Your checklist stays in this browser session.</p></header><div className="layout"><section className="panel"><div className="sectionhead"><h2>Your field kit</h2><span className="badge">{count} of {items.length} packed</span></div><div className="meter" role="progressbar" aria-label="Packed items" aria-valuemin={0} aria-valuemax={items.length} aria-valuenow={count}><i style={{width:100*count/items.length+'%'}}/></div><ul>{items.map(item=><li key={item.id}><div><strong>{item.name}</strong><span>{item.packed?'Packed and ready':'Still to pack'}</span></div><Button onPress={()=>{setItems(items.map(x=>x.id===item.id?{...x,packed:!x.packed}:x));setMessage(item.name+(item.packed?' marked to pack.':' marked packed.'))}} style={item.packed?styles.secondary:styles.primary} aria-label={(item.packed?'Unpack ':'Pack ')+item.name}><Button.Text style={{color:item.packed?'#171717':'#fafafa',fontSize:14,fontWeight:600}}>{item.packed?'Unpack':'Pack item'}</Button.Text></Button></li>)}</ul><p className="status" role="status">{message}</p></section><aside className="panel"><div className="drawing" aria-hidden="true"><span className="book">FIELD<br/>NOTES</span><i className="pencil"/></div><h2>Add one useful thing</h2><label htmlFor="kit-name">Item name</label><Input isInvalid={!!error} isRequired style={styles.input}><Input.Input id="kit-name" aria-label="Item name" aria-describedby={error?'kit-error':'kit-hint'} ref={field} value={name} onChangeText={v=>{setName(v);setError('')}} onSubmitEditing={add} maxLength={60} style={styles.field}/></Input><p id="kit-hint" className="hint">Use a short, unique name. Maximum 60 characters.</p>{error&&<p id="kit-error" className="error" role="alert">{error}</p>}<Button onPress={add} style={styles.primary}><Button.Text style={styles.primaryText}>Add to kit</Button.Text></Button><Button onPress={()=>{setItems(seed);setName('');setError('');setMessage('Example kit restored.');next.current=4}} style={styles.reset}><Button.Text style={{color:'#737373',fontSize:14}}>Reset example kit</Button.Text></Button></aside></div><p className="scope">Native @gluestack-ui/core 5.0.15 behavior rendered through React Native Web. Original OpenDesign layout and artwork; explicitly styled with documented v5 light color roles. This is a web-only study, not an Expo build or the CLI-generated NativeWind component set.</p></main>}
const styles={primary:{backgroundColor:'#171717',paddingVertical:12,paddingHorizontal:16,borderRadius:8,alignItems:'center',justifyContent:'center'},secondary:{backgroundColor:'#f5f5f5',paddingVertical:12,paddingHorizontal:16,borderRadius:8,alignItems:'center',justifyContent:'center'},primaryText:{color:'#fafafa',fontSize:14,fontWeight:600},input:{borderWidth:1,borderColor:'#e5e5e5',borderRadius:8,marginTop:8},field:{padding:12,fontSize:16,color:'#0a0a0a',outlineStyle:'none'},reset:{paddingVertical:16,alignItems:'center'}};
createRoot(document.getElementById('app')).render(<App/>);

コードリファレンス

style.css — オリジナルのレイアウトと明示的なライトカラーの役割

レスポンシブなシェル、イラスト、状態別アウトライン、ブラウザーのフォーカス表示を含む完全な例。

CSS
*{box-sizing:border-box}body{margin:0;background:#fff;color:#0a0a0a;font-family:Arial,sans-serif}main{max-width:1100px;margin:auto;padding:40px}.eyebrow{font-size:12px;letter-spacing:.12em;font-weight:700}.intro{max-width:62ch;color:#737373;line-height:1.6}h1{font-size:52px;line-height:1.03;letter-spacing:-.045em;margin:24px 0}h2{font-size:22px;margin:0 0 20px}.layout{display:grid;grid-template-columns:1.35fr 1fr;gap:24px;margin-top:32px}.panel{border:1px solid #e5e5e5;border-radius:14px;padding:24px;min-width:0}.sectionhead{display:flex;gap:12px;justify-content:space-between;align-items:baseline;flex-wrap:wrap}.badge{font-size:12px;background:#f5f5f5;padding:6px 10px;border-radius:20px}.meter{height:6px;border-radius:8px;background:#f5f5f5;margin:6px 0 24px;overflow:hidden}.meter i{display:block;height:100%;background:#171717}ul{list-style:none;padding:0;margin:0}li{display:flex;gap:16px;align-items:center;justify-content:space-between;padding:20px 0;border-bottom:1px solid #e5e5e5}li>div:first-child{min-width:0;flex:1}li strong{display:block;font-size:16px;overflow-wrap:anywhere}li span{display:block;font-size:13px;color:#737373;margin-top:8px}.status{font-size:14px;line-height:1.6;margin-top:24px}.hint,.scope{font-size:12px;line-height:1.6;color:#737373}.scope{margin-top:28px}.error{font-size:14px;color:#e7000b;line-height:1.5}label{font-size:14px}.drawing{height:130px;background:#f5f5f5;border-radius:8px;display:flex;align-items:center;justify-content:center;gap:24px;margin-bottom:24px}.book{display:block;background:#171717;color:#fafafa;border-left:5px solid #737373;width:80px;height:96px;padding:22px 12px;font-size:12px;line-height:1.6;transform:rotate(-8deg)}.pencil{height:90px;width:8px;background:#a3a3a3;transform:rotate(14deg)}[data-focus-visible=true]{outline:3px solid #737373;outline-offset:3px}[data-invalid=true]{border-color:#e7000b!important}input:focus-visible{outline:2px solid #737373!important;outline-offset:3px}@media(max-width:700px){main{padding:20px}h1{font-size:40px}.layout{grid-template-columns:1fr}.panel{padding:20px}li{gap:12px;flex-wrap:wrap}li>div:first-child{flex-basis:120px}}

コードリファレンス

build.mjs — Webバンドラーの完全な設定

app.jsx ではReact Native Webからホストをインポートしていますが、ネイティブのインポートエイリアスも必須です。

JavaScript
import { build } from 'esbuild';
await build({entryPoints:['app.jsx'],bundle:true,minify:true,outfile:'app.js',alias:{'react-native':'react-native-web'},resolveExtensions:['.web.js','.js','.jsx','.ts','.tsx','.json'],loader:{'.js':'jsx'},define:{'process.env.NODE_ENV':'"production"'}});

コードリファレンス

index.html — ブラウザーのエントリーポイント全体

このファイルはstyle.cssおよび生成されたapp.jsと同じ場所に置いてください。

html
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>gluestack field kit</title><link rel="stylesheet" href="style.css"></head><body><div id="app"></div><script src="app.js"></script></body></html>

コードリファレンス

04

gluestack UI デザインシステム AIエージェントのセットアップ

実装の出発点

まず4つのファイルをすべて保存してください。このセットアップの対象は、ここで示すブラウザー環境の範囲に限られます。NativeWind、Uniwind、Expo、生成されたコンポーネントレジストリは初期化しません。

シェル
npm init -y
npm install [email protected] [email protected] [email protected] @gluestack-ui/[email protected] @gluestack-ui/[email protected] [email protected] --legacy-peer-deps
node build.mjs
python3 -m http.server 8000
# Open http://localhost:8000/

あなたのプロジェクト向けプロンプト

AI エージェント用プロンプト
createButton/createInputとReact Native Webのホストを使用して、gluestack core 5.0.15のフィールドキットをブラウザー上で完全に実装してください。安定したID、制御された入力テキスト、トリミングと重複の検証、フォーカスの復元、派生する梱包済み件数、ローカルリセット、v5のライトロールへの明示的なマッピングを維持してください。元のレイアウトの選択とライブラリのデフォルト設定は分けてください。ネイティブモバイルでのテストやバックエンドへの永続化を行ったとは述べないでください。
05

gluestack UI デザインシステムのソースと対象範囲

React Native Web 0.21.3を介した、@gluestack-ui/core 5.0.15の実際の動作です。フィールドキットのレイアウト、アートワーク、状態モデルはOpenDesignによるオリジナルです。このブラウザーの例ではクリエーターを直接使用し、スタイルを明示的に指定しています。CLIで生成したNativeWind/Uniwindのコンポーネント一式ではなく、iOSやAndroidでのテストも行っていません。