Relay のスタイルマッピングとコンポーネントマッピング

# はじめに

[Relay](https://developer.android.com/jetpack/compose/tooling/relay?hl=ja) のスタイルマッピングとコンポーネントマッピングについて調べてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/4fdd1098-5aa7-2459-42a1-b84765cb28d0.png)


# スタイルマッピング

https://developer.android.com/jetpack/compose/tooling/relay/mapping-styles-to-compose-theme?hl=ja

Figma におけるスタイルと Jetpack Compose におけるスタイルはどのように対応付けるのでしょうか。これは結構愚直にやるしかなく、個別にマッピングファイルを書く必要があります。

:::note info
ここでいうスタイルとは Jetpack Compose でいうところの `Color` や `TextStyle` のことを指します。
:::

## マッピングの構成ファイル

Google が公開している Figma の Material3/Material 2 Design Kit を使用している場合は予め用意されているマッピングを使用することができます。ただし、実際のプロダクトの場合カスタムされたデザインシステムを使用していることが多いのではないかと思います。その場合は独自のマッピングを JSON で記述します。


[公式ドキュメント](https://developer.android.com/jetpack/compose/tooling/relay/mapping-styles-to-compose-theme?hl=ja#configuration-files)にある例を引用します。マッピングの構成ファイルはデザイントークンへのマッピング(`"figma"`セクション)、Compose の Theme へマッピング(`"compose"` セクション`)の2段構えになっています。

`"options"` セクションでは Theme のパッケージを指定します。

```json
{
  "figma": {
    "colors": {
      "my-app-theme/sys/light/primary": "myapp.sys.color.primary",
      "my-app-theme/sys/light/primary-container": "myapp.sys.color.primary-container",
      "my-app-theme/sys/light/background": "myapp.sys.color.background",
      "my-app-theme/sys/light/on-background": "myapp.sys.color.on-background",
      "my-app-theme/sys/dark/background": "myapp.sys.color.background",
      "my-app-theme/sys/dark/on-background": "myapp.sys.color.on-background"
    }
  },
  "compose": {
    "colors": {
      "myapp.sys.color.primary": "MaterialTheme.colorScheme.primary",
      "myapp.sys.color.primary-container": "MaterialTheme.colorScheme.primaryContainer",
      "myapp.sys.color.background": "MaterialTheme.colorScheme.background",
      "myapp.sys.color.on-background": "MaterialTheme.colorScheme.onBackground"
    },
    "options": {
      "packages": {
        "MaterialTheme": "androidx.compose.material3"
      }
    }
  }
}
```

マッピングの構成ファイルを作るのは結構大変そうですが、一度やってしまえば変更する機会は少なさそうなのでやれないことはないかなといった印象です。

# コンポーネントマッピング

https://developer.android.com/jetpack/compose/tooling/relay/mapping-components-to-existing-code?hl=ja

UI の中には Figma で表現できないアニメーションや複雑な動作を含むものがあります。そのような UI を Relay ではどう扱えばよいでしょうか。そのための仕組みがコンポーネントマッピングです。

## マッピングの構成ファイル

例えば以下のような Google Map が埋め込まれているようなカードの UI を考えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/5a317f5d-2fbe-6ccd-1ff7-ff3425fd56c6.png)

Figma で作成されたこのカードの UI を Jetpack Compose のコードに変換する際、地図の部分は実際の Google Map のコンポーザブルに置き換えられることが望ましいです。そのためには`google-map.map` を作成し、以下のように記述します。 (mapが連続して分かりづらくてすみません。)

```json
{
    "target": "CardGoogleMap",
    "package": "com.example.myApp"
}
```

マッピングのファイル名は UIパッケージのディレクトリの名前と一致させる必要があります。また、`ui-package-resources/mappings` ディレクトリに配置します。

## 追加のディレクティブ

マッピングには追加のディレクティブを記述することができます。例えば以下のように記述することで、`google-map` の `location` パラメータを `CardGoogleMap` の `url` パラメータへとマッピングすることができます。

```json
{
    "target": "CardGoogleMap",
    "package": "com.example.myApp",
    "fieldMappings": [
        {
            "type": "parameter",
            "source": "location",
            "target": "url"
        }
    ]
}
```

ちなみに `type: parameter` の他に、`type: lambda`も使用できます。さらに将来的には`type: modifier` がサポートされ Compose の Modifier へのマッピングも可能になります。

# まとめ

Relay のスタイルマッピングとコンポーネントマッピングについて簡単に紹介しました。ここまで複雑になってくると、徐々に Relay を実際に運用する上でのコストが心配になってくる感じがしています。一旦はトレードオフとして受け止めつつ、より少ない手数で済むアップデートを期待したいと思います。

# 参考

* https://developer.android.com/jetpack/compose/tooling/relay/mapping-styles-to-compose-theme?hl=ja
* https://developer.android.com/jetpack/compose/tooling/relay/mapping-components-to-existing-code?hl=ja