Add growing textarea component

This commit is contained in:
ilia tapazukk 2023-05-11 11:33:01 +00:00
parent a3b2288e21
commit 1cd95f955b
5 changed files with 103 additions and 22 deletions

View File

@ -77,10 +77,9 @@
.titleInput,
.subtitleInput {
border: 0;
outline: 0;
padding: 0;
font-size: 36px;
line-height: 1.1;
margin-bottom: 1.2rem;
&::placeholder {
opacity: 0.3;
@ -93,6 +92,8 @@
}
}
//Grow input
.editSettings,
.edit {
display: none;

View File

@ -14,6 +14,7 @@ import { useSession } from '../../context/session'
import { Modal } from '../Nav/Modal'
import { hideModal, showModal } from '../../stores/ui'
import { imageProxy } from '../../utils/imageProxy'
import { GrowingTextarea } from '../_shared/GrowingTextarea'
type EditViewProps = {
shout: Shout
@ -73,11 +74,10 @@ export const EditView = (props: EditViewProps) => {
})
})
const handleTitleInputChange = (e) => {
const title = e.currentTarget.value
setForm('title', title)
const handleTitleInputChange = (value) => {
setForm('title', value)
if (title) {
if (value) {
setFormErrors('title', '')
}
}
@ -139,30 +139,21 @@ export const EditView = (props: EditViewProps) => {
})}
>
<div class={styles.inputContainer}>
<input
<GrowingTextarea
value={(value) => handleTitleInputChange(value)}
class={styles.titleInput}
type="text"
name="title"
id="title"
placeholder={t('Header')}
autocomplete="off"
value={form.title}
onInput={handleTitleInputChange}
initialValue={form.title}
/>
<Show when={formErrors.title}>
<div class={styles.validationError}>{formErrors.title}</div>
</Show>
</div>
<input
<GrowingTextarea
value={(value) => setForm('subtitle', value)}
class={styles.subtitleInput}
type="text"
name="subtitle"
id="subtitle"
autocomplete="off"
placeholder={t('Subheader')}
value={form.subtitle}
onChange={(e) => setForm('subtitle', e.currentTarget.value)}
initialValue={form.subtitle}
/>
<Editor
shoutId={props.shout.id}

View File

@ -0,0 +1,44 @@
.GrowingTextarea {
display: block;
width: 100%;
.growWrap {
display: grid;
width: 100%;
&::after {
content: attr(data-replicated-value);
visibility: hidden;
transition: height 0.3s linear;
}
.textInput {
margin-bottom: 0;
border: none;
resize: none;
overflow: hidden;
&::placeholder {
color: #858585;
}
&:focus,
&:focus-visible,
&:active {
border: none;
outline: none;
box-shadow: none;
}
}
&::after,
& .textInput {
/* Identical styling required!! */
white-space: pre-wrap;
word-wrap: break-word;
overflow: hidden;
grid-area: 1 / 1 / 2 / 2;
width: 100%;
padding: 0;
}
}
}

View File

@ -0,0 +1,44 @@
import { clsx } from 'clsx'
import styles from './GrowingTextarea.module.scss'
import { createEffect, createSignal } from 'solid-js'
type Props = {
class?: string
placeholder: string
initialValue?: string
value: (string) => void
}
export const GrowingTextarea = (props: Props) => {
const [value, setValue] = createSignal('')
const handleChangeValue = (event) => {
setValue(event.target.value)
props.value(event.target.value)
}
const handleKeyDown = async (event) => {
if (event.key === 'Enter' && event.shiftKey) {
return
}
if (event.key === 'Enter' && !event.shiftKey && value()?.trim().length > 0) {
event.preventDefault()
}
}
return (
<div class={clsx(styles.GrowingTextarea)}>
<div class={clsx(styles.growWrap, props.class)} data-replicated-value={value()}>
<textarea
rows={1}
autocomplete="off"
class={clsx(styles.textInput, props.class)}
value={props.initialValue}
onKeyDown={handleKeyDown}
onInput={(event) => handleChangeValue(event)}
placeholder={props.placeholder}
/>
</div>
</div>
)
}

View File

@ -0,0 +1 @@
export { GrowingTextarea } from './GrowingTextarea'