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-1880/Update Input Component #101

Merged
merged 13 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 8 additions & 13 deletions lib/components/Input/HelperMessage.scss
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
$inactive_color: #999999;
$success_color: #4bb4b3;
$warning_color: #ffad3a;
$error_field: #ec3f3f;

.deriv-helper-message {
font-size: 12px;
line-height: 1;
font-size: var(--du-text-size-sm, 12px);
line-height: var(--du-text-lh-2xs, 8px);
font-style: normal;
font-weight: 400;
color: $inactive_color;
font-weight: var(--du-text-weight-normal, 400);
color: var(--du-text-primary, #999999);
&--general {
color: $inactive_color;
color: var(--du-text-less-prominent, #999999);
}
&--success {
color: $success_color;
color: var(--du-text-profit-success, #4bb4b3);
}
&--warning {
color: $warning_color;
color: var(--du-text-warning, #ffad3a);
}
&--error {
color: $error_field;
color: var(--du-text-red, #ff444f);
}
}
24 changes: 24 additions & 0 deletions lib/components/Input/HelperMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,30 @@ const MessageVariant: Record<TMessageVariant, string> = {
error: "deriv-helper-message--error",
};

/**
* HelperMessageProps interface
* @interface HelperMessageProps
* @property {boolean} [error] - If true, the helper message will display an error state.
* @property {ReactNode} [message] - The helper message to display.
* @property {InputVariants} [variant] - The variant of the helper message.
* @property {boolean} [disabled] - If true, the helper message will be disabled.
*/

/**
* HelperMessage component
* @component
* @param {HelperMessageProps} props - The props that define the HelperMessage.
* @returns {ReactNode} The React Node that represents the HelperMessage.
*
* @example
* <HelperMessage
* error={false}
* message="This is a helper message"
* variant="general"
* disabled={false}
* />
*/

const HelperMessage = ({
error,
message,
Expand Down
74 changes: 44 additions & 30 deletions lib/components/Input/Input.scss
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
$disabled_color: #d6dadb;
$inactive_color: #999999;
$active_color: #85acb0;
$success_color: #4bb4b3;
$warning_color: #ffad3a;
$error_field: #ec3f3f;
$input-borders: (
"general": var(--du-state-active, #d6dadb),
"hover": var(--du-border-hover, #999999),
"active": var(--du-brand-secondary, #85acb0),
"success": var(--du-status-success, #4bb4b3),
"error": var(--du-status-danger, #ec3f3f),
);

$label-colors: (
"general": var(--du-border-hover, #999999),
"active": var(--du-brand-secondary, #85acb0),
"error": var(--du-status-danger, #ec3f3f),
"success": var(--du-status-success, #4bb4b3),
"disabled": var(--du-state-active, #d6dadb),
);

$border: 1px solid;
$input-placement: 16px;

.deriv-input__container {
display: inline-block;
Expand All @@ -22,32 +33,35 @@ $border: 1px solid;
.deriv-input {
display: inline-flex;
position: relative;
border-radius: 4px;
border-radius: $border-radius;
width: 100%;
text-align: left;
padding: 10px 16px;
border: $border;
font-size: var(--du-text-size-default, 14px);
color: var(--du-text-prominent, #333333);

&--general {
border-color: $disabled_color;
&:hover {
border-color: $inactive_color;
border-color: map-get($input-borders, "general");
&:hover:not(:disabled):not(:focus-within) {
border-color: map-get($input-borders, "hover");
}
&:focus-within {
border-color: $active_color;
border-color: map-get($input-borders, "active");
}
}
&--error {
border-color: $error_field;
border-color: map-get($input-borders, "error");
}
&--success {
border-color: $success_color;
border-color: map-get($input-borders, "success");
}
&--active {
border-color: $active_color;
border-color: map-get($input-borders, "active");
}
&--disabled {
border-color: $disabled_color;
border-color: map-get($input-borders, "general");
cursor: not-allowed;
}

&__field {
Expand All @@ -59,10 +73,10 @@ $border: 1px solid;
&:focus,
&:not(:placeholder-shown) {
& ~ label {
font-size: 10px;
font-size: var(--du-text-size-xs, 10px);
transform: translate(0, -50%);
background-color: #ffffff;
padding: 0px 4px;
background-color: var(--du-general-main-1, #ffffff);
padding: 0 4px;
height: fit-content;
}
}
Expand All @@ -74,51 +88,51 @@ $border: 1px solid;
top: 0;
bottom: 0;
padding: 0;
left: 16px;
left: $input-placement;
display: flex;
align-items: center;
pointer-events: none;
transition: all 0.15s ease-out;
font-size: 14px;
font-size: var(--du-text-size-default, 14px);
&--general {
color: $inactive_color;
color: map-get($label-colors, "general");
}
&--error {
color: $error_field;
color: map-get($label-colors, "error");
}
&--success {
color: $success_color;
color: map-get($label-colors, "success");
}
&--active {
color: $active_color;
color: map-get($label-colors, "active");
}

&--disabled {
color: $disabled_color;
color: map-get($label-colors, "disabled");
}
}

&__right-content {
margin-left: 16px;
margin-left: $input-placement;
}
}

.deriv-input--general .deriv-input__field:disabled + .deriv-input__label,
.deriv-input--error .deriv-input__field:disabled + .deriv-input__label,
.deriv-input--success .deriv-input__field:disabled + .deriv-input__label {
color: $disabled_color;
color: map-get($label-colors, "disabled");
}

.deriv-input--general .deriv-input__field:focus + .deriv-input__label {
color: $active_color;
color: map-get($label-colors, "active");
}

.deriv-input--error .deriv-input__field:focus + .deriv-input__label {
color: $error_field;
color: map-get($label-colors, "error");
}

.deriv-input--success .deriv-input__field:focus + .deriv-input__label {
color: $success_color;
color: map-get($label-colors, "success");
}

.deriv-input__helper-message {
Expand Down
55 changes: 55 additions & 0 deletions lib/components/Input/__test__/HelperMessage.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { render, screen } from "@testing-library/react";
import HelperMessage from "../HelperMessage";

const props = { message: "This is a helper message" };

describe("HelperMessage", () => {
it("should render correctly", () => {
render(<HelperMessage {...props} />);
const helperMessage = screen.getByText(props.message);
expect(helperMessage).toHaveClass("deriv-helper-message");
expect(helperMessage).toHaveTextContent(props.message);
});

it("should render variants: General", () => {
render(<HelperMessage {...props} />);
screen.debug();
const helperMessage = screen.getByText(props.message);
expect(helperMessage).toHaveClass("deriv-helper-message--general");
});

it("should render variants: Success", () => {
render(<HelperMessage {...props} variant="success" />);
screen.debug();
const helperMessage = screen.getByText(props.message);
expect(helperMessage).toHaveClass("deriv-helper-message--success");
});

it("should render variants: Error", () => {
render(<HelperMessage {...props} variant="error" />);
screen.debug();
const helperMessage = screen.getByText(props.message);
expect(helperMessage).toHaveClass("deriv-helper-message--error");
});

it("should render variants: Warning", () => {
render(<HelperMessage {...props} variant="warning" />);
screen.debug();
const helperMessage = screen.getByText(props.message);
expect(helperMessage).toHaveClass("deriv-helper-message--warning");
});

it("should show disabled", () => {
render(<HelperMessage {...props} disabled variant="disabled" />);
screen.debug();
const helperMessage = screen.getByText(props.message);
expect(helperMessage).toHaveClass("deriv-helper-message--general");
});

it("should show Error variant", () => {
render(<HelperMessage {...props} error />);
screen.debug();
const helperMessage = screen.getByText(props.message);
expect(helperMessage).toHaveClass("deriv-helper-message--error");
});
});
110 changes: 110 additions & 0 deletions lib/components/Input/__test__/Input.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { render, screen } from "@testing-library/react";
import { Input } from "..";

const props = { label: "Test", message: "Test message", id: "test" };

describe("Input", () => {
it("should render correctly", () => {
const { container, getByLabelText } = render(<Input {...props} />);
const inputContainer = container.firstChild;
const input = getByLabelText(props.label);
expect(inputContainer).toHaveClass("deriv-input__container");
expect(inputContainer).toHaveTextContent(props.label);
expect(inputContainer).toHaveTextContent(props.message);
expect(input).toBeInTheDocument();
});

it("should show label", () => {
render(<Input {...props} />);
const inputLabel = screen.getByText(props.label);
expect(inputLabel).toBeInTheDocument();
});

it("container should be full width", () => {
const { container } = render(<Input {...props} isFullWidth />);
const inputContainer = container.firstChild;
expect(inputContainer).toHaveClass("deriv-input__container--full");
});

it("should show message", () => {
render(<Input {...props} />);
const helperMessage = screen.getByText(props.message);
expect(helperMessage).toHaveClass("deriv-helper-message--general");
expect(helperMessage).toBeInTheDocument();
});

it("should hide message", () => {
const { container } = render(<Input {...props} hideMessage />);
const inputContainer = container.firstChild;
const input = inputContainer?.lastChild;
expect(input).not.toHaveClass("deriv-helper-message--general");
});

it("should show different variants: General", () => {
const { container } = render(<Input {...props} />);
const inputContainer = container.firstChild;
const input = inputContainer?.firstChild;
const inputLabel = screen.getByText(props.label);
const helperMessage = screen.getByText(props.message);
expect(input).toHaveClass("deriv-input--general");
expect(input).not.toHaveClass("deriv-input--error");
expect(inputLabel).toHaveClass("deriv-input__label--general");
expect(helperMessage).toHaveClass("deriv-helper-message--general");
});

it("should show different variants: Success", () => {
const { container } = render(<Input variant="success" {...props} />);
const inputContainer = container.firstChild;
const input = inputContainer?.firstChild;
const inputLabel = screen.getByText(props.label);
const helperMessage = screen.getByText(props.message);
expect(input).toHaveClass("deriv-input--success");
expect(input).not.toHaveClass("deriv-input--error");
expect(inputLabel).toHaveClass("deriv-input__label--success");
expect(helperMessage).toHaveClass("deriv-helper-message--success");
});

it("should show different variants: Error", () => {
const { container } = render(<Input variant="error" {...props} />);
const inputContainer = container.firstChild;
const input = inputContainer?.firstChild;
const inputLabel = screen.getByText(props.label);
const helperMessage = screen.getByText(props.message);
expect(input).toHaveClass("deriv-input--error");
expect(input).not.toHaveClass("deriv-input--success");
expect(inputLabel).toHaveClass("deriv-input__label--error");
expect(helperMessage).toHaveClass("deriv-helper-message--error");
});

it("should show different variants: Warning", () => {
const { container } = render(<Input variant="warning" {...props} />);
const inputContainer = container.firstChild;
const input = inputContainer?.firstChild;
const inputLabel = screen.getByText(props.label);
const helperMessage = screen.getByText(props.message);
expect(input).toHaveClass("deriv-input--general");
expect(input).not.toHaveClass("deriv-input--error");
expect(inputLabel).toHaveClass("deriv-input__label--general");
expect(helperMessage).toHaveClass("deriv-helper-message--warning");
});

it("should show different variants: Disabled", () => {
const { container } = render(<Input variant="disabled" {...props} />);
const inputContainer = container.firstChild;
const input = inputContainer?.firstChild;
const inputLabel = screen.getByText(props.label);
expect(input).toHaveClass("deriv-input--disabled");
expect(input).not.toHaveClass("deriv-input--error");
expect(inputLabel).toHaveClass("deriv-input__label--disabled");
});

it("should show different variants: Disabled", () => {
const { container } = render(<Input variant="disabled" {...props} />);
const inputContainer = container.firstChild;
const input = inputContainer?.firstChild;
const inputLabel = screen.getByText(props.label);
expect(input).toHaveClass("deriv-input--disabled");
expect(input).not.toHaveClass("deriv-input--error");
expect(inputLabel).toHaveClass("deriv-input__label--disabled");
});
});
Loading