mcpField
S
styles

styles

github.com/androidデザイン・UI10.0k2.2k 回インストール2 日前に更新
リポジトリ

styles について

Jetpack ComposeのカスタムコンポーネントとテーマをStyles APIへ移行するスキルです。スタイル定義、状態管理、表示検証を扱います。実験的機能で、Composeのalpha APIが必要です。Material Designコンポーネントのスタイルには対応しません。

主な機能

  1. 01テーマ構成とデザイントークンを分析
  2. 02ComponentStylesを作成してカスタムテーマに接続
  3. 03コンポーネントをStyles APIへ移行
  4. 04インタラクション状態とModifier.styleable()を処理
  5. 05スクリーンショットとUIテストで表示を検証

活用シーン

  1. 01カスタムコンポーネントのスタイル引数をStyleへ移行
  2. 02デザイントークンをコンポーネントスタイルに集約
  3. 03スタイル移行後の表示崩れを確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/android/skills --skill styles

インストール後、Claude Code で/stylesを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/android/develop/ui/compose/designsystems/
custom.md
references/android/develop/ui/compose/styles/
fundamentals.md
state-animations.md
styles-vs-modifiers.md
theming.md

詳細

制限事項

  • このスキルは EXPERIMENTAL であり、Compose をアルファ版に更新して Experimental API をオプトインする必要があることをユーザーに警告してください。
  • このスキルはカスタム UI コンポーネントとカスタムテーマのみをサポートします。
  • このスキルは Material Design コンポーネントの Style をサポートしません。

前提条件

1. 依存関係をアップグレードする
  • プロジェクトでは compileSdk バージョン 37 以降を使用する必要があります。
  • プロジェクトでは androidx.compose.foundation:foundation バージョン 1.12.0-alpha01 以降を使用する必要があります。
  • または、プロジェクトでは Compose BOM バージョン 2026.04.01 以降を使用する必要があります。
  • API では次のパッケージを正確に指定する必要があります:import androidx.compose.foundation.style.Style
2. 実験的 API を有効にするコンパイラーオプションを設定する

プロジェクトレベルで実験的 API をオプトインする必要があります。次のブロックをモジュールの build.gradle.kts に追加してください。

kotlin {
    compilerOptions {
        jvmTarget = JvmTarget.fromTarget("17")
        freeCompilerArgs.add("-opt-in=androidx.compose.foundation.style.ExperimentalFoundationStyleApi")
    }
}

主なワークフローとガイド

特定の開発タスクを完了するには、公式ドキュメントを参照してください。

段階的な移行ワークフロー

ステップ 1:テーマ構造を分析する
  1. 中心となるテーマファイル(Theme.kt など)を探します。
  2. デザイントークンを特定します。色、タイポグラフィ、シェイプの参照(LocalColorScheme、LocalTypography、LocalShapes など)を書き留めます。
  3. プロジェクトに Jetpack Compose の依存関係がない場合は、作業を中止します。まず Jetpack Compose に移行するようユーザーに指示してください。
  4. プロジェクトが androidx.compose.material.MaterialTheme をインポートしている場合は、続行する前に Material 3 への移行を推奨してください。
ステップ 2:ComponentStyles を作成する
  1. テーマディレクトリに ComponentStyles.kt という名前の新しいファイルを作成します。

  2. コンポーネントのスタイルを格納するトップレベルのデータクラスを定義します。たとえば、Jetsnack では JetsnackStyles という名前です。

    object ExampleComponentStyles {
        val customButtonStyle: Style = {
    
        }
        val customTextFieldStyle: Style = {
    
        }
    }
    

  3. このクラスは静的な参照を使ってカスタムテーマから公開します。ここでは必要ないため、CompositionLocals は使用しないでください。

    @Immutable
    class JetsnackTheme(
        // other Design system properties
    ) {
        companion object {
            val colors: CustomThemingWithStyles.JetsnackColors
                @Composable @ReadOnlyComposable
                get() = LocalJetsnackTheme.current.colors
            // ...
    
            // add helper static reference
            val styles: ComponentStyles = ComponentStyles
        }
    }
    

  4. CompositionLocals を使って公開している場合は、テーマトークンを直接参照する StyleScope の拡張機能を用意します。例:

    val StyleScope.colors: JetsnackColors
        get() = LocalJetsnackTheme.currentValue.colors
    
    val StyleScope.typography: androidx.compose.material3.Typography
        get() = LocalJetsnackTheme.currentValue.typography
    
    val StyleScope.shapes: Shapes
        get() = LocalJetsnackTheme.currentValue.shapes
    

ステップ 3:コンポーネントを Styles API に移行する

カスタムコンポーネント(例:CustomButton)ごとに、次の手順を完了してください。

  1. 視覚的なベースラインを確立する(エミュレーターが利用できる場合):
    • Android エミュレーターを実行できない場合: この手順全体をスキップして、ステップ 2 に進んでください。
    • Android エミュレーターを実行できる場合: ベースラインのスクリーンショットを取得するため、次のいずれかを実施してください。
      • オプション A: コンポーネントの既存のスクリーンショットテストを探して実行します。
      • オプション B(テストが存在しない場合): プロジェクトで既に使用しているテストフレームワークを使ってテストを作成し、実行します。
      • オプション C(フレームワークが存在しない場合): UI Automator または Espresso を使って最小限のスクリーンショットテストを作成し、実行します。
  2. 個別のスタイル設定パラメーターを削除します:シグネチャから backgroundColor、shape、textStyle、contentPadding など、StyleScope がサポートするスタイル設定パラメーターを削除します。
  3. スタイルパラメーターを追加します:関数シグネチャに style: Style = Style を追加します。デフォルト値が必ず Style であることを確認してください(例:style: Style = Style)。ChipStyleDefault など、特定のスタイルをデフォルト値にしないでください。
  4. 状態の追跡を宣言します:コンポーネントが操作可能な場合は、インタラクションソースを使って MutableStyleState を作成します。Composable 内で isEnabled などの状態フィールドを更新し、状態を正しく追跡してください。
  5. スタイル適用可能なモディファイアを適用します:ルート要素の個別のレイアウトモディファイアを Modifier.styleable() に置き換えます。
  6. デフォルト値を ComponentStyles に移動します:コンポーネント定義内のハードコードされた値を、ComponentStyles.kt の専用の Style インスタンスに移動します。
  7. コンポーネントを検証します: 最初に取得したベースラインのスクリーンショット画像と、新しい Composable のレンダリング済み Compose Preview を比較します。文字列の内容は無視し、レイアウトとスタイルに注目してください。見た目が一致するまで Compose コードを調整します。確認できたら、新しい Composable の Compose UI テストを作成します。
移行例

移行前:

@Composable
fun CustomButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    backgroundColor: Color = JetsnackTheme.colors.brandLight,
    disabledBackgroundColor: Color = JetsnackTheme.colors.brandSecondary,
    shape: Shape = JetsnackTheme.shapes.extraLarge,
    textStyle: TextStyle = JetsnackTheme.typography.labelLarge,
    enabled: Boolean = true,
    content: @Composable RowScope.() -> Unit,
) {
    val interactionSource = remember { MutableInteractionSource() }
    Row(
        modifier
            .clickable(onClick = onClick, indication = null, interactionSource = interactionSource)
            .background(if (enabled) backgroundColor else disabledBackgroundColor, shape)
            .defaultMinSize(58.dp, 40.dp),
        horizontalArrangement = Arrangement.Center,
        verticalAlignment = Alignment.CenterVertically,
        content = content,
    )
}

移行後:

// Exposed via ComponentStyles.kt
object ComponentStyles {
    val buttonStyle = Style {
        background(colors.brandLight)
        shape(shapes.extraLarge)
        minWidth(58.dp)
        minHeight(40.dp)
        textStyle(typography.labelLarge)
        disabled {
            background(colors.brandSecondary)
        }
    }
}

@Composable
fun CustomButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    style: Style = Style,
    enabled: Boolean = true,
    content: @Composable RowScope.() -> Unit,
) {
    val interactionSource = remember { MutableInteractionSource() }
    val styleState = rememberUpdatedStyleState(interactionSource) {
        it.isEnabled = enabled
    }
    Row(
        modifier
            .clickable(onClick = onClick, indication = null, interactionSource = interactionSource)
            .styleable(styleState, JetsnackTheme.styles.buttonStyle, style),
        horizontalArrangement = Arrangement.Center,
        verticalAlignment = Alignment.CenterVertically,
        content = content,
    )
}

ステップ 4:変更を検証する
  1. プロジェクトをビルドします。コンパイルエラーがないことを確認してください。
  2. モジュールのスクリーンショットテストを実行します。
  3. 更新前と更新後のコンポーネントを使ったアプリ全体の見た目を比較します。レイアウトに視覚的なリグレッションが発生していないことを確認してください。

コメント