Skip to content

Commit ab5b850

Browse files
authored
Merge pull request #46 from deriv-com/aizad/FEQ-1560/password-input
Aizad/FEQ-1560/Password Input Field
2 parents 63365d8 + 5025c17 commit ab5b850

15 files changed

+552
-94
lines changed
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
$inactive_color: #999999;
2+
$success_color: #4bb4b3;
3+
$warning_color: #ffad3a;
4+
$error_field: #ec3f3f;
5+
6+
.deriv-helper-message {
7+
font-size: 12px;
8+
font-style: normal;
9+
font-weight: 400;
10+
line-height: 18px;
11+
&--general {
12+
color: $inactive_color;
13+
}
14+
&--success {
15+
color: $success_color;
16+
}
17+
&--warning {
18+
color: $warning_color;
19+
}
20+
&--error {
21+
color: $error_field;
22+
}
23+
}

lib/components/Input/HelperMessage.tsx

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import React, { ReactNode } from "react";
22
import clsx from "clsx";
33
import { InputVariants } from ".";
4-
import "./Input.scss";
4+
import "./HelperMessage.scss";
55

66
export interface HelperMessageProps {
77
error?: boolean;
88
message?: ReactNode;
99
variant?: InputVariants;
1010
disabled?: boolean;
1111
}
12-
13-
const MessageVariant: Record<InputVariants, string> = {
14-
general: "deriv-helper-message__general",
15-
success: "deriv-helper-message__success",
16-
error: "deriv-helper-message__error",
12+
type TMessageVariant = Exclude<InputVariants, "disabled">;
13+
const MessageVariant: Record<TMessageVariant, string> = {
14+
general: "deriv-helper-message--general",
15+
success: "deriv-helper-message--success",
16+
warning: "deriv-helper-message--warning",
17+
error: "deriv-helper-message--error",
1718
};
1819

1920
const HelperMessage = ({
@@ -25,7 +26,8 @@ const HelperMessage = ({
2526
<p
2627
className={clsx("deriv-helper-message", {
2728
[MessageVariant["general"]]: disabled,
28-
[MessageVariant[error ? "error" : variant]]: !disabled,
29+
[MessageVariant[error ? "error" : (variant as TMessageVariant)]]:
30+
!disabled,
2931
})}
3032
>
3133
{message}

lib/components/Input/Input.scss

+49-67
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,44 @@ $disabled_color: #d6d6d6;
22
$inactive_color: #999999;
33
$active_color: #85acb0;
44
$success_color: #4bb4b3;
5+
$warning_color: #ffad3a;
56
$error_field: #ec3f3f;
6-
$inactive_color: #999999;
77
$border: 1px solid;
88

99
.deriv-input {
10-
display: inline-block;
10+
display: inline-flex;
1111
position: relative;
12+
border-radius: 4px;
13+
width: 328px;
14+
box-sizing: border-box;
15+
text-align: left;
16+
padding: 10px 16px;
17+
border: $border;
18+
19+
&--general {
20+
border-color: $inactive_color;
21+
&:focus-within {
22+
border-color: $active_color;
23+
}
24+
}
25+
&--error {
26+
border-color: $error_field;
27+
}
28+
&--success {
29+
border-color: $success_color;
30+
}
31+
32+
&--active {
33+
border-color: $active_color;
34+
}
1235

13-
&--field {
36+
&--disabled {
37+
border-color: $disabled_color;
38+
}
39+
40+
&__field {
1441
width: 100%;
15-
padding: 10px 16px;
1642
outline: none;
17-
border-radius: 4px;
18-
width: 328px;
19-
box-sizing: border-box;
20-
outline: none;
21-
text-align: left;
22-
&:disabled {
23-
border: $border $disabled_color;
24-
color: $inactive_color;
25-
}
2643
&::placeholder {
2744
visibility: hidden;
2845
}
@@ -36,27 +53,9 @@ $border: 1px solid;
3653
height: fit-content;
3754
}
3855
}
39-
&__general {
40-
border: $border $inactive_color;
41-
&:focus {
42-
border: $border $active_color;
43-
}
44-
}
45-
&__error {
46-
border: $border $error_field;
47-
&:focus {
48-
border: $border $error_field;
49-
}
50-
}
51-
&__success {
52-
border: $border $success_color;
53-
&:focus {
54-
border: $border $success_color;
55-
}
56-
}
5756
}
5857

59-
&--label {
58+
&__label {
6059
display: inline-block;
6160
position: absolute;
6261
top: 0;
@@ -68,61 +67,44 @@ $border: 1px solid;
6867
text-transform: capitalize;
6968
transition: all 0.15s ease-out;
7069
padding: 0;
71-
&__general {
70+
&--general {
7271
color: $inactive_color;
7372
}
74-
&__error {
73+
&--error {
7574
color: $error_field;
7675
}
77-
&__success {
76+
&--success {
7877
color: $success_color;
7978
}
79+
&--active {
80+
color: $active_color;
81+
}
82+
83+
&--disabled {
84+
color: $disabled_color;
85+
}
8086
}
8187

82-
&--helper-message {
88+
&__helper-message {
89+
top: calc(100% + 2px);
8390
position: absolute;
8491
left: 16px;
85-
margin-top: 2px;
92+
line-height: 1;
8693
}
8794

88-
&--right-content {
89-
position: absolute;
90-
right: 16px;
91-
bottom: 25%;
95+
&__right-content {
96+
margin-left: 16px;
9297
}
9398
}
9499

95-
.deriv-input--field__general:disabled + .deriv-input--label,
96-
.deriv-input--field__error:disabled + .deriv-input--label,
97-
.deriv-input--field__success:disabled + .deriv-input--label {
98-
color: $inactive_color;
99-
cursor: not-allowed;
100-
}
101-
102-
.deriv-input--field:focus + .deriv-input--label {
100+
.deriv-input--general .deriv-input__field:focus + .deriv-input__label {
103101
color: $active_color;
104102
}
105103

106-
.deriv-input--field__error:focus + .deriv-input--label {
104+
.deriv-input--error .deriv-input__field:focus + .deriv-input__label {
107105
color: $error_field;
108106
}
109107

110-
.deriv-input--field__success:focus + .deriv-input--label {
108+
.deriv-input--success .deriv-input__field:focus + .deriv-input__label {
111109
color: $success_color;
112110
}
113-
114-
.deriv-helper-message {
115-
font-size: 12px;
116-
font-style: normal;
117-
font-weight: 400;
118-
line-height: 18px;
119-
&__general {
120-
color: $inactive_color;
121-
}
122-
&__success {
123-
color: $success_color;
124-
}
125-
&__error {
126-
color: $error_field;
127-
}
128-
}

lib/components/Input/index.tsx

+37-19
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@ import clsx from "clsx";
33
import HelperMessage from "./HelperMessage";
44
import "./Input.scss";
55

6-
export type InputVariants = "general" | "success" | "error";
7-
interface InputProps
6+
export type InputVariants =
7+
| "general"
8+
| "success"
9+
| "error"
10+
| "warning"
11+
| "disabled";
12+
interface InputProps
813
extends Omit<ComponentProps<"input">, "style" | "placeholder"> {
914
label?: string;
1015
leftPlaceholder?: ReactNode;
@@ -15,15 +20,19 @@ export type InputVariants = "general" | "success" | "error";
1520
}
1621

1722
const InputVariant: Record<InputVariants, string> = {
18-
general: "deriv-input--field__general",
19-
success: "deriv-input--field__success",
20-
error: "deriv-input--field__error",
23+
general: "deriv-input--general",
24+
success: "deriv-input--success",
25+
warning: "deriv-input--general",
26+
error: "deriv-input--error",
27+
disabled: "deriv-input--disabled",
2128
};
2229

2330
const LabelVariant: Record<InputVariants, string> = {
24-
general: "deriv-input--label__general",
25-
success: "deriv-input--label__success",
26-
error: "deriv-input--label__error",
31+
general: "deriv-input__label--general",
32+
success: "deriv-input__label--success",
33+
warning: "deriv-input__label--general",
34+
error: "deriv-input__label--error",
35+
disabled: "deriv-input__label--disabled",
2736
};
2837

2938
export const Input = ({
@@ -39,33 +48,42 @@ export const Input = ({
3948
...rest
4049
}: InputProps) => {
4150
return (
42-
<div className="deriv-input">
51+
<div
52+
className={clsx(
53+
"deriv-input",
54+
className,
55+
InputVariant[error ? "error" : variant],
56+
{
57+
"deriv-input--disabled": disabled,
58+
}
59+
)}
60+
>
4361
{leftPlaceholder && (
44-
<div className="deriv-input--left-content">{leftPlaceholder}</div>
62+
<div className="deriv-input__left-content">{leftPlaceholder}</div>
4563
)}
4664
<input
4765
placeholder={label}
48-
className={clsx(
49-
"deriv-input--field",
50-
className,
51-
InputVariant[error ? "error" : variant]
52-
)}
66+
className="deriv-input__field"
5367
id={id}
68+
disabled={disabled}
5469
{...rest}
5570
/>
5671
<label
5772
className={clsx(
58-
"deriv-input--label",
59-
LabelVariant[error ? "error" : variant]
73+
"deriv-input__label",
74+
LabelVariant[error ? "error" : variant],
75+
{
76+
"deriv-input--label--disabled": disabled,
77+
}
6078
)}
6179
htmlFor={id}
6280
>
6381
{label}
6482
</label>
6583
{rightPlaceholder && (
66-
<div className="deriv-input--right-content">{rightPlaceholder}</div>
84+
<div className="deriv-input__right-content">{rightPlaceholder}</div>
6785
)}
68-
<div className="deriv-input--helper-message">
86+
<div className="deriv-input__helper-message">
6987
{message && (
7088
<HelperMessage
7189
message={message}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
export type TScore = 0 | 1 | 2 | 3 | 4;
2+
3+
export type passwordKeys =
4+
| "common"
5+
| "commonNames"
6+
| "dates"
7+
| "extendedRepeat"
8+
| "keyPattern"
9+
| "namesByThemselves"
10+
| "pwned"
11+
| "recentYears"
12+
| "sequences"
13+
| "similarToCommon"
14+
| "simpleRepeat"
15+
| "straightRow"
16+
| "topHundred"
17+
| "topTen"
18+
| "userInputs"
19+
| "wordByItself";
20+
21+
export const passwordRegex = {
22+
hasLowerCase: /[a-z]/,
23+
hasNumber: /\d/,
24+
hasSymbol: /\W/,
25+
hasUpperCase: /[A-Z]/,
26+
isLengthValid: /^.{8,25}$/,
27+
isPasswordValid: /^(?=.*[a-z])(?=.*\d)(?=.*[A-Z])[!-~]{8,25}$/,
28+
};
29+
30+
export const passwordValues = {
31+
longPassword: 12,
32+
maxLength: 25,
33+
minLength: 8,
34+
};
35+
36+
export const passwordErrorMessage = {
37+
invalidLength: "You should enter 8-25 characters.",
38+
missingCharacter:
39+
"Password should have lower and uppercase English letters with numbers.",
40+
PasswordError: "That password is incorrect. Please try again.",
41+
};
42+
43+
export const warningMessages: Record<passwordKeys, string> = {
44+
common: "This is a very common password.",
45+
commonNames: "Common names and surnames are easy to guess.",
46+
dates: "Dates are easy to guess.",
47+
extendedRepeat:
48+
'Repeated character patterns like "abcabcabc" are easy to guess.',
49+
keyPattern: "Short keyboard patterns are easy to guess.",
50+
namesByThemselves: "Single names or surnames are easy to guess.",
51+
pwned: "Your password was exposed by a data breach on the Internet.",
52+
recentYears: "Recent years are easy to guess.",
53+
sequences: 'Common character sequences like "abc" are easy to guess.',
54+
similarToCommon: "This is similar to a commonly used password.",
55+
simpleRepeat: 'Repeated characters like "aaa" are easy to guess.',
56+
straightRow: "Straight rows of keys on your keyboard are easy to guess.",
57+
topHundred: "This is a frequently used password.",
58+
topTen: "This is a heavily used password.",
59+
userInputs: "There should not be any personal or page related data.",
60+
wordByItself: "Single words are easy to guess.",
61+
};

0 commit comments

Comments
 (0)