fix: multiline inputs now grow instead of scroll when the content is tall

pull/3148/head
yougotwill 8 months ago
parent 7708bc97c1
commit c101f4eeb5

@ -1,29 +1,17 @@
import { useState } from 'react'; import { useState } from 'react';
import useKey from 'react-use/lib/useKey'; import useKey from 'react-use/lib/useKey';
import styled from 'styled-components';
import { getConversationController } from '../../session/conversations'; import { getConversationController } from '../../session/conversations';
import { openConversationWithMessages } from '../../state/ducks/conversations'; import { openConversationWithMessages } from '../../state/ducks/conversations';
import { updateUserDetailsModal, UserDetailsModalState } from '../../state/ducks/modalDialog'; import { updateUserDetailsModal, UserDetailsModalState } from '../../state/ducks/modalDialog';
import { Avatar, AvatarSize } from '../avatar/Avatar'; import { Avatar, AvatarSize } from '../avatar/Avatar';
import { Flex } from '../basic/Flex';
import { SessionButton, SessionButtonType } from '../basic/SessionButton'; import { SessionButton, SessionButtonType } from '../basic/SessionButton';
import { SpacerLG } from '../basic/Text'; import { SpacerLG } from '../basic/Text';
import { CopyToClipboardButton } from '../buttons/CopyToClipboardButton'; import { CopyToClipboardButton } from '../buttons/CopyToClipboardButton';
import { SessionInput } from '../inputs'; import { SessionInput } from '../inputs';
import { SessionWrapperModal } from '../SessionWrapperModal'; import { SessionWrapperModal } from '../SessionWrapperModal';
import { ConversationTypeEnum } from '../../models/types'; import { ConversationTypeEnum } from '../../models/types';
import { StyledTextAreaContainer } from '../inputs/SessionInput'; import { Flex } from '../basic/Flex';
const StyledInputContainer = styled(Flex)`
${StyledTextAreaContainer} {
overflow-y: hidden;
textarea {
cursor: default;
top: 10px;
}
}
`;
export const UserDetailsDialog = (props: UserDetailsModalState) => { export const UserDetailsDialog = (props: UserDetailsModalState) => {
const [isEnlargedImageShown, setIsEnlargedImageShown] = useState(false); const [isEnlargedImageShown, setIsEnlargedImageShown] = useState(false);
@ -82,12 +70,7 @@ export const UserDetailsDialog = (props: UserDetailsModalState) => {
</div> </div>
</div> </div>
<SpacerLG /> <SpacerLG />
<StyledInputContainer <Flex container={true} width={'100%'} justifyContent="center" alignItems="center">
container={true}
width={'100%'}
justifyContent="center"
alignItems="center"
>
<SessionInput <SessionInput
value={props.conversationId} value={props.conversationId}
textSize="md" textSize="md"
@ -96,7 +79,7 @@ export const UserDetailsDialog = (props: UserDetailsModalState) => {
monospaced={true} monospaced={true}
isTextArea={true} isTextArea={true}
/> />
</StyledInputContainer> </Flex>
<SpacerLG /> <SpacerLG />
<div className="session-modal__button-group__center"> <div className="session-modal__button-group__center">
<SessionButton <SessionButton

@ -91,7 +91,6 @@ const StyledInput = styled(motion.input)<{
`; `;
export const StyledTextAreaContainer = styled(motion.div)<{ export const StyledTextAreaContainer = styled(motion.div)<{
noValue: boolean;
error: boolean; error: boolean;
textSize: TextSizes; textSize: TextSizes;
centerText?: boolean; centerText?: boolean;
@ -99,14 +98,12 @@ export const StyledTextAreaContainer = styled(motion.div)<{
}>` }>`
display: flex; display: flex;
align-items: center; align-items: center;
overflow-y: ${props => (props.noValue ? 'hidden' : 'auto')};
position: relative; position: relative;
min-height: 48px; line-height: 1;
min-height: 80px;
height: 100%; height: 100%;
max-height: ${props =>
props.textSize ? `calc(var(--font-size-${props.textSize}) * 4)` : '48px'};
width: 100%; width: 100%;
margin: var(--margins-sm) var(--margins-md); padding: 0 var(--margins-md);
background: transparent; background: transparent;
color: ${props => (props.error ? 'var(--danger-color)' : 'var(--input-text-color)')}; color: ${props => (props.error ? 'var(--danger-color)' : 'var(--input-text-color)')};
@ -114,42 +111,57 @@ export const StyledTextAreaContainer = styled(motion.div)<{
font-family: ${props => (props.monospaced ? 'var(--font-mono)' : 'var(--font-default)')}; font-family: ${props => (props.monospaced ? 'var(--font-mono)' : 'var(--font-default)')};
${props => `font-size: var(--font-size-${props.textSize});`} ${props => `font-size: var(--font-size-${props.textSize});`}
line-height: 1;
${props => props.centerText && 'text-align: center;'}
textarea { textarea {
display: flex; display: flex;
height: 100%; height: 100%;
width: 100%; width: 100%;
padding: 0; padding: var(--margins-md) 0;
outline: 0; outline: 0;
border: none; border: none;
background: transparent; background: transparent;
position: absolute;
top: ${props =>
`calc(var(--font-size-${props.textSize}) + ${props.textSize === 'xl' ? '8px' : '5px'})`};
resize: none; resize: none;
word-break: break-all; word-break: break-all;
user-select: all; user-select: all;
${props => props.centerText && 'text-align: center;'}
&:placeholder-shown { &:placeholder-shown {
line-height: 1;
font-family: ${props => (props.monospaced ? 'var(--font-mono)' : 'var(--font-default)')}; font-family: ${props => (props.monospaced ? 'var(--font-mono)' : 'var(--font-default)')};
${props => `font-size: var(--font-size-${props.textSize});`} ${props => `font-size: var(--font-size-${props.textSize});`}
line-height: 1;
} }
&::placeholder { &::placeholder {
color: var(--input-text-placeholder-color); color: var(--input-text-placeholder-color);
${props => props.centerText && 'text-align: center;'}
} }
} }
`; `;
const StyledPlaceholder = styled(motion.div)<{
error: boolean;
textSize: TextSizes;
editable: boolean;
centerText?: boolean;
monospaced?: boolean;
}>`
position: relative;
width: 100%;
min-height: 80px;
height: 100%;
transition: opacity var(--default-duration) color var(--default-duration);
${props => props.editable && 'cursor: pointer;'}
line-height: 1;
background: transparent;
color: ${props => (props.error ? 'var(--danger-color)' : 'var(--input-text-color)')};
font-family: ${props => (props.monospaced ? 'var(--font-mono)' : 'var(--font-default)')};
font-size: ${props => `var(--font-size-${props.textSize})`};
${props =>
props.centerText &&
'text-align: center; display: flex; align-items: center; justify-content: center;'}
`;
const ErrorItem = (props: { id: string; error: string }) => { const ErrorItem = (props: { id: string; error: string }) => {
return ( return (
<motion.label <motion.label
@ -284,6 +296,7 @@ export const SessionInput = (props: Props) => {
const [errorString, setErrorString] = useState(''); const [errorString, setErrorString] = useState('');
const [textErrorStyle, setTextErrorStyle] = useState(false); const [textErrorStyle, setTextErrorStyle] = useState(false);
const [forceShow, setForceShow] = useState(false); const [forceShow, setForceShow] = useState(false);
const [isFocused, setIsFocused] = useState(false);
const textAreaRef = useRef(inputRef?.current || null); const textAreaRef = useRef(inputRef?.current || null);
@ -312,7 +325,6 @@ export const SessionInput = (props: Props) => {
} }
}; };
// TODO[epic=ses-893] Type inputProps properly
const inputProps: any = { const inputProps: any = {
id, id,
type: correctType, type: correctType,
@ -332,6 +344,9 @@ export const SessionInput = (props: Props) => {
onBlur: (event: ChangeEvent<HTMLInputElement>) => { onBlur: (event: ChangeEvent<HTMLInputElement>) => {
if (editable && !disableOnBlurEvent) { if (editable && !disableOnBlurEvent) {
updateInputValue(event); updateInputValue(event);
if (isEmpty(value) && isFocused) {
setIsFocused(false);
}
} }
}, },
onKeyDown: (event: KeyboardEvent) => { onKeyDown: (event: KeyboardEvent) => {
@ -389,11 +404,29 @@ export const SessionInput = (props: Props) => {
> >
{isTextArea ? ( {isTextArea ? (
<StyledTextAreaContainer {...containerProps}> <StyledTextAreaContainer {...containerProps}>
<textarea {isFocused ? (
{...inputProps} <textarea
ref={inputRef || textAreaRef} {...inputProps}
aria-label={ariaLabel || 'session input text area'} placeholder={''}
/> ref={inputRef || textAreaRef}
aria-label={ariaLabel || 'session input text area'}
/>
) : (
<StyledPlaceholder
error={textErrorStyle}
textSize={textSize}
editable={editable}
centerText={centerText}
monospaced={monospaced}
onClick={() => {
if (editable) {
setIsFocused(true);
}
}}
>
{editable ? placeholder : value}
</StyledPlaceholder>
)}
</StyledTextAreaContainer> </StyledTextAreaContainer>
) : ( ) : (
<StyledInput <StyledInput

@ -62,7 +62,8 @@ export const OverlayCommunity = () => {
return; return;
} }
setGroupUrlError(undefined); setGroupUrlError(undefined);
await joinOpenGroup(completeUrl || groupUrl, setGroupUrlError, joinSogsUICallback); const url = (completeUrl && completeUrl.trim()) || (groupUrl && groupUrl.trim());
await joinOpenGroup(url, setGroupUrlError, joinSogsUICallback);
} catch (e) { } catch (e) {
setGroupUrlError(e.message); setGroupUrlError(e.message);
window.log.warn(e); window.log.warn(e);

@ -55,12 +55,9 @@ const StyledButtonerContainer = styled.div`
const StyledInputContainer = styled(Flex)` const StyledInputContainer = styled(Flex)`
${StyledTextAreaContainer} { ${StyledTextAreaContainer} {
margin: var(--margins-sm); padding: 0;
overflow-y: hidden; div:first-child {
padding: 0 var(--margins-sm);
textarea {
cursor: default;
top: 10px;
} }
} }
`; `;

Loading…
Cancel
Save