LoginSignup
1
2

ログイン画面と登録画面の切り替え(フロントエンド)

Last updated at Posted at 2023-12-30

はじめに

Next.jsでログイン画面とアカウント登録画面を切り替えるUIを作ったので、メモとして残しておきます。
言語はTypescriptを使用しています。

ポイント

useCallback、useStateを使用する。
今回だと、toggleVariantをspanタグのonClickで指定しているため、
このspanタグのテキストがクリックされたときに、画面を切り替えることが可能になる。

実装例

画像部分は好きなものに置き換えてください。(背景とロゴの部分2箇所)

auth.tsx
import { useCallback, useState } from "react";
import Input from "../components/Input";

const Auth = () => {
  const [name, setName] = useState('')
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  // ログイン画面、アカウント登録画面の切り替え
  const [variant, setVariant] = useState('login')
  
  // このtoggleVariantを、spanタグのonclickと紐づけている。
  const toggleVariant = useCallback(() => {
    setVariant((currentVariant) => currentVariant === 'login' ? 'register' : 'login')
  }, [])

  return (
    <div className="relative h-full w-full bg-[url('/images/任意の画像ファイル')] bg-no-repeat  bg-fixed bg-cover">
      <div className="bg-black w-full h-full lg:bg-opacity-50">
        <nav className="">
          <img src="/images/任意の画像ファイル" alt="Logo" className="h-24 w-auto" />
        </nav>
        <div className="flex justify-center">
          <div className="bg-black bg-opacity-90 px-14 py-14 self-center lg:w-2/5 lg:max-w-md rounded-md">
            <h2 className="text-white text-4xl mb-8 font-semibold">
              {/* 登録済みの場合、Sign In, 未登録の場合はRegister */}
              {variant === 'login' ? 'Sign In' : 'Register'}
            </h2>
            <div className="flex flex-col gap-4">
              {/* 氏名は登録時のみ入力 */}
              {variant === 'register' && (
                <Input
                  id="name"
                  onChange={(event:any) => setName(event.target.value)}
                  type="name"
                  label="Name"
                  value={name}
                />
              )}
              <Input
                id="email"
                onChange={(event:any) => setEmail(event.target.value)}
                type="email"
                label="Email"
                value={email}
              />
              
              <Input
                id="password"
                onChange={(event:any) => setPassword(event.target.value)}
                type="password"
                label="Password"
                // usestateのpassword
                value={password}
              />
              </div>
              <button className="bg-red-600 py-3 text-white rounded-md w-full mt-10 hover:bg-red-700 transition">
                {variant === 'login' ? 'Login' : 'Sign Up'}
              </button>
              <p className="text-neutral-500 mt-7">
                {variant === 'login' ? 'First time using Netflix?' : 'Already have an account?'}
                {/* このボタンを押したときに、アカウント作成、ログインの画面が切り替わるようにする */}
                <span onClick={toggleVariant} className="text-white ml-1 hover:underline cursor-pointer">
                  {variant === 'login' ? 'Create an account' : 'Sign In'}
                </span>
              </p>
          </div>
        </div>
      </div>
    </div>
  );
}

export default Auth;

auth.tsxで使用している、入力フォームのコンポーネント(Input)は以下のような実装

input.tsx
interface InputProps {
  id: string;
  onChange: any;
  value: string;
  label: string;
  type?: string;
}

const Input: React.FC<InputProps> = ({
  id,
  onChange,
  value,
  label,
  type,
}) => {
  return (
    // inputタグとlabelタグの位置を揃えるには、親タグのclassNameにrelativeを指定する
    <div className="relative">
      <input
        id={id}
        type={type}
        value={value}
        onChange={onChange}
        className="
          block
          rounded-md
          px-6
          pt-7
          pb-3
          w-full
          text-md
          text-white
          bg-neutral-700
          appearance-none
          focus:outline-none
          focus:ring-0
          peer
        "
        // この空のplaceholderがないと、カーソルを合わせる前から文字が小さくなってしまう。
        placeholder=""
        />
      <label
      // 入力時はplaceholderの文字が上側に表示されるようにする
      className="
        absolute
        text-md
        text-zinc-400
        duration-150
        transform
        -translate-y-3
        scale-75
        top-5
        z-10
        origin-[0]
        left-5
        peer-placeholder-shown:scale-100
        peer-placeholder-shown:translate-y-0
        peer-focus:scale-75
        peer-focus:-translate-y-4
      "
      htmlFor={id}>
        {label}
      </label>
    </div>
  )
}
export default Input

ブラウザ画面

背景画像、ロゴともDALL-E3で作ってもらいました。
クオリティ高くて素晴らしいです!!
https://openai.com/dall-e-3

ログイン画面

スクショ(大).jpeg

アカウント登録画面(Create an accountをクリックすると切り替わる)

スクショ1(大).jpeg

終わりに

このようなログイン画面は作る機会多いと思うので、サクッと作れるようにしておきたいですよね。
また初めにNext.jsのプロジェクトを作成する際に、色々と聞かれるのですが、

✔ Would you like to use App Router? (recommended) … No

この問いをNoにしておかないと、pagesディレクトリが作成されず、appディレクトリが作成されてしまうので、気を付けてください。

こちらの記事のおかげで絶望せずに済みました。筆者の@mu_tomoyaさん、ありがとうございます!
参考:https://qiita.com/mu_tomoya/items/7545bea039e82e483f9e

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2