diff --git a/public/icons/arrow-left.svg b/public/icons/arrow-left.svg new file mode 100644 index 00000000..ff4bf063 --- /dev/null +++ b/public/icons/arrow-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index e23bb13c..7e980854 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -2,6 +2,7 @@ "...subscribing": "...subscribing", "About myself": "About myself", "About the project": "About the project", + "Add a few topics so that the reader knows what your content is about and can find it on pages of topics that interest them. Topics can be swapped, the first topic becomes the title": "Add a few topics so that the reader knows what your content is about and can find it on pages of topics that interest them. Topics can be swapped, the first topic becomes the title", "Add another image": "Add another image", "Add audio": "Add audio", "Add comment": "Comment", @@ -29,6 +30,7 @@ "Authors": "Authors", "Autotypograph": "Autotypograph", "Back": "Back", + "Back to editor": "Back to editor", "Back to main page": "Back to main page", "Become an author": "Become an author", "Bold": "Bold", @@ -48,12 +50,15 @@ "By updates": "By updates", "By views": "By views", "Cancel": "Cancel", + "Cancel changes": "Cancel changes", "Characters": "Знаков", "Chat Title": "Chat Title", "Choose a post type": "Choose a post type", "Choose a title image for the article. You can immediately see how the publication card will look like.": "Choose a title image for the article. You can immediately see how the publication card will look like.", "Choose who you want to write to": "Choose who you want to write to", "Collaborate": "Help Edit", + "Come up with a subtitle for your story": "Come up with a subtitle for your story", + "Come up with a title for your story": "Come up with a title for your story", "Comments": "Comments", "Communities": "Communities", "Confirm": "Confirm", @@ -75,6 +80,7 @@ "Date of Birth": "Date of Birth", "Decline": "Decline", "Delete": "Delete", + "Delete cover": "Delete cover", "Description": "Description...", "Discours": "Discours", "Discours is an intellectual environment, a web space and tools that allows authors to collaborate with readers and come together to co-create publications and media projects": "Discours is an intellectual environment, a web space and tools that allows authors to collaborate with readers and come together to co-create publications and media projects", @@ -251,6 +257,7 @@ "Short opening": "Short opening", "Show": "Show", "Show lyrics": "Текст песни", + "Slug": "Slug", "Social networks": "Social networks", "Something went wrong, check email and password": "Something went wrong. Check your email and password", "Something went wrong, please try again": "Something went wrong, please try again", @@ -315,6 +322,7 @@ "Work with us": "Cooperate with Discourse", "Write": "Write", "Write a comment...": "Write a comment...", + "Write a short introduction": "Write a short introduction", "Write about the topic": "Write about the topic", "Write an article": "Write an article", "Write comment": "Write comment", diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index ee2fa019..4226ea97 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -4,6 +4,7 @@ "About myself": "О себе", "About the project": "О проекте", "Accomplices": "Соучастники", + "Add a few topics so that the reader knows what your content is about and can find it on pages of topics that interest them. Topics can be swapped, the first topic becomes the title": "Добавьте несколько тем, чтобы читатель знал, о чем ваш материал, и мог найти его на страницах интересных ему тем. Темы можно менять местами, первая тема становится заглавной", "Add another image": "Добавить другое изображение", "Add audio": "Добавить аудио", "Add comment": "Комментировать", @@ -33,6 +34,7 @@ "Authors": "Авторы", "Autotypograph": "Автотипограф", "Back": "Назад", + "Back to editor": "Вернуться в редактор", "Back to main page": "Вернуться на главную", "Become an author": "Стать автором", "Bold": "Жирный", @@ -52,12 +54,15 @@ "By updates": "По обновлениям", "By views": "По просмотрам", "Cancel": "Отмена", + "Cancel changes": "Отменить изменения", "Characters": "Знаков", "Chat Title": "Тема дискурса", "Choose a post type": "Выберите тип публикации", "Choose a title image for the article. You can immediately see how the publication card will look like.": "Выберите заглавное изображение для статьи. Тут же сразу можно увидеть как будет выглядеть карточка публикации.", "Choose who you want to write to": "Выберите кому хотите написать", "Collaborate": "Помочь редактировать", + "Come up with a subtitle for your story": "Придумайте подзаголовок вашей истории", + "Come up with a title for your story": "Придумайте заголовок вашей истории", "Comments": "Комментарии", "Communities": "Сообщества", "Confirm": "Подтвердить", @@ -79,6 +84,7 @@ "Date of Birth": "Дата рождения", "Decline": "Отмена", "Delete": "Удалить", + "Delete cover": "Удалить обложку", "Description": "Описание...", "Discours": "Дискурс", "Discours is an intellectual environment, a web space and tools that allows authors to collaborate with readers and come together to co-create publications and media projects": "Дискурс — это интеллектуальная среда, веб-пространство и инструменты, которые позволяют авторам сотрудничать с читателями и объединяться для совместного создания публикаций и медиапроектов", @@ -267,6 +273,7 @@ "Short opening": "Небольшое вступление, чтобы заинтересовать читателя", "Show": "Показать", "Show lyrics": "Текст песни", + "Slug": "Постоянная ссылка", "Social networks": "Социальные сети", "Something went wrong, check email and password": "Что-то пошло не так. Проверьте адрес электронной почты и пароль", "Something went wrong, please try again": "Что-то пошло не так, попробуйте еще раз", @@ -333,6 +340,7 @@ "Work with us": "Сотрудничать с Дискурсом", "Write": "Написать", "Write a comment...": "Написать комментарий...", + "Write a short introduction": "Напишите краткое вступление", "Write about the topic": "Написать в тему", "Write an article": "Написать статью", "Write comment": "Написать комментарий", diff --git a/src/components/Views/Edit.module.scss b/src/components/Views/Edit.module.scss index ee938d1b..573ce000 100644 --- a/src/components/Views/Edit.module.scss +++ b/src/components/Views/Edit.module.scss @@ -2,72 +2,6 @@ position: static; } -.articlePreview { - border: 2px solid #e8e8e8; - padding: 1rem 1.2rem; - display: flex; - flex-direction: column; - min-height: 300px; - align-items: flex-start; - box-sizing: border-box; - - .actions { - display: flex; - gap: 16px; - } - - .shoutCardCoverContainer { - position: relative; - width: 100%; - - .shoutCardCover { - height: 0; - overflow: hidden; - position: relative; - margin: 1.6rem 0; - padding-bottom: 56.2%; - - img { - height: 100%; - object-fit: cover; - position: absolute; - transform-origin: 50% 50%; - transition: transform 1s ease-in-out; - width: 100%; - } - - &:hover img { - transform: scale(1.1); - } - } - } - - .shoutCardTitle { - @include font-size(2.2rem); - - font-weight: 700; - line-height: 1.25; - margin: auto 0 0.8rem; - } - - .shoutCardSubtitle { - @include font-size(1.7rem); - - color: #696969; - font-weight: 400; - line-height: 1.3; - margin-bottom: 0.8rem; - transition: color 0.2s, background-color 0.2s, box-shadow 0.2s; - } - - .shoutAuthor { - @include font-size(1.2rem); - - margin-right: 1.6rem; - color: rgb(0 0 0 / 70%); - } -} - .formHolder { padding: 0 4rem; } @@ -117,17 +51,6 @@ } } -// Grow input - -.editSettings, -.edit { - display: none; - - &.visible { - display: block; - } -} - .asidePanel { background: #1f1f1f; color: rgb(255 255 255 / 35%); @@ -272,7 +195,3 @@ background-repeat: no-repeat; } } - -.topicSelectContainer { - height: 64px; -} diff --git a/src/components/Views/Edit.tsx b/src/components/Views/Edit.tsx index daaaf92d..0b85d1b4 100644 --- a/src/components/Views/Edit.tsx +++ b/src/components/Views/Edit.tsx @@ -24,10 +24,17 @@ import { LayoutType, MediaItem } from '../../pages/types' import { clone } from '../../utils/clone' import deepEqual from 'fast-deep-equal' import { AutoSaveNotice } from '../Editor/AutoSaveNotice' +import { PublishSettings } from './PublishSettings' type Props = { shout: Shout } + +export const EMPTY_TOPIC: Topic = { + id: -1, + slug: '' +} + const AUTO_SAVE_INTERVAL = 5000 const handleScrollTopButtonClick = (e) => { e.preventDefault() @@ -37,17 +44,9 @@ const handleScrollTopButtonClick = (e) => { }) } -const EMPTY_TOPIC: Topic = { - id: -1, - slug: '' -} - export const EditView = (props: Props) => { const { t } = useLocalize() - const { user } = useSession() const [isScrolled, setIsScrolled] = createSignal(false) - const [topics, setTopics] = createSignal(null) - const [coverImage, setCoverImage] = createSignal(null) const { page } = useRouter() @@ -84,11 +83,6 @@ export const EditView = (props: Props) => { return JSON.parse(form.media || '[]') }) - onMount(async () => { - const allTopics = await apiClient.getAllTopics() - setTopics(allTopics) - }) - onMount(() => { const handleScroll = () => { setIsScrolled(window.scrollY > 0) @@ -108,37 +102,6 @@ export const EditView = (props: Props) => { } } - const handleSlugInputChange = (e) => { - const slug = e.currentTarget.value - setForm('slug', slug) - } - - const handleUploadModalContentCloseSetCover = (imgUrl: string) => { - hideModal() - setCoverImage(imageProxy(imgUrl)) - setForm('coverImageUrl', imgUrl) - } - const handleDeleteCoverImage = () => { - setForm('coverImageUrl', '') - setCoverImage(null) - } - - const handleTopicSelectChange = (newSelectedTopics) => { - if (newSelectedTopics.length === 0) { - setForm('mainTopic', EMPTY_TOPIC) - } else if ( - form.selectedTopics.length === 0 || - newSelectedTopics.every((topic) => topic.id !== form.mainTopic.id) - ) { - setForm('mainTopic', newSelectedTopics[0]) - } - - if (newSelectedTopics.length > 0) { - setFormErrors('selectedTopics', '') - } - setForm('selectedTopics', newSelectedTopics) - } - const handleAddMedia = (data) => { const newMedia = [...mediaItems(), ...data] setForm('media', JSON.stringify(newMedia)) @@ -259,247 +222,137 @@ export const EditView = (props: Props) => {
-
-
-
- handleTitleInputChange(value)} - class={styles.titleInput} - placeholder={articleTitle()} - initialValue={form.title} - maxLength={100} - /> - - -
{formErrors.title}
-
- - -
- handleBaseFieldsChange('artist', event.target.value)} - /> - handleBaseFieldsChange('date', event.target.value)} - /> - handleBaseFieldsChange('genre', event.target.value)} - /> -
-
- - + + <> +
+
setForm('subtitle', value)} - class={styles.subtitleInput} - placeholder={t('Subheader')} - initialValue={form.subtitle} + allowEnterKey={true} + value={(value) => handleTitleInputChange(value)} + class={styles.titleInput} + placeholder={articleTitle()} + initialValue={form.title} maxLength={100} /> - -
- - - {t('min. 1400×1400 pix')} -
- {t('jpg, .png, max. 10 mb.')} - - } - isMultiply={false} - fileType={'image'} - onUpload={(val) => setForm('coverImageUrl', val[0].url)} + + +
{formErrors.title}
+
+ + +
+ handleBaseFieldsChange('artist', event.target.value)} + /> + handleBaseFieldsChange('date', event.target.value)} + /> + handleBaseFieldsChange('genre', event.target.value)} + /> +
+
+ + + setForm('subtitle', value)} + class={styles.subtitleInput} + placeholder={t('Subheader')} + initialValue={form.subtitle} + maxLength={100} /> - } - > -
- - -
- - - handleMediaDelete(index)} - onImagesAdd={(value) => handleAddMedia(value)} - onImagesSorted={(value) => handleSortedMedia(value)} - /> - - - - handleAddMedia(data)} - onVideoDelete={(index) => handleMediaDelete(index)} - /> - - - - handleAddMedia(value)} - onAudioChange={handleMediaChange} - onAudioSorted={(value) => handleSortedMedia(value)} - /> - -
-
-

{t('Publish Settings')}

- -

Slug

-
- - -
- - {/*

Лид

*/} - {/*
*/} - {/* */} - {/* */} - {/*
*/} - - {/*

Выбор сообщества

*/} - {/*

Сообщества можно перечислить через запятую

*/} - {/*
*/} - {/* */} - {/*
*/} - -

{t('Topics')}

- {/*

*/} - {/* Добавьте несколько тем, чтобы читатель знал, о чем ваш материал, и мог найти*/} - {/* его на страницах интересных ему тем. Темы можно менять местами, первая тема*/} - {/* становится заглавной*/} - {/*

*/} -
-
- - setForm('mainTopic', mainTopic)} - mainTopic={form.mainTopic} - /> - -
- -
{formErrors.selectedTopics}
-
-
- - {/*

Соавторы

*/} - {/*

У каждого соавтора можно добавить роль

*/} - {/*
*/} - {/*
*/} - {/* */} - {/* */} - {/*
*/} - {/* */} - {/*
*/} - - {/*
*/} - {/*
Михаил Драбкин
*/} - {/*
*/} - {/* */} - {/*
*/} - {/*
*/} - -

{t('Material card')}

-

- {t( - 'Choose a title image for the article. You can immediately see how the publication card will look like.' - )} -

-
-
-
- -
-
- {form.title} -
+
+ + + {t('min. 1400×1400 pix')} +
+ {t('jpg, .png, max. 10 mb.')} + + } + isMultiply={false} + fileType={'image'} + onUpload={(val) => setForm('coverImageUrl', val[0].url)} + /> + } + > +
+ + +
+ + + handleMediaDelete(index)} + onImagesAdd={(value) => handleAddMedia(value)} + onImagesSorted={(value) => handleSortedMedia(value)} + /> -
{form.title}
-
{form.subtitle}
-
{user().name}
-
-
+ + + handleAddMedia(data)} + onVideoDelete={(index) => handleMediaDelete(index)} + /> + + + + handleAddMedia(value)} + onAudioChange={handleMediaChange} + onAudioSorted={(value) => handleSortedMedia(value)} + /> + + +
+ + +
- - setForm('body', body)} - /> + + setForm('body', body)} + /> +
- - handleUploadModalContentCloseSetCover(value)} /> - + ) diff --git a/src/components/Views/PublishSettings/PublishSettings.module.scss b/src/components/Views/PublishSettings/PublishSettings.module.scss new file mode 100644 index 00000000..4b0e8ecc --- /dev/null +++ b/src/components/Views/PublishSettings/PublishSettings.module.scss @@ -0,0 +1,154 @@ +.PublishSettings { + .goBack { + @include font-size(1.8rem); + + font-weight: 500; + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + line-height: 2.4rem; + } + + .inputContainer { + position: relative; + flex: 1; + display: flex; + flex-flow: column; + + .validationError { + position: absolute; + z-index: 1; + top: calc(100% + 4px); + font-size: small; + color: var(--danger-color); + } + } + + .commonSettings { + display: flex; + flex-direction: column; + gap: 10px; + + .settingInput { + &::after, + textarea { + @include font-size(1.6rem); + } + } + } + + .articlePreview { + border: 2px solid #e8e8e8; + padding: 1rem 1.2rem; + display: flex; + flex-direction: column; + min-height: 300px; + align-items: flex-start; + box-sizing: border-box; + + .actions { + display: flex; + gap: 16px; + } + + .shoutCardCoverContainer { + position: relative; + width: 100%; + min-height: 300px; + + &.hasImage { + &::before { + content: ''; + height: 100%; + position: absolute; + width: 100%; + z-index: 1; + background: linear-gradient(to bottom, rgb(0 0 0 / 0%) 40%, rgb(0 0 0 / 70%) 100%); + } + } + + .shoutCardCover { + height: 0; + overflow: hidden; + position: relative; + margin: 1.6rem 0 0; + padding-bottom: 56.2%; + + img { + height: 100%; + object-fit: cover; + position: absolute; + transform-origin: 50% 50%; + transition: transform 1s ease-in-out; + width: 100%; + } + + &:hover img { + transform: scale(1.1); + } + } + + .text { + bottom: 16px; + left: 16px; + right: 16px; + position: absolute; + z-index: 2; + color: var(--default-color); + + .mainTopic { + @include font-size(1.4rem); + + margin: auto 0 1.6rem; + font-weight: 600; + text-transform: uppercase; + } + + .shoutCardTitle { + @include font-size(2.4rem); + + font-weight: 700; + line-height: 1.25; + margin-bottom: 0.8rem; + } + + .shoutCardSubtitle { + @include font-size(2.2rem); + + font-weight: 400; + line-height: 1.3; + margin-bottom: 0.8rem; + transition: color 0.2s, background-color 0.2s, box-shadow 0.2s; + } + + .shoutAuthor { + @include font-size(1.6rem); + } + } + + &.hasImage .text { + color: var(--default-color-invert); + } + } + } + + .topicSelectContainer { + height: 64px; + } + + .formActions { + display: flex; + align-items: center; + justify-content: flex-end; + flex-direction: row; + padding: 1rem 0; + gap: 1rem; + margin-top: 80px; + border-top: 2px solid var(--black-100); + + .cancel { + margin-right: auto; + } + } +} diff --git a/src/components/Views/PublishSettings/PublishSettings.tsx b/src/components/Views/PublishSettings/PublishSettings.tsx new file mode 100644 index 00000000..f2f6904d --- /dev/null +++ b/src/components/Views/PublishSettings/PublishSettings.tsx @@ -0,0 +1,246 @@ +import { clsx } from 'clsx' +import styles from './PublishSettings.module.scss' +import { createEffect, createSignal, onMount, Show } from 'solid-js' +import { TopicSelect, UploadModalContent } from '../../Editor' +import { Button } from '../../_shared/Button' +import { hideModal, showModal } from '../../../stores/ui' +import { imageProxy } from '../../../utils/imageProxy' +import { ShoutForm, useEditorContext } from '../../../context/editor' +import { useLocalize } from '../../../context/localize' +import { Modal } from '../../Nav/Modal' +import { Topic } from '../../../graphql/types.gen' +import { apiClient } from '../../../utils/apiClient' +import { EMPTY_TOPIC } from '../Edit' +import { useSession } from '../../../context/session' +import { Icon } from '../../_shared/Icon' +import stylesBeside from '../../Feed/Beside.module.scss' +import { redirectPage } from '@nanostores/router' +import { router } from '../../../stores/router' +import { GrowingTextarea } from '../../_shared/GrowingTextarea' +import { createStore } from 'solid-js/store' + +type Props = { + shoutId: number + form: ShoutForm +} + +const MAX_LEAD_LIMIT = 400 +const shorten = (str: string, maxLen: number) => { + if (str.length <= maxLen) return str + return str.slice(0, Math.max(0, str.lastIndexOf(' ', maxLen))).trim() +} + +export const PublishSettings = (props: Props) => { + const { t } = useLocalize() + const { user } = useSession() + + const composeLead = () => { + if (!props.form.lead) { + const leadText = props.form.body.replaceAll(/<\/?[^>]+(>|$)/gi, ' ') + return shorten(leadText, MAX_LEAD_LIMIT).trim() + } + return props.form.lead + } + + const initialData: Partial = { + coverImageUrl: props.form.coverImageUrl, + mainTopic: props.form.mainTopic || EMPTY_TOPIC, + slug: props.form.slug, + title: props.form.title, + subtitle: props.form.subtitle, + lead: composeLead() + } + + const { + formErrors, + actions: { setForm, setFormErrors, saveShout, publishShout } + } = useEditorContext() + + const [settingsForm, setSettingsForm] = createStore(initialData) + const [topics, setTopics] = createSignal(null) + + const handleUploadModalContentCloseSetCover = (imgUrl: string) => { + hideModal() + setSettingsForm('coverImageUrl', imgUrl) + } + const handleDeleteCoverImage = () => { + setSettingsForm('coverImageUrl', '') + } + + const handleTopicSelectChange = (newSelectedTopics) => { + if ( + props.form.selectedTopics.length === 0 || + newSelectedTopics.every((topic) => topic.id !== props.form.mainTopic.id) + ) { + setSettingsForm((prev) => { + return { + ...prev, + mainTopic: newSelectedTopics[0] + } + }) + } + + if (newSelectedTopics.length > 0) { + setFormErrors('selectedTopics', '') + } + setForm('selectedTopics', newSelectedTopics) + } + + onMount(async () => { + const allTopics = await apiClient.getAllTopics() + setTopics(allTopics) + }) + + const handleBackClick = () => { + redirectPage(router, 'edit', { + shoutId: props.shoutId.toString() + }) + } + const handleCancelClick = () => { + setSettingsForm(initialData) + handleBackClick() + } + const handlePublishSubmit = () => { + publishShout({ ...props.form, ...settingsForm }) + } + const handleSaveDraft = () => { + saveShout({ ...props.form, ...settingsForm }) + } + + return ( +
+
+ +
+

{t('Publish Settings')}

+

{t('Material card')}

+
+
+
+
+ +
+ {initialData.title} +
+
+
+ +
{settingsForm.mainTopic.title}
+
+
{settingsForm.title}
+
{settingsForm.subtitle}
+
{user().name}
+
+
+
+

+ {t( + 'Choose a title image for the article. You can immediately see how the publication card will look like.' + )} +

+ +
+ setSettingsForm('title', value)} + allowEnterKey={false} + maxLength={100} + /> + setSettingsForm('subtitle', value)} + allowEnterKey={false} + maxLength={100} + /> + MAX_LEAD_LIMIT - 1 && '...'}`} + value={(value) => setSettingsForm('lead', value)} + allowEnterKey={false} + maxLength={MAX_LEAD_LIMIT} + /> +
+ +

{t('Slug')}

+
+ + +
+ +

{t('Topics')}

+

+ {t( + 'Add a few topics so that the reader knows what your content is about and can find it on pages of topics that interest them. Topics can be swapped, the first topic becomes the title' + )} +

+
+
+ + setForm('mainTopic', mainTopic)} + mainTopic={props.form.mainTopic} + /> + +
+ +
{formErrors.selectedTopics}
+
+
+ + {/*

Соавторы

*/} + {/*

У каждого соавтора можно добавить роль

*/} + {/*
*/} + {/*
*/} + {/* */} + {/* */} + {/*
*/} + {/* */} + {/*
*/} + + {/*
*/} + {/*
Михаил Драбкин
*/} + {/*
*/} + {/* */} + {/*
*/} + {/*
*/} + +
+
+ + handleUploadModalContentCloseSetCover(value)} /> + +
+ ) +} diff --git a/src/components/Views/PublishSettings/index.ts b/src/components/Views/PublishSettings/index.ts new file mode 100644 index 00000000..500c89ca --- /dev/null +++ b/src/components/Views/PublishSettings/index.ts @@ -0,0 +1 @@ +export { PublishSettings } from './PublishSettings' diff --git a/src/components/_shared/GrowingTextarea/GrowingTextarea.module.scss b/src/components/_shared/GrowingTextarea/GrowingTextarea.module.scss index 0149af68..81b706eb 100644 --- a/src/components/_shared/GrowingTextarea/GrowingTextarea.module.scss +++ b/src/components/_shared/GrowingTextarea/GrowingTextarea.module.scss @@ -3,6 +3,14 @@ width: 100%; position: relative; + &.bordered { + box-sizing: border-box; + padding: 16px 12px; + border-radius: 2px; + border: 2px solid var(--black-100); + background: var(--white-500, #fff); + } + .growWrap { display: grid; width: 100%; @@ -40,14 +48,16 @@ white-space: pre-wrap; word-wrap: break-word; overflow: hidden; + line-height: 1.2; grid-area: 1 / 1 / 2 / 2; width: 100%; padding: 0; + margin: 0; } } .maxLength { - color: #000; + color: var(--default-color); opacity: 1; position: absolute; z-index: 1; @@ -60,7 +70,7 @@ line-height: 1; user-select: none; transition: opacity 0.3s ease-in-out; - background: rgb(255 255 255 / 80%); + background: var(--white-500); &.visible { opacity: 1; @@ -71,6 +81,13 @@ animation-iteration-count: 2; } } + + &.bordered .maxLength { + opacity: 1; + font-weight: 500; + border: unset; + bottom: 0; + } } @keyframes blink { diff --git a/src/components/_shared/GrowingTextarea/GrowingTextarea.tsx b/src/components/_shared/GrowingTextarea/GrowingTextarea.tsx index 7fdc7f8f..d5e70faf 100644 --- a/src/components/_shared/GrowingTextarea/GrowingTextarea.tsx +++ b/src/components/_shared/GrowingTextarea/GrowingTextarea.tsx @@ -1,6 +1,7 @@ import { clsx } from 'clsx' import styles from './GrowingTextarea.module.scss' -import { createSignal, Show } from 'solid-js' +import { createSignal, Show, Switch } from 'solid-js' +import { style } from 'solid-js/web' type Props = { class?: string @@ -9,6 +10,7 @@ type Props = { value: (string) => void maxLength?: number allowEnterKey: boolean + variant?: 'bordered' } export const GrowingTextarea = (props: Props) => { @@ -29,7 +31,7 @@ export const GrowingTextarea = (props: Props) => { } return ( -
+