Stripe UI拡張機能入門: FocusViewを使って、詳細画面や追加のステップ用の画面を追加する



この記事は、[Stripe Apps を25日間紹介し続ける Advent Calendar 2022](https://qiita.com/advent-calendar/2022/stripe-apps) 10日目の記事です。

![スクリーンショット 2022-11-24 17.56.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/e0261865-0418-daa2-423a-5f4d70558b1b.png)

昨日の記事にて、顧客情報やサブスクリプションの情報を更新するフォームの作り方を紹介しました。

https://qiita.com/hideokamoto/items/362ca7e572b8e0e12d66

しかしフォームを作り始めると、「もう少し表示幅を広くとりたい」ケースも増えてきます。

今回の記事では、より多くの情報・フォームを表示できる`FocusView`を紹介します。

## デフォルトの表示幅はあまり広くない

Stripe Appsのアプリは、ダッシュボード右側のウィジェットとして表示されます。

そのため、横幅は320px程度と、多くの情報を出すにはすこし手狭です。

![スクリーンショット 2022-12-06 15.13.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/8cef3133-c3f6-0957-1a1e-32f1748b759f.png)

## FocusViewで大きな画面を利用する

`FocusView`は、モーダルのような扱いをするコンポーネントです。

`useState`などで表示・非表示を制御されつつ、子要素のより広い画面で表示できます。

```tsx
import { Box, Button, FocusView } from "@stripe/ui-extension-sdk/ui";
import { FC, useState} from 'react'

const MegaMenu:FC = () => {
  const [open, isOpen] = useState(false)
  return (
    <>
      <Box>
        <Button
          type="primary"
          css={{ width: 'fill', alignX: 'center' }}
          onPress={() => isOpen(!open)}
        >Open Editor</Button>
      </Box>
      <FocusView
        title="Menu"
        shown={open}
        setShown={isOpen}
      >
        <Box>Hello</Box>
      </FocusView>
    </>
  )
}
```

このコンポーネントを表示させると、アプリ上にボタンが表示されます。

![スクリーンショット 2022-12-06 15.21.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/5fc351ba-115d-7bbd-7e3d-2149a7524e5d.png)

ボタンをクリックすると、オーバーレイする形で、新しい画面が出てきます。

![スクリーンショット 2022-12-06 15.21.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/096ffbd0-31f3-51aa-7046-a03e31568c46.png)

## 「保存」「キャンセル」などのアクションを設定する

`FocusView`には、保存・キャンセル・閉じるなどのアクションを表示するためのプロパティが用意されています。

```diff_typescript
      <FocusView
        title="Menu"
        shown={open}
        setShown={isOpen}
+        primaryAction={(
+          <Button type="primary">Save</Button>
+        )}
+        secondaryAction={(
+          <Button>Cancel</Button>
+        )}
      >
        <Box>Hello</Box>
      </FocusView>
```

それぞれのプロパティを追加すると、画面下部にアクションボタンが表示されます。

![スクリーンショット 2022-12-06 15.28.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/82561057-1ba5-00d5-da59-0fac637ff392.png)

画面を閉じたい場合は、`secondaryAction`の`Button`タグを使います。

`isOpen`などの`useState`で作成した表示非表示を制御する関数を設定しましょう。

```diff_typescript
        secondaryAction={(
-          <Button>Cancel</Button>
+          <Button onPress={() => isOpen(false)}>Cancel</Button>
        )}
```

## 閉じる前に、確認メッセージを出す

複数ステップにわたるウィザードの途中や、情報入力が完了していない状態では、FocusViewを閉じる前に確認画面を出す要件が発生します。

その場合、`confirmCloseMessages`を利用して、本当に画面を閉じて良いかを確認できます。

```diff_typescript
      <FocusView
        title="Menu"
        shown={open}
        setShown={isOpen}
        primaryAction={(
          <Button type="primary">Save</Button>
        )}
        secondaryAction={(
          <Button onPress={() => isOpen(false)}>Cancel</Button>
        )}
+        confirmCloseMessages={{
+          title: "Are you sure?",
+          description: "Your form data will be cleared",
+          cancelAction: "Cancel",
+          exitAction: "Understand"
+        }}
      >
```

この値を設定すると、`FocusView`を閉じようとした際に、確認画面が開きます。

![スクリーンショット 2022-12-06 15.34.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/014bc9be-3c23-5bfd-679a-c30b26dbfe84.png)

`exitAction`に設定したラベルのボタンをクリックすると、このままクローズされます。

## ドキュメント

https://stripe.com/docs/stripe-apps/components/focusview

https://stripe.com/docs/stripe-apps/patterns/progress-stepping



## Stripe Appsひとりアドベントカレンダー 2022

今年ベータリリースされたばかりのStripe Appsは、まだ日本語の情報が多くありません。

そこでQiita Advent Calendar 2022にて、毎日Stripe Appsについての情報を投稿します。

https://qiita.com/advent-calendar/2022/stripe-apps

ノーコードで利用する方法や、開発するためのTipsなども紹介予定ですので、ぜひ購読をお願いします。