diff --git a/packages/uikit b/packages/uikit index 8429761f8..231f15dac 160000 --- a/packages/uikit +++ b/packages/uikit @@ -1 +1 @@ -Subproject commit 8429761f8b8d5c7944aef9a9902ae7c27fb9da7a +Subproject commit 231f15dac40e247c1811716c5a22846915ec4d16 diff --git a/src/components/CustomChannelComponent.tsx b/src/components/CustomChannelComponent.tsx index fde51ea1f..cdaccd272 100644 --- a/src/components/CustomChannelComponent.tsx +++ b/src/components/CustomChannelComponent.tsx @@ -80,7 +80,7 @@ const Root = styled.div` // @link: https://weblog.west-wind.com/posts/2023/Apr/17/Preventing-iOS-Safari-Textbox-Zooming font-size: ${isIOSMobile ? 16 : 14}px; font-family: 'Roboto', sans-serif; - line-height: 20px; + line-height: 24px; // because top & bottom padding is 8px each and the input height is 40px. resize: none; border: none; outline: none; @@ -112,7 +112,8 @@ const Root = styled.div` } } .sendbird-message-input--placeholder { - top: 9px; + top: 50%; + transform: translateY(-50%); } } `; diff --git a/src/components/CustomTypingIndicatorBubble.tsx b/src/components/CustomTypingIndicatorBubble.tsx index bef73254e..69299928a 100644 --- a/src/components/CustomTypingIndicatorBubble.tsx +++ b/src/components/CustomTypingIndicatorBubble.tsx @@ -35,7 +35,7 @@ const blink = keyframes` const TypingDotsContainer = styled.div` align-items: center; - border-radius: 16px; + border-radius: 100px; display: flex; gap: 6px; justify-content: center; @@ -67,6 +67,7 @@ const TypingDot = styled.span` const Root = styled.div` display: flex; align-items: flex-end; + margin-top: 16px; `; function TypingDots() { diff --git a/src/components/FormInput.tsx b/src/components/FormInput.tsx index 2ffc3a201..e5447a674 100644 --- a/src/components/FormInput.tsx +++ b/src/components/FormInput.tsx @@ -1,5 +1,5 @@ import { MessageFormItemStyle } from '@sendbird/chat/message'; -import { ReactElement, ReactNode, useState } from 'react'; +import { ReactElement, ReactNode } from 'react'; import styled from 'styled-components'; import Icon, { IconColors, IconTypes } from '@uikit/ui/Icon'; @@ -34,25 +34,26 @@ const OptionalText = styled.span` const Root = styled.div>` padding-bottom: 12px; width: 100%; + .sendbird-input .sendbird-input__input { color: ${({ theme }) => theme.textColor.incomingMessage} !important; height: fit-content; - background-color: ${({ theme }) => theme.bgColor.formInput} !important; + background-color: ${({ theme }) => theme.bgColor.formInput.default} !important; border: ${({ theme, errorMessage }) => `solid 1px ${errorMessage ? theme.borderColor.formInput.error : theme.borderColor.formInput.default}`} !important; - ::placeholder { - color: ${({ theme }) => theme.textColor.placeholder}; - } + &:disabled { pointer-events: none; - background-color: ${({ theme }) => theme.bgColor.formInputDisabled} !important; + background-color: ${({ theme }) => theme.bgColor.formInput.disabled} !important; border: none !important; } + &:focus { border: ${({ theme }) => `solid 1px ${theme.borderColor.formInput.focus}`} !important; outline: none; box-shadow: 0 0 0 1px ${({ theme }) => theme.borderColor.formInput.focus}; } + &:active { border: ${({ theme }) => `solid 1px ${theme.borderColor.formInput.active}`} !important; } @@ -64,6 +65,26 @@ interface ChipProps { isSubmitted?: boolean; } +interface PlaceholderProps { + numMaxLines?: number; +} + +const Placeholder = styled.div` + width: calc(100% - 26px); // (12px side padding + 1px border) * 2 = 26px + height: calc(100% - 16px); // (7px padding + 1px border) * 2 = 16px + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: ${({ numMaxLines }) => numMaxLines ?? 1}; + -webkit-box-orient: vertical; + position: absolute; + pointer-events: none; + top: 8px; + left: 13px; + font-size: 14px; + line-height: 1.43; + color: ${({ theme }) => theme.textColor.placeholder}; +`; + const Chip = styled.div` border-radius: 100px; padding: ${({ isSubmitted }) => (isSubmitted ? '6px 16px' : '5px 15px')}; @@ -170,7 +191,7 @@ const SubmittedTextInputContainer = styled.div word-wrap: break-word; width: calc(100% - 24px); color: ${({ theme }) => theme.textColor.incomingMessage}; - background-color: ${({ theme }) => theme.bgColor.formInputDisabled} !important; + background-color: ${({ theme }) => theme.bgColor.formInput.disabled} !important; border: none; pointer-events: none; ${({ isTextarea }) => { @@ -189,6 +210,25 @@ const SubmittedTextInputContainer = styled.div white-space: pre-wrap; `; +interface SubmittedTextInputComponentProps { + layout: string; + currentValue: string; + isValid: boolean | undefined; +} + +const SubmittedTextInputComponent = ({ layout, currentValue, isValid }: SubmittedTextInputComponentProps) => { + return ( + + {currentValue} + {isValid && ( + + + + )} + + ); +}; + const SubmittedText = styled.div` width: calc(100% - 24px); line-height: 20px; @@ -216,21 +256,23 @@ const CheckIconForChip = styled(Icon)` const InputContainer = styled.div` width: 100%; + position: relative; `; export interface InputProps { name: string; style: MessageFormItemStyle; - required?: boolean; - disabled?: boolean; - isValid?: boolean; + isSubmitted: boolean; errorMessage: string | null; values: string[]; - placeHolder?: string; - onFocused?: (isFocus: boolean) => void; + isInvalidated: boolean; + isSubmitTried: boolean; onChange: (values: string[]) => void; - isSubmitted: boolean; layout: MessageFormItemStyle['layout']; + required?: boolean; + isValid?: boolean; + placeHolder?: string; + onFocused?: (isFocus: boolean) => void; } type ChipState = 'default' | 'selected' | 'submittedDefault' | 'submittedSelected'; @@ -245,10 +287,11 @@ const FormInput = (props: InputProps) => { layout, name, required, - disabled, errorMessage, isValid, values, + isInvalidated, + isSubmitTried, style, onFocused, onChange, @@ -260,15 +303,11 @@ const FormInput = (props: InputProps) => { const { min = 1, max = 1 } = resultCount ?? {}; const chipDataList: ChipData[] = getInitialChipDataList(); - const [isFocused, setIsFocused] = useState(false); - const handleFocus = () => { - setIsFocused(true); onFocused?.(true); }; const handleBlur = () => { - setIsFocused(false); onFocused?.(false); }; @@ -291,14 +330,9 @@ const FormInput = (props: InputProps) => { let newDraftedValues: string[]; if (min === 1 && max === 1) { // Single select - newDraftedValues = [chipDataList[index].option]; + newDraftedValues = chipDataList[index].state === 'selected' ? [] : [chipDataList[index].option]; } else { - /** - * Multi select case - * Upon chip click, if it is: - * 1. not selected and can select more -> select the chip. Keep other selected chips as is. - * 2. already selected -> deselect the chip. Keep other selected chips as is. - */ + // Multi select newDraftedValues = chipDataList.reduce((acc, chipData, i) => { if (i === index) { if (chipData.state === 'default' && values.length < max) { @@ -312,7 +346,7 @@ const FormInput = (props: InputProps) => { return acc; }, [] as string[]); } - if (newDraftedValues.length > 0) onChange(newDraftedValues); + onChange(newDraftedValues); }; return ( @@ -356,28 +390,26 @@ const FormInput = (props: InputProps) => { return ( {isSubmitted ? ( - - {currentValue} - {isValid && ( - - - - )} - + <> + + {!currentValue && No Response} + ) : ( -