Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Aizad/FEQ-1560/Password Input Field #46

Merged
merged 21 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ae6ef49
chore: added Password Input field
aizad-deriv Jan 30, 2024
af8378b
chore: import PasswordInput inside of main.ts
aizad-deriv Jan 30, 2024
13b9d33
chore: added password meter colors, width and colors
aizad-deriv Jan 30, 2024
8f43383
fix: added helperMessage based on score
aizad-deriv Jan 30, 2024
97da93d
fix: added warning variant inside for helperMessage
aizad-deriv Jan 30, 2024
d6c382d
chore: refactor PasswordMeter as a child component
aizad-deriv Jan 30, 2024
83060c3
added hidePasswordMeter
aizad-deriv Jan 30, 2024
7ea72ac
add package-lock
aizad-deriv Jan 31, 2024
12458ce
fix: added variants according to production
aizad-deriv Jan 31, 2024
ce0cfcf
change props to rest to match the rest of the components
aizad-deriv Jan 31, 2024
afb6eca
added show password and hide password icon
aizad-deriv Jan 31, 2024
c262641
WIP: 83060c3 added hidePasswordMeter
aizad-deriv Jan 31, 2024
6fdaad7
fix: change css for input
aizad-deriv Jan 31, 2024
6c861be
seperate password icons into their own dedicated file
aizad-deriv Jan 31, 2024
e65415c
added colors for icon
aizad-deriv Jan 31, 2024
f925a15
implement BEM class naming conventions inside of Password Meter
aizad-deriv Feb 1, 2024
7b1d442
implement BEM class naming conventions inside of Input
aizad-deriv Feb 1, 2024
fced196
fix remove duplicated scss variables
aizad-deriv Feb 1, 2024
c401ee1
Merge branch 'main' of github.com:deriv-com/ui into aizad/FEQ-1560/pa…
aizad-deriv Feb 1, 2024
35fea18
fix: change types and added stylings to Input and PasswordInput
aizad-deriv Feb 1, 2024
5025c17
chore: added Storybook for password input component
aizad-deriv Feb 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions lib/components/Input/HelperMessage.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
$inactive_color: #999999;
$success_color: #4bb4b3;
$warning_color: #ffad3a;
$error_field: #ec3f3f;

.deriv-helper-message {
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 18px;
&--general {
color: $inactive_color;
}
&--success {
color: $success_color;
}
&--warning {
color: $warning_color;
}
&--error {
color: $error_field;
}
}
16 changes: 9 additions & 7 deletions lib/components/Input/HelperMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import React, { ReactNode } from "react";
import clsx from "clsx";
import { InputVariants } from ".";
import "./Input.scss";
import "./HelperMessage.scss";

export interface HelperMessageProps {
error?: boolean;
message?: ReactNode;
variant?: InputVariants;
disabled?: boolean;
}

const MessageVariant: Record<InputVariants, string> = {
general: "deriv-helper-message__general",
success: "deriv-helper-message__success",
error: "deriv-helper-message__error",
type TMessageVariant = Exclude<InputVariants, "disabled">;
const MessageVariant: Record<TMessageVariant, string> = {
general: "deriv-helper-message--general",
success: "deriv-helper-message--success",
warning: "deriv-helper-message--warning",
error: "deriv-helper-message--error",
};

const HelperMessage = ({
Expand All @@ -25,7 +26,8 @@ const HelperMessage = ({
<p
className={clsx("deriv-helper-message", {
[MessageVariant["general"]]: disabled,
[MessageVariant[error ? "error" : variant]]: !disabled,
[MessageVariant[error ? "error" : (variant as TMessageVariant)]]:
!disabled,
})}
>
{message}
Expand Down
116 changes: 49 additions & 67 deletions lib/components/Input/Input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,44 @@ $disabled_color: #d6d6d6;
$inactive_color: #999999;
$active_color: #85acb0;
$success_color: #4bb4b3;
$warning_color: #ffad3a;
$error_field: #ec3f3f;
$inactive_color: #999999;
$border: 1px solid;

.deriv-input {
display: inline-block;
display: inline-flex;
position: relative;
border-radius: 4px;
width: 328px;
box-sizing: border-box;
text-align: left;
padding: 10px 16px;
border: $border;

&--general {
border-color: $inactive_color;
&:focus-within {
border-color: $active_color;
}
}
&--error {
border-color: $error_field;
}
&--success {
border-color: $success_color;
}

&--active {
border-color: $active_color;
}

&--field {
&--disabled {
border-color: $disabled_color;
}

&__field {
width: 100%;
padding: 10px 16px;
outline: none;
border-radius: 4px;
width: 328px;
box-sizing: border-box;
outline: none;
text-align: left;
&:disabled {
border: $border $disabled_color;
color: $inactive_color;
}
&::placeholder {
visibility: hidden;
}
Expand All @@ -36,27 +53,9 @@ $border: 1px solid;
height: fit-content;
}
}
&__general {
border: $border $inactive_color;
&:focus {
border: $border $active_color;
}
}
&__error {
border: $border $error_field;
&:focus {
border: $border $error_field;
}
}
&__success {
border: $border $success_color;
&:focus {
border: $border $success_color;
}
}
}

&--label {
&__label {
display: inline-block;
position: absolute;
top: 0;
Expand All @@ -68,61 +67,44 @@ $border: 1px solid;
text-transform: capitalize;
transition: all 0.15s ease-out;
padding: 0;
&__general {
&--general {
color: $inactive_color;
}
&__error {
&--error {
color: $error_field;
}
&__success {
&--success {
color: $success_color;
}
&--active {
color: $active_color;
}

&--disabled {
color: $disabled_color;
}
}

&--helper-message {
&__helper-message {
top: calc(100% + 2px);
position: absolute;
left: 16px;
margin-top: 2px;
line-height: 1;
}

&--right-content {
position: absolute;
right: 16px;
bottom: 25%;
&__right-content {
margin-left: 16px;
}
}

.deriv-input--field__general:disabled + .deriv-input--label,
.deriv-input--field__error:disabled + .deriv-input--label,
.deriv-input--field__success:disabled + .deriv-input--label {
color: $inactive_color;
cursor: not-allowed;
}

.deriv-input--field:focus + .deriv-input--label {
.deriv-input--general .deriv-input__field:focus + .deriv-input__label {
color: $active_color;
}

.deriv-input--field__error:focus + .deriv-input--label {
.deriv-input--error .deriv-input__field:focus + .deriv-input__label {
color: $error_field;
}

.deriv-input--field__success:focus + .deriv-input--label {
.deriv-input--success .deriv-input__field:focus + .deriv-input__label {
color: $success_color;
}

.deriv-helper-message {
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 18px;
&__general {
color: $inactive_color;
}
&__success {
color: $success_color;
}
&__error {
color: $error_field;
}
}
56 changes: 37 additions & 19 deletions lib/components/Input/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import clsx from "clsx";
import HelperMessage from "./HelperMessage";
import "./Input.scss";

export type InputVariants = "general" | "success" | "error";
interface InputProps
export type InputVariants =
| "general"
| "success"
| "error"
| "warning"
| "disabled";
interface InputProps
extends Omit<ComponentProps<"input">, "style" | "placeholder"> {
label?: string;
leftPlaceholder?: ReactNode;
Expand All @@ -15,15 +20,19 @@ export type InputVariants = "general" | "success" | "error";
}

const InputVariant: Record<InputVariants, string> = {
general: "deriv-input--field__general",
success: "deriv-input--field__success",
error: "deriv-input--field__error",
general: "deriv-input--general",
success: "deriv-input--success",
warning: "deriv-input--general",
error: "deriv-input--error",
disabled: "deriv-input--disabled",
};

const LabelVariant: Record<InputVariants, string> = {
general: "deriv-input--label__general",
success: "deriv-input--label__success",
error: "deriv-input--label__error",
general: "deriv-input__label--general",
success: "deriv-input__label--success",
warning: "deriv-input__label--general",
error: "deriv-input__label--error",
disabled: "deriv-input__label--disabled",
};

export const Input = ({
Expand All @@ -39,33 +48,42 @@ export const Input = ({
...rest
}: InputProps) => {
return (
<div className="deriv-input">
<div
className={clsx(
"deriv-input",
className,
InputVariant[error ? "error" : variant],
{
"deriv-input--disabled": disabled,
}
)}
>
{leftPlaceholder && (
<div className="deriv-input--left-content">{leftPlaceholder}</div>
<div className="deriv-input__left-content">{leftPlaceholder}</div>
)}
<input
placeholder={label}
className={clsx(
"deriv-input--field",
className,
InputVariant[error ? "error" : variant]
)}
className="deriv-input__field"
id={id}
disabled={disabled}
{...rest}
/>
<label
className={clsx(
"deriv-input--label",
LabelVariant[error ? "error" : variant]
"deriv-input__label",
LabelVariant[error ? "error" : variant],
{
"deriv-input--label--disabled": disabled,
}
)}
htmlFor={id}
>
{label}
</label>
{rightPlaceholder && (
<div className="deriv-input--right-content">{rightPlaceholder}</div>
<div className="deriv-input__right-content">{rightPlaceholder}</div>
)}
<div className="deriv-input--helper-message">
<div className="deriv-input__helper-message">
{message && (
<HelperMessage
message={message}
Expand Down
61 changes: 61 additions & 0 deletions lib/components/PasswordInput/PasswordConstants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
export type TScore = 0 | 1 | 2 | 3 | 4;

export type passwordKeys =
| "common"
| "commonNames"
| "dates"
| "extendedRepeat"
| "keyPattern"
| "namesByThemselves"
| "pwned"
| "recentYears"
| "sequences"
| "similarToCommon"
| "simpleRepeat"
| "straightRow"
| "topHundred"
| "topTen"
| "userInputs"
| "wordByItself";

export const passwordRegex = {
hasLowerCase: /[a-z]/,
hasNumber: /\d/,
hasSymbol: /\W/,
hasUpperCase: /[A-Z]/,
isLengthValid: /^.{8,25}$/,
isPasswordValid: /^(?=.*[a-z])(?=.*\d)(?=.*[A-Z])[!-~]{8,25}$/,
};

export const passwordValues = {
longPassword: 12,
maxLength: 25,
minLength: 8,
};

export const passwordErrorMessage = {
invalidLength: "You should enter 8-25 characters.",
missingCharacter:
"Password should have lower and uppercase English letters with numbers.",
PasswordError: "That password is incorrect. Please try again.",
};

export const warningMessages: Record<passwordKeys, string> = {
common: "This is a very common password.",
commonNames: "Common names and surnames are easy to guess.",
dates: "Dates are easy to guess.",
extendedRepeat:
'Repeated character patterns like "abcabcabc" are easy to guess.',
keyPattern: "Short keyboard patterns are easy to guess.",
namesByThemselves: "Single names or surnames are easy to guess.",
pwned: "Your password was exposed by a data breach on the Internet.",
recentYears: "Recent years are easy to guess.",
sequences: 'Common character sequences like "abc" are easy to guess.',
similarToCommon: "This is similar to a commonly used password.",
simpleRepeat: 'Repeated characters like "aaa" are easy to guess.',
straightRow: "Straight rows of keys on your keyboard are easy to guess.",
topHundred: "This is a frequently used password.",
topTen: "This is a heavily used password.",
userInputs: "There should not be any personal or page related data.",
wordByItself: "Single words are easy to guess.",
};
Loading