amazon-web-servicesaws-amplifyamplifyjs

How to Override Amplify Sign In Page


I am using the newer version @aws-amplify/ui-react, not the old version which was aws-amplify-react. In the older version you could extend the SignIn and SignUp pages, change the ui to whatever you want, and essential just call the super methods like in these examples: https://medium.com/@pandeysoni/how-to-setup-customize-amplify-authentication-ui-using-hooks-36442f5fdc or https://blog.kylegalbraith.com/2018/11/29/how-to-easily-customize-the-aws-amplify-authentication-ui/ .

In the new package though I can't seem to figure out how to accomplish the equivalent. Here is my current code using the basic amplify ui:

<AmplifyAuthenticator usernameAlias="email">
      <AmplifySignUp
        slot="sign-up"
        usernameAlias="email"
        headerText="Create a new account"
        formFields={[
          {
            type: "email",
            label: "Email",
            placeholder: "Your company email address",
            required: true,
          },
          {
            type: "password",
            label: "Password",
            placeholder: "Password",
            required: true,
          },
        ]}
      />
      <AmplifySignIn
        slot="sign-in"
        usernameAlias="email"
        headerText="Sign in to your account"
      />
      <AppWithRoutes />
</AmplifyAuthenticator>

If I however change it to:

<AmplifyAuthenticator usernameAlias="email">
      <AppWithRoutes />
</AmplifyAuthenticator>

It doesn't seem to change anything other than not using my custom headers and such. So obviously it's pulling a default SignIn/SignUp class. So then I looked here: https://github.com/aws-amplify/amplify-js/blob/bf2f04888ea7e1e5364e1f669bb2847040fde684/packages/amplify-ui-components/src/components/amplify-authenticator/amplify-authenticator.tsx#L204 and found that they use AuthState to determine which auth component to load, and here: https://github.com/aws-amplify/amplify-js/blob/bf2f04888ea7e1e5364e1f669bb2847040fde684/packages/amplify-ui-components/src/components/amplify-authenticator/amplify-authenticator.tsx#L171 they seem to check to see if the auth component slot name exists, and if it doesn't then it returns the default AmplifySignIn class from here: https://github.com/aws-amplify/amplify-js/blob/bf2f04888ea7e1e5364e1f669bb2847040fde684/packages/amplify-ui-components/src/components/amplify-authenticator/amplify-authenticator.tsx#L145 .

My assumption is that if I send in a class with the same slot name that this should determine that the slot is overridden, and no longer return/render the default SignIn page.

interface CustomProps {
  slot: string;
}

const CustomSignIn: React.FC<CustomProps> = props => {
  const { slot } = props;
  return <div>This should show up</div>;
};

<AmplifyAuthenticator usernameAlias="email">
      <CustomSignIn slot="sign-in" />
      <AppWithRoutes />
</AmplifyAuthenticator>

I still end up with the exact same login page with SignIn, SignUp, nothing customized. Am I just missing something really obvious? Do I need some special handling for the slot parameter? Is this no longer possible? I know that with the new package they allowed for more CSS override and customization, but it is still very limited.

If I do:

<AmplifyAuthenticator usernameAlias="email">
    <div slot="sign-in">Hello</div>
    <AppWithRoutes />
</AmplifyAuthenticator>

Then it slows just the sign div with the word Hello, like I would expect. So maybe I'm just handling slot wrong? So it looks like div is of type

React.DetailedHTMLProps<React.HTMLAttributes, HTMLDivElement>

And that is where slot is defined. So I changed my CustomSignIn props to be:

interface CustomProps extends HTMLAttributes<HTMLDivElement> {}

It goes back to the default sign-in sign-up instead of correctly overriding. But if I wrap it in the div like so:

<AmplifyAuthenticator usernameAlias="email">
    <div slot="sign-in"><CustomSignIn /></div>
    <AppWithRoutes />
</AmplifyAuthenticator>

It correctly shows what I'm returning from CustomSignIn. So I can at least get it to render the component I want, but I'd like to start by taking the base AWS UI, extend and tweak it vs completely writing my own.

If anyone has any ideas or knows of any documentation I missed, please let me know. Again, this is with @aws-amplify/ui-react package, NOT aws-amplify-react, which is the legacy version.

Thanks


Solution

  • I've tested it and this should work. You need to put "slot" in standard HTML tags.

    const CustomSignIn: React.FC<CustomProps> = props => {
      return <div slot="sign-in">This should show up</div>;
    };
    
    <AmplifyAuthenticator usernameAlias="email">
      <CustomSignIn />
      <AppWithRoutes />
    </AmplifyAuthenticator>