🔐

Amplify UI - Authenticatorのスタイルカスタマイズ

2024/03/16に公開

前提

Amplify UIでサインイン画面を作成するチュートリアル記事はたくさんありますが、その大半はサインイン機能の実装が主であり、見た目の調整については、Amplifyが用意したUIの色の変更など基礎的な範囲に留まっていることが多いです。
一方で、すでに用意されたデザイン・モックがあり、その再現を求められる場合に、基礎だけでは不十分なケースも存在します。
今回は、実際にサインイン・サインアップ画面をAmplify UIで作成した経験を元に、どんなことが可能なのか、基礎〜発展まで検討してみます。

扱わないこと

https://ui.docs.amplify.aws/react/connected-components/authenticator/configuration
に記載されているようなフォーム項目の設定など、スタイルカスタマイズ以外の範囲は今回扱いません。
(上記ページの最後にある、サインアップタブを隠すはスタイルカスタマイズに役立つと思います。)

環境

Next.js, TailwindCSSを前提とします。

何がやれるのか?

https://ui.docs.amplify.aws/react/connected-components/authenticator/customization
基本的には、こちらに書かれていることが全てです。
この記事でもこのページ内をセクションごとに追って解説していきます。

1.Header、Footerのカスタマイズ(例:アカウント作成手順の表示)

https://ui.docs.amplify.aws/react/connected-components/authenticator/customization#headers--footers
ここでいうHeader、Footerはページ自体ではなく、Authenticator内で表示されるHeader、Footerを指します。
Header, Footerは、Authenticator自体に付随するものと、SignIn, SignUp, ConfirmSignUpなど、それぞれのシチュエーションに応じて表示される画面に付随するものの2種類が存在します。

  • Header
    • Custom header - Amplifyのロゴ部分
    • Custom Sign In header - SignIn画面のSign in to your account部分
  • Footer
    • Custom footer - © All Rights Reserved部分
    • Custom Sign In footer - SignIn画面のReset Password部分
      これらの中身は自由に記述することが可能です。
const components = {
  SignUp: {
    Header() {
      return <AuthStepIndicator step={'1'} /> // アカウント作成完了までの手順を番号で表示
    },
  },
}

2.ラベル・テキストのカスタマイズ(例:日本語対応)

ラベル自体の文言をカスタマイズ、またはI18nを使用して、各言語に対応したテキストを表示することができます。言語対応など発展性を考えると、I18nを活用する方法が良いと思います。

I18nについてはこちらをご参照ください。
https://ui.docs.amplify.aws/react/connected-components/authenticator/customization#internationalization-i18n
また、I18nの対象とできるキーとその日本語訳例はこちらにあります。
https://github.com/aws-amplify/amplify-ui/blob/main/packages/ui/src/i18n/dictionaries/authenticator/ja.ts
具体的にどう翻訳したいか固まっていない場合などは、こちらの内容を参考にすることをお勧めします。

ラベル・テキストのカスタマイズ方法はこちらをご参照ください。
https://ui.docs.amplify.aws/react/connected-components/authenticator/customization#labels--text
ただし、こちらの方法でカスタマイズした場合はI18nの全言語に影響が出てしまうため、基本的にはラベル・テキストのカスタマイズではI18nを使う方が良いと考えます。

3.フォーム内容の追加・編集(例:利用規約に同意)

フォームの項目を追加したり、カスタムしたバリデーションを追加したり、フォームの並び順を編集したり、placeholderの文言を変更したりできます。
詳しくは、下記からUpdate Setup TOTP QR Issuer and Usernameあたりまでをご参照ください。
https://ui.docs.amplify.aws/react/connected-components/authenticator/customization#sign-up-fields
ちょうどサインアップ時に利用規約に同意させたい場面があり、サンプルコードが大いに役立ちました。
バリデーションエラーもAmplifyが用意しているものを使えば簡単に実装できます。

auth/page.tsx
const components = {
  SignUp: {
    FormFields() {
      const { validationErrors } = useAuthenticator()
      return (
        <>
          <Authenticator.SignUp.FormFields />
          <CheckboxField
            errorMessage={validationErrors.acknowledgement as string}
            hasError={!!validationErrors.acknowledgement}
            name='acknowledgement'
            value='yes'
            label={
              <div className='flex'>
                <a
                  href='/support/terms'
                  target='_blank'
                  rel='noopener noreferrer'
                  className='underline text-blue-500'
                >
                  利用規約
                </a>
                <span>に同意する</span>
              </div>
            }
          />
        </>
      )
    },
  },
}
(中略)
const Page = () => {
  return (
    <Authenticator
      components={components}
      services={{
        async validateCustomSignUp(formData) {
          if (!formData.acknowledgement) {
            return {
              acknowledgement: '内容をお読みの上、チェックを入れてください',
            }
          }
        },
      }}
    >
  )
}

4.CSS変数の上書き(例:大まかに他のページと色味だけ揃える)

CSS変数で特定の箇所の色味や形状を指定することが可能です。
https://ui.docs.amplify.aws/react/connected-components/authenticator/customization#css-style
単純ではありますが、ホバーしている時のボタンの背景色など、要素によってはなかなか正しい変数が判明せず、ブラウザの開発者環境で変数をしらみつぶしに見ることになりました。
変数さえ分かれば上書きするだけなので、既存のデザインをほぼ変えずに、手っ取り早く色味だけ変更するような時はこちらで良いかもしれません。
ただし、可読性が高いとは言い難いです。

以下のコードは実際にプロジェクトで使用したものです(一部ダミー)。
色味に関しては、こちらでおおよそカバーできると思います。

globals.css
[data-amplify-authenticator] {
  display: block !important;
  --amplify-components-authenticator-container-width-max: 390px;
  --amplify-components-authenticator-router-box-shadow: 0 0 16px var(--amplify-colors-overlay-10);
  --amplify-components-authenticator-router-border-width: 0;
  --amplify-components-authenticator-form-padding: var(--amplify-space-medium)
    var(--amplify-space-xl) var(--amplify-space-xl);
  --amplify-components-fieldcontrol-focus-box-shadow: 0 0 0 2px deepskyblue;
  --amplify-components-tabs-item-color: dimgray;
  --amplify-components-tabs-item-hover-color: midnightblue;
  --amplify-components-tabs-item-active-color: midnightblue;
  --amplify-components-tabs-item-active-border-color: dodgerblue;
  --amplify-components-button-primary-background-color: dodgerblue;
  --amplify-components-button-primary-hover-background-color: midnightblue;
  --amplify-components-button-primary-active-background-color: deepskyblue;
  --amplify-components-button-link-color: dodgerblue;
  --amplify-components-button-link-hover-color: deepskyblue;
  --amplify-components-button-link-hover-border-color: deepskyblue;
  --amplify-components-button-link-hover-background-color: #00bfff1a;
  --amplify-components-button-focus-box-shadow: 0px 0px 0px 2px deepskyblue;
  --amplify-components-checkbox-icon-background-color: dodgerblue;
}

5.ThemeProviderでAuthenticatorを囲み、スタイルを当てる

https://ui.docs.amplify.aws/react/connected-components/authenticator/customization#theme-provider-theme
AmplifyではDesign Tokensを使用したThemeのカスタマイズが可能です。
Chakra-UIと似たコンベンションでできているそうなので、馴染みがある方にはこちらの方が使いやすく、読みやすいかもしれません。(未経験のため詳細不詳)

<ThemeProvider theme={theme}>
  <Authenticator></Authenticator>
</ThemeProvider>

6.amplify-から始まるクラス名・data-から始まる属性名で上書きする(例:大幅に見た目を変更する)

要素ごとに適用されているクラス・属性を上書きしてしまうことで、大幅に見た目を変更することも可能です。例えば

  • ボタンの色だけでなく、形を変更して装飾も追加する
  • パスワードのvisible/hiddenアイコンの表示を調整する

など大掛かりなものはこちらが良さそうです。

amplify-から始まるクラスで構成されているものは、すべてこれで上書きすることができます。
https://ui.docs.amplify.aws/react/connected-components/authenticator/customization#additional-css-styling
また、ドキュメントの例には載っていませんが、data-から始まる属性なども上書き可能です。

以下にいくつか例を記載します。

globals.css
[data-amplify-form] {
    width: calc(100% - 32px);
    padding: 0 32px!important;
    border-radius: 30px!important;
}
.amplify-input {
    color: brown!important;
    font-size: 20px!important;
    background-color: white!important;
    border-radius: 42px!important;
}
.amplify-input:focus {
    box-shadow: none!important;
}
#amplify-id-2 {
    border-radius: 42px 0 0 42px!important;
}
.amplify-button[data-variation='primary'] {
  background: brown;
  border-radius: 42px;
  border: solid 5px white;
  font-size: 20px;
}

やりにくいこと

個々のパーツの調整は、先ほどの⑥:クラスの上書き で可能ですが、全体の構造を変更することが難しく、基本的には

  • HeaderとFooterに書き足す
  • 既存部分のクラスの上書き(あるいは変数の上書き)

でやり繰りすることになります。
そのため、Amplify UIのAuthenticatorを使用する場合は、あらかじめデザイナーと大まかなにできること・難しいことを共有しておいた方がスムーズかもしれません。

最後に

サインイン・サインアップ画面と一言で済ませましたが、実際にはサインイン後の認証画面やパスワードリセット画面など、サインイン・サインアップ画面に関わる要素は意外と多く、またAmplify側が既に:hover:active状態などにも細かくスタイルを当てているため、網羅的にスタイルを調整するのは結構大変でした。
また、特定の条件下でしか出ないエラーメッセージには、まだ日本語訳がgithub上には存在しなかったりなど、状況の再現・その対応にもいくつか苦労しました。
(こちらは別途記事を書くか、contributeできればと考えています)

長文となりましたが、最後までお読みいただきありがとうございました!
まだまだスムーズなスタイリング方法を模索中ではありますが、この記事がお役に立てば幸いです。
不足点・誤りなどありましたら、ぜひお気軽にコメントください!

Discussion