OpenAIExpo2026/02/03 14:15

Building high-quality UIs with Expo and NativeWind

要点だけを先に読めるように短く再構成したセクションです。

元記事

Quick Digest

要約

要点だけを先に読めるように短く再構成したセクションです。

openaijamodel: gpt-5-mini-2025-08-07

Expo と NativeWind で高品質な UI を構築

Key Points

  • コードでデザイン
  • NativeWindでテーマ管理
  • 再利用コンポーネント

Summary

Thomino によるワークフローの紹介。Expo Go のライブプレビューを使ってコード上で直接デザインし、Figma を使わずに実装を進める手法を説明します。NativeWind の vars で一元的にテーマを管理し、Reanimated でアニメーションを付けたトグルやナビゲーションを実現することで、再利用可能なコンポーネント群から高速に高品質な UI を組み立てられます。

Key Points

  • 再利用可能コンポーネント: フレキシブルな Header、アニメーションタブ(TabTrigger/TabButton)、MultiStep のオンボーディング、Chip などをコンポーネント化してプロジェクトのテンプレート化に活用する。
  • NativeWind でのテーマ管理: import { vars } from "nativewind" を使い、themes ファイルにライト/ダークの変数を定義して一箇所で切替可能にする。
  • アニメーション付き UI: Reanimated を使ってダークモードトグルやタブ遷移にアニメーションを追加し、UX を向上させる。
  • 実装の実務的ヒント: useThemeColors や react-native-safe-area-context を組み合わせ、className(NativeWind)でスタイルを当てながら Expo Go で即時確認するワークフローが効率的。
  • 効果と狙い: デザインと実装の反復が早まり、オンボーディング成功率向上や一貫したデザインシステム構築に寄与する。

Full Translation

翻訳

原文の流れを保ったまま読める翻訳セクションです。

openaijamodel: gpt-5-mini-2025-08-07

Expo と NativeWind で高品質な UI を構築する

Expo と NativeWind で高品質な UI を構築する

開発 • React Native • 2026-02-03 • 読了時間: 3分
Thomino(ゲスト著者)

Expo、NativeWind、Reanimated を使ってコード上で直接 React Native アプリをデザインする方法を学びます。再利用可能なコンポーネントを構築し、テーマを実装し、Figma を使わずに済ませる方法を紹介します。

この記事は Thomino の寄稿です。彼は Native Templates の作者で、X でフォローすると良いアカウントです。

私は IE6 の時代からウェブを作ってきました。ボックスシャドウにスライス画像を使い、角丸に透明 GIF を使い、構造にネストしたテーブルを使っていたことを覚えています。あれはフロントエンド開発の「暗黒時代」でした。幸い状況は変わりました。Expo、NativeWind、Reanimated の組み合わせがあれば、アプリのデザインは非常に簡単です。実際、私はもう Figma を使っていません。Expo Go のライブプレビューで直接コード内でデザインしています。

以下では、私がワークフローで使っている再利用可能なコンポーネントでどのようにアプリを作っているかを紹介します。これらのコンポーネントによってエディタ内で直接デザインできます。さらに、テーマの扱い方とアニメーション付きのテーマ切替(Theme toggle)の作り方も解説します。

再利用可能なコンポーネント

各アプリは異なりますが、多くは画面、フロー、コンポーネントを共有します。そのため、新しいプロジェクトでベースとして常に使えるテンプレートを作ることにしました。効果的に行う鍵は、特定のアプリに合わせて簡単にスタイル調整できる再利用可能なコンポーネントを作ることでした。以下は私が NativeTemplates で実装したいくつかの例です。

NativeWind で柔軟なヘッダーコンポーネントを作る

おそらく最も重要で基本的なコンポーネントです。ヘッダーを柔軟で調整しやすくすることが非常に重要でした。

コード例: import React from "react" ; import { View , Text , TouchableOpacity } from "react-native" ; import { useThemeColors } from "app/contexts/ThemeColors" ; import { Link , router } from "expo-router" ; import Icon , { IconName } from "./Icon" ; import { useSafeAreaInsets } from "react-native-safe-area-context" ; type HeaderProps = { title : string , showBackButton ? : boolean , rightComponents ? : React . ReactNode [ ] , } ; const Header : React . FC < HeaderProps > = ( { title , showBackButton = false , rightComponents = [ ] , } ) => { const colors = useThemeColors ( ) ; const insets = useSafeAreaInsets ( ) ; const handleBackPress = ( ) => { router . back ( ) ; } ; return ( < View style = { { paddingTop : insets . top } } className = "w-full pb-2 flex-row justify-between px-6 bg-background" > < View className = "flex-row items-center flex-1" > { showBackButton && ( < TouchableOpacity onPress = { handleBackPress } className = "mr-4 py-4" > < Icon name = "ArrowLeft" size = { 24 } color = { colors . icon } / > < / TouchableOpacity > ) } < View className = "py-4" > < Text className = "text-lg font-bold" style = { { color : colors . text } } > { title } < / Text > < / View > < / View > { rightComponents . length > 0 && ( < View className = "flex-row items-center justify-end flex-1" > { rightComponents . map ( ( component , index ) => ( < View key = { index } className = "ml-6" > { component } < / View > ) ) } < / View > ) } < / View > ) ; } ; export default Header ;

使用例: // Basic header with title < Header title = "Home" / > // Header with back button < Header title = "Details" showBackButton / > // Header with action icons < Header title = "Messages" rightComponents = { [ < HeaderIcon key = "search" icon = "Search" href = "/search" / > , < HeaderIcon key = "settings" icon = "Settings" href = "/settings" / > ] } / >

React Native でアニメーション付きタブナビゲーションを作成

アイコン、アニメーション、またはアバターを選べます。

コード例: < TabTrigger name = "home" href = "/" asChild > < TabButton labelAnimated = { true } icon = "Home" > Home < / TabButton > < / TabTrigger > < TabTrigger name = "profile" href = "/profile" asChild > < TabButton labelAnimated = { true } avatar = { require ( '@/assets/img/thomino.jpg' ) } > Profile < / TabButton > < / TabTrigger >

マルチステップフォームとオンボーディングフローの構築

これは非常によく使います。オンボーディングやその他のユーザーフローに最適です。オンボーディングはユーザーを活性化し、早期離脱を減らすのに不可欠です。

コード例: < MultiStep onComplete = { handleComplete } onClose = { handleClose } headerTitle = "Get Started" > < Step title = "Profile" > < Profile / > < / Step > < Step title = "Role" > < Role / > < / Step > < Step title = "Capabilities" > < Capabilities / > < / Step > < Step title = "Review" > < Review / > < / Step > < / MultiStep >

フィルターやフォーム向けの再利用可能なチップコンポーネント

これは非常に基本的ですが、フィルターやフォームで多用します。

コード例: < Chip label = "Custom" className = "my-2 mx-1" size = "xl" / >

ドキュメントで全コンポーネントを確認できます。

NativeWind でテーマ変数を実装する

NativeWind によってテーマ化が非常に強力になります。vars を使うことで、アプリ全体のテーマを1ファイルで切り替えられます。これにより、ライト/ダークモードが単なる後付けではなく、デザインシステムの中核になります。

コード例: import { vars } from "nativewind" ; export const themes = { light : vars ( { "--color-primary" : "#000000" , "--color-invert" : "#ffffff" , "--color-secondary" : "#ffffff" , "--color-background" : "#F4F4F5" , "--color-darker" : "#F4F4F5" , "--color-text" : "#000000" , "--color-highlight" : "#7E55D8" , "--color-border" : "rgba(0, 0, 0, 0.15)" , } ) , dark : vars ( { "--color-primary" : "#ffffff" , "--color-invert" : "#000000" , "--color-secondary" : "#1e1e1e" , "--color-background" : "#141414" , "--color-darker" : "#000000" , "--color-text" : "#ffffff" , "--color-highlight" : "#7E55D8" , "--color-border" : "rgba(255, 255, 255, 0.15)" , } ) , } ;

Reanimated でアニメーションするダークモード切替を作る

Reanimated を使ってテーマ切替をアニメーション化します。ユーザーがテーマを切り替えたときに滑らかなトランジションやインタラクティブなフィードバックを追加することで、体験を向上させます。