Penambahan Fitur Login Form Component dan Stories

This commit is contained in:
2023-11-09 12:04:28 +07:00
parent 9ed87f60ed
commit f7044df992
19 changed files with 447 additions and 0 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 52 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 97 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 722 B

After

Width:  |  Height:  |  Size: 722 B

View File

Before

Width:  |  Height:  |  Size: 446 B

After

Width:  |  Height:  |  Size: 446 B

View File

Before

Width:  |  Height:  |  Size: 425 B

After

Width:  |  Height:  |  Size: 425 B

View File

@@ -0,0 +1,9 @@
import loginBg from '@/components/Login/assets/LoginBg.svg'
export const Background = (
) => {
return(
<img src={loginBg} className='absolute w-full h-full no-repeat bg-cover' ></img>
)
}

View File

@@ -0,0 +1,26 @@
import { Button , buttonVariants } from "@/components/ui/button";
interface ButtonProps {
variant ?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
size ?: 'default' | 'sm' | 'lg' | 'icon' ;
label ?: string;
styling?: string;
}
export const Buttons = ( {...props}:ButtonProps )=> {
return (
<Button
className={
(buttonVariants({
variant: props.variant,
size: props.size
}),
props.styling
)
}
>
{props.label}
</Button>
);
};

View File

@@ -0,0 +1,52 @@
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { useState } from "react"
import mail from "@/components/Login/assets/mail.svg"
import lock from "@/components/Login/assets/lock-closed.svg"
import eyeOff from "@/components/Login/assets/eye-off.svg"
import eyeOn from "@/components/Login/assets/eye-on.svg"
export interface InputWithLabelProps {
labelValue ?: string;
// typeName ?: string;
placeHolderName ?: string;
togglePasswordVisibility ?:boolean;
type ?: 'password' | 'email';
onClick ?: () => void;
}
export const InputWithLabel = ({
...props
}:InputWithLabelProps) => {
const [showPassword, setShowPassword] = useState(false);
const togglePasswordVisibility = () => {
setShowPassword(!showPassword);
};
const srcIcon = props.type?.toLowerCase() === 'email' ? mail : props.type?.toLowerCase() === 'password' ? lock : '';
return (
<div className= "flex flex-col items-start gap-4">
<Label > { props.labelValue } </Label>
<div className= "relative">
<img src= { srcIcon } className="w-10% absolute top-0 left-0 py-2.5 pl-2" />
{(props.type === 'password') && (
<img
src={props.togglePasswordVisibility ? eyeOn : eyeOff}
className="w-10% absolute py-2.5 right-0 pr-2 "
onClick={togglePasswordVisibility}
/>
)}
<Input
// type= { props.typeName }
placeholder= { props.placeHolderName }
className={`w-full px-8 `}
type={props.type?.toLowerCase() === 'password' && showPassword ? 'text' : props.type}
/>
</div>
</div>
)
}

View File

@@ -0,0 +1,13 @@
interface LinkBtnProps {
value ?: string;
}
export const LinkBtn = ({
...props
}:LinkBtnProps ) => {
return (
<div className="flex flex-col items-end gap-8">
<a className="text-black font-inter text-sm font-normal underline">{props.value}</a>
</div>
)
}

View File

@@ -0,0 +1,32 @@
import { Background } from "./Background"
import { LogoSismedika } from "./Logo"
import { EmailInput, PasswordInput } from "../stories/Input.stories"
import { ForgetPasswordLink } from "../stories/Link.stories"
import { LoginTitle } from "../stories/Title.stories"
import { LoginButton } from "../stories/Button.stories"
export const LoginForm = (
) => {
return(
<>
<div className="relative w-full h-full">
<div className="object-cover"><Background /></div>
<div className="flex justify-center item-center object-contain">
<div className="inline-grid scale-75 gap-5">
<div className="flex justify-center items-center pb-4">
<LogoSismedika />
</div>
<LoginTitle />
<EmailInput />
<div className="gap-5">
<PasswordInput />
<ForgetPasswordLink />
</div>
<LoginButton />
</div>
</div>
</div>
</>
)
}

View File

@@ -0,0 +1,10 @@
import logoSismedika from '@/components/Login/assets/LogoSismedika.svg'
export const LogoSismedika = (
) => {
return(
<img src={logoSismedika} ></img>
)
}

View File

@@ -0,0 +1,20 @@
import { Label } from "@/components/ui/label"
interface TitleProps {
value : string;
value2 ?: string;
}
export const Title = ({
...props
}: TitleProps ) => {
return (
<div className="flex flex-col justify-center items-center gap-1">
<Label className="text-primary-text text-3xl font-inter font-bold">{props.value}</Label>
<Label className="text-secondary-text text-xs font-inter font-normal text-[#637381]">{props.value2}</Label>
</div>
)
}

View File

@@ -0,0 +1,13 @@
import { Background } from "../loginComponents/Background";
const meta = {
title: 'Component/Login/LoginBackground'
}
export default meta;
export const LoginBg= () => {
return(
<Background/>
)
}

View File

@@ -0,0 +1,40 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Buttons } from '../loginComponents/Button';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Component/Login/Button',
component: Buttons,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
args : {
},
argTypes: {
},
} satisfies Meta<typeof Buttons>;
export default meta;
type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const LoginButton = (args:Story) => {
return(
<Buttons
variant='default'
size='lg'
label='Log In'
styling='flex w-full p-3.5 justify-center items-center gap-2.5 rounded-md border border-black bg-[#F15A29]'
{...args}
/>
)
}

View File

@@ -0,0 +1,73 @@
import { Meta, StoryObj } from "@storybook/react";
import { InputWithLabel } from "../loginComponents/Inputs";
import { boolean } from "zod";
const meta = {
title: "Component/Login/Input",
component: InputWithLabel,
tags: ['autodocs'],
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
args: {
labelValue: "Label Name",
placeHolderName : "Place Holder Name",
},
argTypes: {
type: {
options: ['email', 'password'],
control: { type: 'radio' },
},
togglePasswordVisibility : {action : boolean},
onClick: { action: 'clicked' }
},
} satisfies Meta<typeof InputWithLabel>
export default meta;
type Story = StoryObj<typeof meta>;
// export const ArgumentEmailInput: Story = {
// args: {
// labelValue: "Email",
// typeName: "Email",
// placeHolderName: "Input your Email",
// },
// };
// export const ArgumentPasswordInput: Story = {
// args:{
// labelValue: "Password",
// typeName: "Password",
// placeHolderName: "Input your Password",
// togglePasswordVisibility: false,
// },
// };
export const EmailInput = (args:Story) => {
return(
<InputWithLabel
labelValue="Email"
type="email"
placeHolderName="Input your Email"
{...args}
/>
)
}
export const PasswordInput = (args:Story) => {
return(
<InputWithLabel
labelValue="Password"
type="password"
placeHolderName="Input your Password"
{...args}
/>
)
}

View File

@@ -0,0 +1,27 @@
import { Meta, StoryObj } from "@storybook/react";
import { LinkBtn } from "../loginComponents/LinkButton";
const meta= {
title: 'Component/Login/LinkButton',
component: LinkBtn,
tags: ['autodocs'],
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
args:{
value : "Forget password",
}
}satisfies Meta<typeof LinkBtn>
export default meta;
type Story = StoryObj<typeof meta>;
export const ForgetPasswordLink = (args:Story) => {
return(
<LinkBtn value="Forget Password" {...args} />
)
}

View File

@@ -0,0 +1,21 @@
import { LoginForm } from "../loginComponents/LoginForm";
const meta = {
title: 'Component/Login/Forms',
tags: ['autodocs'],
component: LoginForm,
args:{
value: "value",
value2: "value2"
},
};
export default meta;
export const LoginForms = () => {
return(
<LoginForm/>
)
}

View File

@@ -0,0 +1,29 @@
import { Meta, StoryObj } from "@storybook/react";
import {Title} from "../loginComponents/Title";
const meta = {
title: 'Component/Login/Title',
component: Title,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes:{
},
args: {
value: 'value1',
value2: 'value2',
},
}satisfies Meta<typeof Title>
export default meta;
type Story = StoryObj<typeof meta>;
export const LoginTitle = (args:Story) => {
return(
<Title value={"Port Server"} value2="Welcome back! Enter your account details" {...args} />
)
}