Skip to content

Commit 36e2403

Browse files
Merge branch 'PROD-265_work-intake' into PROD-1024_textarea
2 parents 2428532 + 743119d commit 36e2403

File tree

8 files changed

+268
-0
lines changed

8 files changed

+268
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
@import '../../../styles';
2+
3+
$form-pad-top: calc($pad-md - $border);
4+
$border-xs: 1px;
5+
$error-line-height: 14px;
6+
7+
.form-field-wrapper {
8+
display: flex;
9+
flex-direction: column;
10+
justify-content: flex-start;
11+
padding-bottom: $pad-md;
12+
13+
.form-field {
14+
flex: 1;
15+
display: flex;
16+
flex-direction: column;
17+
align-items: flex-start;
18+
padding: $pad-sm $form-pad-top $border-xs $form-pad-top;
19+
height: calc($pad-xxl * 2);
20+
background: $tc-white;
21+
border: $border-xs solid $black-40;
22+
box-sizing: border-box;
23+
border-radius: $pad-xs;
24+
margin-bottom: calc($error-line-height + $pad-xs);
25+
26+
&:hover,
27+
&.focus {
28+
border-color: $turq-160;
29+
30+
&.form-field-error {
31+
border-color: $red-100;
32+
}
33+
}
34+
35+
&.focus,
36+
&.form-field-error {
37+
border-width: $border;
38+
padding: calc($pad-sm - $border-xs) calc($form-pad-top - $border-xs) 0 calc($form-pad-top - $border-xs);
39+
}
40+
41+
&.disabled {
42+
background-color: $black-10;
43+
background: $black-10;
44+
border-color: $black-40;
45+
}
46+
47+
&.form-field-error {
48+
border-color: $red-100;
49+
margin-bottom: 0;
50+
51+
.label {
52+
color: $red-100;
53+
}
54+
}
55+
56+
.label {
57+
display: flex;
58+
flex-direction: column;
59+
top: calc(50% - $form-pad-top/2);
60+
color: $turq-160;
61+
margin-bottom: $pad-xs;
62+
width: 100%;
63+
// extend ultra-small and override some properties
64+
@extend .ultra-small;
65+
@include font-weight-medium;
66+
line-height: calc($pad-md - $border);
67+
font-style: normal;
68+
white-space: nowrap;
69+
70+
.label-and-hint {
71+
display: flex;
72+
justify-content: flex-start;
73+
align-items: center;
74+
75+
.hint {
76+
color: $black-60;
77+
padding-left: $border;
78+
@include font-weight-less-bold;
79+
white-space: nowrap;
80+
overflow: hidden;
81+
text-overflow: ellipsis;
82+
}
83+
}
84+
}
85+
}
86+
87+
.error {
88+
display: flex;
89+
align-items: center;
90+
color: $red-100;
91+
// extend body ultra small and override it
92+
@extend .body-ultra-small;
93+
line-height: $error-line-height;
94+
margin-top: $pad-xs;
95+
96+
svg {
97+
@include icon-md;
98+
fill: $red-100;
99+
margin-right: $pad-xs;
100+
}
101+
}
102+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import '@testing-library/jest-dom'
2+
3+
describe('<FormFieldWrapper /> ', () => {
4+
5+
test('it should display the FormField', () => {})
6+
})
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import classNames from 'classnames'
2+
import { Dispatch, FC, ReactNode, SetStateAction, useState } from 'react'
3+
4+
import { IconSolid } from '../../../svgs'
5+
6+
import styles from './FormFieldWrapper.module.scss'
7+
8+
export const optionalHint: string = '(optional)'
9+
10+
interface FormFieldWrapperProps {
11+
readonly children: ReactNode
12+
readonly dirty?: boolean
13+
readonly disabled: boolean
14+
readonly error?: string
15+
readonly hint?: string
16+
readonly label: string
17+
readonly name: string
18+
}
19+
20+
const FormFieldWrapper: FC<FormFieldWrapperProps> = (props: FormFieldWrapperProps) => {
21+
22+
const [focusStyle, setFocusStyle]: [string | undefined, Dispatch<SetStateAction<string | undefined>>] = useState<string | undefined>()
23+
24+
const showError: boolean = !!props.error && !!props.dirty
25+
const formFieldClasses: string = classNames(
26+
styles['form-field'],
27+
props.disabled ? styles.disabled : undefined,
28+
focusStyle,
29+
showError ? styles['form-field-error'] : undefined
30+
)
31+
32+
return (
33+
<div className={styles['form-field-wrapper']}>
34+
35+
<div
36+
className={formFieldClasses}
37+
onBlur={() => setFocusStyle(undefined)}
38+
onFocus={() => setFocusStyle(styles.focus)}
39+
>
40+
<label
41+
className={styles.label}
42+
role='presentation'
43+
>
44+
<div className={styles['label-and-hint']}>
45+
<div>
46+
{props.label}
47+
</div>
48+
{!!props.hint && (
49+
<div className={styles.hint}>
50+
{props.hint}
51+
</div>
52+
)}
53+
</div>
54+
55+
{props.children}
56+
</label>
57+
</div>
58+
59+
{showError && (
60+
<div className={styles.error}>
61+
<IconSolid.ExclamationIcon />
62+
{props.error}
63+
</div>
64+
)}
65+
</div>
66+
)
67+
}
68+
69+
export default FormFieldWrapper
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as FormFieldWrapper } from './Form-Field-Wrapper'
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
@import '../../../styles';
2+
3+
.form-input-text {
4+
@extend .body-small;
5+
color: $black-60;
6+
box-sizing: border-box;
7+
border: 0;
8+
width: 100%;
9+
padding: 0;
10+
11+
&:focus {
12+
box-shadow: none;
13+
border: none;
14+
outline: none;
15+
color: $black-100;
16+
17+
&::placeholder {
18+
color: $black-60;
19+
}
20+
}
21+
22+
&:disabled {
23+
background-color: $black-10;
24+
}
25+
26+
&::placeholder {
27+
opacity: 1;
28+
}
29+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import '@testing-library/jest-dom'
2+
3+
describe('<TextInput /> ', () => {
4+
5+
test('it should display the TextInput', () => {})
6+
})
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { FC } from 'react'
2+
3+
import { FormFieldWrapper } from '../form-field-wrapper'
4+
5+
import styles from './InputText.module.scss'
6+
7+
export const optionalHint: string = '(optional)'
8+
9+
<<<<<<< HEAD:src/lib/form/form-input/input-text/InputText.tsx
10+
interface InputTextProps {
11+
=======
12+
interface TextInputProps {
13+
>>>>>>> PROD-265_work-intake:src/lib/form/text-input/Text-Input.tsx
14+
readonly dirty?: boolean
15+
readonly disabled?: boolean
16+
readonly error?: string
17+
readonly hint?: string
18+
readonly label?: string
19+
readonly name: string
20+
readonly placeholder?: string
21+
readonly preventAutocomplete?: boolean
22+
readonly tabIndex: number
23+
readonly type: 'password' | 'text'
24+
readonly value?: string | number
25+
}
26+
27+
const InputText: FC<InputTextProps> = (props: InputTextProps) => {
28+
return (
29+
<FormFieldWrapper
30+
dirty={!!props.dirty}
31+
disabled={!!props.disabled}
32+
error={props.error}
33+
hint={props.hint}
34+
label={props.label || props.name}
35+
name={props.name}
36+
>
37+
<input
38+
autoComplete={!!props.preventAutocomplete ? 'off' : undefined}
39+
className={styles['form-input-text']}
40+
defaultValue={props.value}
41+
disabled={!!props.disabled}
42+
name={props.name}
43+
placeholder={props.placeholder}
44+
tabIndex={props.tabIndex}
45+
type={props.type || 'text'}
46+
/>
47+
</FormFieldWrapper>
48+
)
49+
}
50+
51+
export default InputText

src/lib/form/text-input/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export {
2+
default as TextInput,
3+
optionalHint as textInputOptionalHint,
4+
} from './Text-Input'

0 commit comments

Comments
 (0)