Amplify UI の Authenticator コンポーネント tips まとめ
はじめに
こんにちは!株式会社POLでエンジニアをやっている @show_kanamaru です!
POL は「研究者の可能性を最大化するプラットフォームを創造する」をビジョンに、理系学生に特化した採用サービス、および研究開発者・技術者に特化した転職/採用サービスの2サービスを運営しています。
今更ながら Amplify UI の新しいバージョンを触ってみたので、使ったみて学んだ tips を共有したいと思います!
背景
Amplify はアプリケーションを高速かつ簡単に構築できるサービスで、 UI Components も用意されています。この UI Components に提供されている Authenticator コンポーネントを使用することで、簡単に認証機能を実装することができます。
今までは Amplify UI のバージョン1系を使っていました。
バージョン1系でも新規登録、ログインをする分には問題なかったのですが、細かなカスタマイズができない点が不便でした。
そこで、2021年11月に AWS Amplify UI が新たな Authenticator コンポーネントをリリースしました!
・新たなレイアウトとテーマでビジュアルを一新。
・Amazon Cognito User Pools を使用した Facebook、Google、Amazon および Apple へのソーシャルサインイン
・Amplify Admin UI と Amplify CLI での設定不要
・よりよいフォーム: パスワードとパスワードの表示/非表示機能、カスタムサインアップ属性、パスワード管理者サポートなど
今回、この新しいバージョンの Authenticator コンポーネントを使う機会があったので、公式ドキュメントには書いてない細かな tips を共有したいと思います!
Sign Up Fields
新規登録の際に利用規約やプライバシーポリシーに同意してもらうサービスがほとんどだと思います。新バージョンではこのような場合のチェックボックスが簡単に追加できるようになりました!
ただ、ドキュメント通りに実装すると、以下の画像のように最初からバリデーションエラー文が表示されてしまいます。
理想的には初期表示ではこのエラーは表示させたくないですよね。
なので、 touched という state を持たせて、一度チェックボックスに触るまではエラーを表示しないようにしました。
// Auth.tsx
import React from 'react';
import {
AmplifyProvider,
Authenticator,
useAuthenticator,
} from '@aws-amplify/ui-react';
import { Checkbox } from './Checkbox';
export const Auth = () => (
<AmplifyProvider>
<Authenticator
initialState="signIn"
components={{
SignUp: {
FormFields() {
const { validationErrors } = useAuthenticator();
return (
<>
<Authenticator.SignUp.FormFields />
<Checkbox validationErrors={validationErrors} />
</>
);
},
},
}}
services={{
async validateCustomSignUp(formData) {
if (!formData.acknowledgement) {
return {
acknowledgement: '利用規約、プライバシーポリシーに同意が必要です',
};
}
},
}}
/>
</AmplifyProvider>
);
// Checkbox.tsx
import React, { useState } from 'react';
import { CheckboxField } from '@aws-amplify/ui-react';
type Props = {
validationErrors: {
[key: string]: string;
};
};
export const Checkbox: React.FC<Props> = ({ validationErrors }) => {
const [touched, setTouched] = useState<boolean>(false);
return (
<CheckboxField
errorMessage={validationErrors.acknowledgement}
hasError={touched && !!validationErrors.acknowledgement}
name="acknowledgement"
value="yes"
onChange={() => setTouched(true)}
label={
<p>
<a
href="#"
target="_blank"
rel="noreferrer"
>
利用規約
</a>{' '}
、
<a
href="#"
target="_blank"
rel="noreferrer"
>
プライバシーポリシー
</a>
に同意する
</p>
}
/>
);
};
※ Auth.tsx に useState を持たせると、チェックボックスを触ったタイミングで form が再レンダリングされてしまい、form の中身が消えてしまうのでコンポーネントを分離する必要があります。
こうすることで、初期表示時のエラーが出なくなりました!
Customization
個人的にバージョン1系からアップデートで一番嬉しいのがカスタマイズ性の向上です。 header や footer の追加、ソーシャルログインボタンの追加などが簡単にできるようになりました。
新規登録後の画面はデフォルトでは以下のようになるのですが、この画面のカスタマイズでハマった点が1つあったので共有します。
Internationalization の機能もあるため、以下のようにすれば簡単に日本語に対応させることができます。
import Amplify, { I18n } from 'aws-amplify';
import awsconfig from 'src/aws-exports';
import '@aws-amplify/ui-react/styles.css';
Amplify.configure(awsconfig);
I18n.setLanguage('ja');
I18n.putVocabularies({
ja: {
Confirm: '送信',
'Resend Code': 'コードを再送',
'We Emailed You': 'メールを送信しました',
'Enter your code': '認証コード',
},
});
しかし、
「Your code is on the way. To log in, enter the code we emailed to s***@g***. It may take a minute to arrive.」
の部分は登録したアドレスによって文字列が変わるので、日本語化が難しかったので、以下のように ConfirmSignUp コンポーネントをカスタマイズしました。
// Auth.tsx
import React from 'react';
import {
AmplifyProvider,
Authenticator,
Heading,
Text,
} from '@aws-amplify/ui-react'
export const Auth = () => (
<AmplifyProvider>
<Authenticator
initialState="signIn"
components={{
ConfirmSignUp: {
Header() {
return (
<>
<Heading level={4}>メールを送信しました</Heading>
<Text>
送信した認証コードを入力してください。
<br />
※メールが届くまでに数分かかる可能性があります。
</Text>
</>
);
},
},
}}
/>
</AmplifyProvider>
);
すると、
となり、Text の部分が上書きされず、、
「Your code is on the way. To log in, enter the code we emailed to s***@g***. It may take a minute to arrive.」
は Header の中ではなく、 Form の DOM に定義されていたので上書きができていませんでした。
(以下のように ConfirmSignUp コンポーネントは Header と Footer しか上書きができません)
なので、今回は仕方なく css でクラス名を指定して、無理やり非表示に。。(他に良いやり方があったらぜひ教えてください)
※ .amplify-text だけだと、別のコンポーネントで使用している text も消えてしまうのでご注意を!
// Auth.tsx
import React from 'react';
import {
AmplifyProvider,
Authenticator,
Heading,
} from '@aws-amplify/ui-react'
import Typography from '@mui/material/Typography';
export const Auth = () => (
<AmplifyProvider>
<Authenticator
initialState="signIn"
components={{
ConfirmSignUp: {
Header() {
return (
<>
<Heading level={4}>メールを送信しました</Heading>
// @aws-amplify/ui-reactのTextを使用すると、ここも消えてしまうため自ら定義
<Typography sx={{ fontSize: 14 }}>
送信した認証コードを入力してください。
<br />
※メールが届くまでに数分かかる可能性があります。
</Typography>
</>
);
},
},
}}
/>
</AmplifyProvider>
);
// style.css
[data-amplify-authenticator-confirmsignup] .amplify-text {
display: none;
}
無事、やりたいことが実現できました!!!
Styling
スタイルもバージョン1と比べるとかなり細かく設定できるようになりました。ただ、通常時だけでなく、hover , active , focus 時も設定できるため、項目が多すぎて対応する CSS Variable を探すのが大変でした。
そこで、プチテクニックを紹介!
ブラウザの開発ツールの「Elements」タブで、スタイルを設定したい html 要素の「Styles」タブの上部の「:hov」というボタンをクリックすると、 hover , focus , active 状態の css を確認できます。
画像の例だと、ログインボタンの focus 時の背景色は、 var(--amplify-components-button-primary-focus-background-color) でデフォルト設定がしてあることになります。
このやり方で、それぞれの要素のそれぞれの状態の CSS Variable を簡単に取得できるので、細かいスタイル設定が楽にできるようになります!
おわりに
今回は Amplify UI の新バージョンを触ってみました!バージョン1系に比べてかなり使いやすくなりましたね!ただ細かいところはまだ自分で実装する必要があるところも多いので、時間があるときにプルリクエスト出してみようかなと思いました(今年は OSS コントリビュートするぞ!)
そして、株式会社POL ではエンジニア、デザイナー、プロダクトマネージャーを大募集してます!お話しだけでも構いませんのでお気軽にお声がけください!!!