Skip to content

Commit

Permalink
[EN-6218] feat(textarea): add textarea line limit
Browse files Browse the repository at this point in the history
  • Loading branch information
emile-bex committed Jul 27, 2023
1 parent 880839e commit d72e734
Show file tree
Hide file tree
Showing 14 changed files with 259 additions and 64 deletions.
1 change: 1 addition & 0 deletions src/components/forms/GenericField.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ export const GenericField = ({
<TextAreaNew
id={`${formId}-${data.id}`}
name={data.name}
maxLines={data.maxLines}
onChange={onChangeCustom}
value={value}
valid={getValid(data.name)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/forms/schema/formAddExternalOpportunity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const formAddExternalOpportunityCandidate = {
component: 'heading',
},
{
component: 'fieldgroup',
component: 'fieldgroup-new',
fields: [
{
id: 'recruiterFirstName',
Expand Down
1 change: 1 addition & 0 deletions src/components/modals/Modal/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const CustomModal = ({ children, closeOnNextRender, className, fullWidth }) => {

return (
<Modal
id="modal-screen"
closeTimeoutMS={200}
style={{
overlay: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ import '@testing-library/jest-dom/extend-expect';

import { ModalConfirm } from '../ModalConfirm';
import { ModalsListener, openModal } from 'src/components/modals/Modal';
import { BREAKPOINTS } from 'src/constants/styles';

jest.mock('@react-hook/window-size', () => {
return jest.fn(() => {
return {
useWindowWidth: BREAKPOINTS.desktop,
};
});
});

jest.mock('react-modal');

Expand Down
5 changes: 4 additions & 1 deletion src/components/modals/Modal/ModalGeneric/ModalGeneric.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ interface ModalGenericProps {
withCloseButton?: boolean;
}

const id = 'modal-generic';

export const ModalGeneric = ({
title,
description,
Expand All @@ -30,10 +32,11 @@ export const ModalGeneric = ({
return (
<Modal className={className} fullWidth={fullWidth}>
<div
id={id}
className={`uk-margin-auto-vertical ${
fullWidth ? 'uk-width-expand' : 'uk-width-2xlarge@m'
}`}
data-testid="modal-generic"
data-testid={id}
>
<div
className={`uk-modal-body ${
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import _ from 'lodash';
import moment from 'moment';
import React, {
/* memo, */ useCallback,
Expand Down
9 changes: 9 additions & 0 deletions src/components/partials/CarouselItem/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import { render } from '@testing-library/react';
import React from 'react';
import { CarouselItem } from '..';
import '@testing-library/jest-dom';
import { BREAKPOINTS } from 'src/constants/styles';

jest.mock('@react-hook/window-size', () => {
return jest.fn(() => {
return {
useWindowWidth: BREAKPOINTS.desktop,
};
});
});

describe('Carousel Item', () => {
it('renders the Carousel item', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import styled from 'styled-components';
import { BREAKPOINTS } from 'src/constants/styles';

export const StyledBackground = styled.section`
&.top-banner {
Expand Down
12 changes: 3 additions & 9 deletions src/components/utils/BackgroundImage/BackgroundImage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import Image, { StaticImageData } from 'next/image';
import React, { useEffect, useState } from 'react';
import React from 'react';
import { StyledBackground } from 'src/components/utils/BackgroundImage/BackgroundImage.styles';
import { BREAKPOINTS } from 'src/constants/styles';
import { useWindowSize } from 'src/hooks/useWindowSize';
import { useIsDesktop } from 'src/hooks/utils';

interface BackgroundImageProps {
img: string | StaticImageData;
Expand All @@ -23,12 +22,7 @@ export const BackgroundImage = ({
isHero,
hasCta,
}: BackgroundImageProps) => {
const { width } = useWindowSize();
const [isDesktop, setIsDesktop] = useState(true);

useEffect(() => {
setIsDesktop(width >= BREAKPOINTS.desktop);
}, [imgMobile, width]);
const isDesktop = useIsDesktop();

return (
<StyledBackground
Expand Down
2 changes: 1 addition & 1 deletion src/components/utils/Inputs/CheckBox/CheckBox.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const StyledCheckbox = styled.div`
display: flex;
align-items: center;
justify-content: left;
justify-content: flex-start;
height: 16px;
position: relative;
cursor: pointer;
Expand Down
72 changes: 55 additions & 17 deletions src/components/utils/Inputs/TextArea/TextArea.styles.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import styled from 'styled-components';
import styled, { css } from 'styled-components';
import { COLORS } from 'src/constants/styles';

export const StyledTextAreaContainer = styled.div`
max-width: 100%;
background-color: ${COLORS.white};
border-radius: 5px;
/* div.label {
border-bottom: solid 2px ${COLORS.gray};
Expand All @@ -15,22 +16,59 @@ export const StyledTextAreaContainer = styled.div`
color: ${COLORS.darkGray};
margin-bottom: 8px;
} */
textarea {
width: 100%;
padding-bottom: 12px;
box-sizing: border-box;
border: none;
resize: vertical;
border-bottom: solid 2px ${COLORS.gray};
margin-bottom: 30px;
`;

export const StyledTextArea = styled.textarea`
width: ${({ hasLineLimit, width }) => {
// Hard code the width in case the width of the modal changes
return hasLineLimit ? `${width}px` : '100%';
}};
padding-bottom: 12px;
box-sizing: border-box;
border: none;
resize: none;
border-bottom: solid 2px ${COLORS.gray};
font-family: Poppins, sans-serif;
// need to fix line height to calculate number of lines
line-height: 17px;
&::placeholder {
font-style: italic;
color: ${COLORS.darkGray};
font-family: Poppins, sans-serif;
&::placeholder {
font-style: italic;
color: ${COLORS.darkGray};
font-family: Poppins, sans-serif;
}
:focus-visible {
outline: none;
}
}
:focus-visible {
outline: none;
}
`;

export const StyledTextAreaScrollContainer = styled.div`
overflow-x: auto;
${({ hasLineLimit, textAreaWidth, width }) => {
return hasLineLimit
? css`
width: ${textAreaWidth || width}px;
max-width: ${width}px;
`
: css`
width: 100%;
max-width: 100%;
`;
}};
margin-bottom: 30px;
min-width: 300px;
`;

export const StyledAnnotations = styled.div`
display: flex;
justify-content: space-between;
`;

export const StyledLineLimit = styled.div`
color: ${({ warning }) => {
return warning ? COLORS.noRed : COLORS.darkGray;
}};
font-size: 12px;
text-align: right;
align-self: flex-end;
transform: translate(0, -30px);
`;
61 changes: 51 additions & 10 deletions src/components/utils/Inputs/TextArea/TextArea.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import React from 'react';
import { FormValidatorErrorMessage } from 'src/components/forms/FormValidatorErrorMessage';
import { StyledTextAreaContainer } from './TextArea.styles';
import { useIsMobile } from 'src/hooks/utils';
import {
StyledAnnotations,
StyledLineLimit,
StyledTextArea,
StyledTextAreaContainer,
StyledTextAreaScrollContainer,
} from './TextArea.styles';
import { useLineLimit } from './useLineLimit';

interface TextAreaProps {
title: string;
Expand All @@ -13,6 +21,7 @@ interface TextAreaProps {
isInvalid: boolean;
message: string;
};
maxLines?: { lines: number; width: number };
}

export function TextArea({
Expand All @@ -23,22 +32,54 @@ export function TextArea({
value,
hidden,
valid,
maxLines,
}: TextAreaProps) {
const isMobile = useIsMobile();

const { textAreaRef, remainingLines, textAreaWidth } = useLineLimit(
value,
name,
onChange,
maxLines?.lines
);

if (hidden) {
return null;
}

const maxLinesWidth = maxLines?.width || 655;

return (
<StyledTextAreaContainer>
<textarea
name={name}
id={id}
rows={5}
placeholder={title}
onChange={onChange}
value={value}
/>
<FormValidatorErrorMessage validObj={valid} newInput />
<StyledTextAreaScrollContainer
textAreaWidth={textAreaWidth}
isMobile={isMobile}
hasLineLimit={!!maxLines}
width={maxLinesWidth}
>
<StyledTextArea
isMobile={isMobile}
hasLineLimit={!!maxLines}
width={maxLinesWidth}
ref={textAreaRef}
name={name}
id={id}
rows={5}
placeholder={title}
onChange={onChange}
value={value}
/>
</StyledTextAreaScrollContainer>
<StyledAnnotations>
<div>
<FormValidatorErrorMessage validObj={valid} newInput />
</div>
{maxLines && (
<StyledLineLimit warning={remainingLines === 0}>
{remainingLines} ligne(s) restante(s)
</StyledLineLimit>
)}
</StyledAnnotations>
</StyledTextAreaContainer>
);
}
Loading

0 comments on commit d72e734

Please sign in to comment.