optimizing flex layout & styling inputs

This commit is contained in:
Anton Tranelis 2025-06-07 11:22:09 +02:00
parent 758730b523
commit 47322f277a
9 changed files with 72 additions and 92 deletions

View File

@ -1,3 +1,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { Color } from '@tiptap/extension-color'
import { Image } from '@tiptap/extension-image'
import { Placeholder } from '@tiptap/extension-placeholder'
@ -29,11 +32,8 @@ export function RichTextEditor({
containerStyle,
defaultValue,
placeholder,
required = true,
updateFormValue,
}: RichTextEditorProps) {
console.log(placeholder, required)
const handleChange = () => {
const newValue: string | undefined = editor?.storage.markdown.getMarkdown()
if (updateFormValue && newValue) {

View File

@ -1,5 +1,4 @@
import BoldIcon from '@heroicons/react/24/solid/BoldIcon'
import CodeBracketIcon from '@heroicons/react/24/solid/CodeBracketIcon'
import H1Icon from '@heroicons/react/24/solid/H1Icon'
import H2Icon from '@heroicons/react/24/solid/H2Icon'
import H3Icon from '@heroicons/react/24/solid/H3Icon'
@ -7,9 +6,7 @@ import ItalicIcon from '@heroicons/react/24/solid/ItalicIcon'
import ListBulletIcon from '@heroicons/react/24/solid/ListBulletIcon'
import NumberedListIcon from '@heroicons/react/24/solid/NumberedListIcon'
import { useEditorState } from '@tiptap/react'
import { FaQuoteLeft } from 'react-icons/fa6'
import { MdUndo, MdRedo, MdHorizontalRule } from 'react-icons/md'
import { LiaTextHeightSolid } from 'react-icons/lia'
import type { Editor } from '@tiptap/react'
@ -44,42 +41,16 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
},
})
const addYoutubeVideo = () => {
const url = prompt('Enter YouTube URL')
if (url) {
editor.commands.setYoutubeVideo({
src: url,
width: Math.max(320) || 640,
height: Math.max(180) || 480,
})
}
}
return (
<>
<ul className='tw:menu tw:p-1 tw:menu-horizontal tw:flex-none tw:bg-base-200 tw:rounded-box tw:w-full tw:rounded-b-none'>
<ul
className={
'tw:menu tw:p-1 tw:menu-horizontal tw:flex-nowrap tw:overflow-x-hidden tw:flex-none tw:bg-base-200 tw:rounded-box tw:w-full tw:rounded-b-none'
}
>
<li>
<div
className={`tw:tooltip tw:px-1 ${editorState.canUndo ? '' : 'tw:opacity-50'}`}
data-tip='Undo'
onClick={() => editor.chain().focus().undo().run()}
>
<MdUndo className='tw:w-5 tw:h-5' />
</div>
</li>
<li>
<div
className={`tw:tooltip tw:px-1 ${editorState.canRedo ? '' : 'tw:opacity-50'}`}
data-tip='Redo'
onClick={() => editor.chain().focus().redo().run()}
>
<MdRedo className='tw:w-5 tw:h-5' />
</div>
</li>
<li>
<div
className={`tw:tooltip tw:px-1 ${editorState.isBold ? 'tw:bg-base-content/10' : ''}`}
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isBold ? 'tw:bg-base-content/10' : ''}`}
data-tip='Bold'
onClick={() => editor.chain().focus().toggleBold().run()}
>
@ -88,7 +59,7 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
</li>
<li>
<div
className={`tw:tooltip tw:px-1 ${editorState.isItalic ? 'tw:bg-base-content/10' : ''}`}
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isItalic ? 'tw:bg-base-content/10' : ''}`}
data-tip='Italic'
onClick={() => editor.chain().focus().toggleItalic().run()}
>
@ -96,45 +67,36 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
</div>
</li>
<li>
<details className='tw:z-10000'>
<summary>
<LiaTextHeightSolid className='tw:w-5 tw:h-5' />
</summary>
<ul>
<li>
<div
className={`tw:tooltip tw:px-1 ${editorState.isHeading1 ? 'tw:bg-base-content/10' : ''}`}
data-tip='Heading 1'
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
>
<H1Icon className='tw:w-5 tw:h-5' />
</div>
</li>
<li>
<div
className={`tw:tooltip tw:px-1 ${editorState.isHeading2 ? 'tw:bg-base-content/10' : ''}`}
data-tip='Heading 2'
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
>
<H2Icon className='tw:w-5 tw:h-5' />
</div>
</li>
<li>
<div
className={`tw:tooltip tw:px-1 ${editorState.isHeading3 ? 'tw:bg-base-content/10' : ''}`}
data-tip='Heading 3'
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
>
<H3Icon className='tw:w-5 tw:h-5' />
</div>
</li>
</ul>
</details>
<div
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isHeading1 ? 'tw:bg-base-content/10' : ''}`}
data-tip='Heading 1'
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
>
<H1Icon className='tw:w-5 tw:h-5' />
</div>
</li>
<li>
<div
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isHeading2 ? 'tw:bg-base-content/10' : ''}`}
data-tip='Heading 2'
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
>
<H2Icon className='tw:w-5 tw:h-5' />
</div>
</li>
<li>
<div
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isHeading3 ? 'tw:bg-base-content/10' : ''}`}
data-tip='Heading 3'
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
>
<H3Icon className='tw:w-5 tw:h-5' />
</div>
</li>
<li>
<div
className={`tw:tooltip tw:px-1 ${editorState.isBulletList ? 'tw:bg-base-content/10' : ''}`}
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isBulletList ? 'tw:bg-base-content/10' : ''}`}
data-tip='List'
onClick={() => editor.chain().focus().toggleBulletList().run()}
>
@ -143,22 +105,13 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
</li>
<li>
<div
className={`tw:tooltip tw:px-1 ${editorState.isOrderedList ? 'tw:bg-base-content/10' : ''}`}
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 ${editorState.isOrderedList ? 'tw:bg-base-content/10' : ''}`}
data-tip='List'
onClick={() => editor.chain().focus().toggleOrderedList().run()}
>
<NumberedListIcon className='tw:w-5 tw:h-5' />
</div>
</li>
<li>
<div
className={`tw:tooltip tw:px-1 ${editorState.isBlockquote ? 'tw:bg-base-content/10' : ''}`}
data-tip='Quote'
onClick={() => editor.chain().focus().toggleBlockquote().run()}
>
<FaQuoteLeft className='tw:w-5 tw:h-5' />
</div>
</li>
<li>
<div
className='tw:tooltip tw:px-1'
@ -168,6 +121,25 @@ export const TextEditorMenu = ({ editor }: { editor: Editor }) => {
<MdHorizontalRule className='tw:w-5 tw:h-5' />
</div>
</li>
<div className='tw:flex-grow'></div>
<li>
<div
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 tw:hidden tw:sm:block tw:md:hidden tw:lg:block ${editorState.canUndo ? '' : 'tw:opacity-50'}`}
data-tip='Undo'
onClick={() => editor.chain().focus().undo().run()}
>
<MdUndo className='tw:w-5 tw:h-5' />
</div>
</li>
<li>
<div
className={`tw:tooltip tw:px-1.5 tw:mx-0.5 tw:hidden tw:sm:block tw:md:hidden tw:lg:block ${editorState.canRedo ? '' : 'tw:opacity-50'}`}
data-tip='Redo'
onClick={() => editor.chain().focus().redo().run()}
>
<MdRedo className='tw:w-5 tw:h-5' />
</div>
</li>
</ul>
{/** <div className='control-group tiptap-toolbar'>
<div className='button-group'>

View File

@ -6,6 +6,7 @@ import type { Item } from '#types/Item'
export interface StartEndInputProps {
item?: Item
showLabels?: boolean
labelStyle?: string
updateStartValue?: (value: string) => void
updateEndValue?: (value: string) => void
}
@ -16,6 +17,7 @@ export interface StartEndInputProps {
export const PopupStartEndInput = ({
item,
showLabels = true,
labelStyle,
updateStartValue,
updateEndValue,
}: StartEndInputProps) => {
@ -27,6 +29,7 @@ export const PopupStartEndInput = ({
dataField='start'
inputStyle='tw:text-sm tw:px-2'
labelTitle={showLabels ? 'Start' : ''}
labelStyle={labelStyle}
defaultValue={item && item.start ? item.start.substring(0, 10) : ''}
autocomplete='one-time-code'
updateFormValue={updateStartValue}
@ -37,6 +40,7 @@ export const PopupStartEndInput = ({
dataField='end'
inputStyle='tw:text-sm tw:px-2'
labelTitle={showLabels ? 'End' : ''}
labelStyle={labelStyle}
defaultValue={item && item.end ? item.end.substring(0, 10) : ''}
autocomplete='one-time-code'
updateFormValue={updateEndValue}

View File

@ -178,7 +178,7 @@ export function ProfileForm() {
)
}}
>
<div className='tw:flex tw:flex-col tw:flex-1'>
<div className='tw:flex tw:flex-col tw:flex-1 pb-4'>
<FormHeader item={item} state={state} setState={setState} />
{template === 'onepager' && (
@ -204,7 +204,7 @@ export function ProfileForm() {
></TabsForm>
)}
<div className='tw:mt-6 tw:flex-none'>
<div className='tw:mb-4 tw:mt-6 tw:flex-none'>
<button
className={`${loading ? ' tw:loading tw:btn tw:float-right' : 'tw:btn tw:float-right'}`}
type='submit'

View File

@ -43,7 +43,7 @@ export const ProfileTextForm = ({
<div className='tw:flex tw:justify-between tw:items-center'>
<label
htmlFor='nextAppointment'
className='tw:block tw:text-sm tw:font-medium tw:text-gray-500 tw:mb-1'
className='tw:block tw:text-sm tw:font-medium tw:text-base-content/50 tw:mb-1'
>
{heading || 'Text'}:
</label>

View File

@ -44,6 +44,7 @@ export const TabsForm = ({
<PopupStartEndInput
item={item}
showLabels={true}
labelStyle={'tw:text-base-content/50'}
updateEndValue={(e) =>
setState((prevState) => ({
...prevState,
@ -61,6 +62,7 @@ export const TabsForm = ({
<RichTextEditor
labelTitle='About'
labelStyle={'tw:text-base-content/50'}
placeholder='about ...'
defaultValue={item?.text ? item.text : ''}
updateFormValue={(v) =>
@ -73,6 +75,7 @@ export const TabsForm = ({
/>
<RichTextEditor
labelTitle='Contact Info'
labelStyle={'tw:text-base-content/50'}
placeholder='contact info ...'
defaultValue={state.contact || ''}
updateFormValue={(c) =>

View File

@ -43,7 +43,7 @@ export const TabsView = ({
unlinkItem: (id: string) => Promise<void>
}) => {
const addFilterTag = useAddFilterTag()
const [activeTab, setActiveTab] = useState<number>()
const [activeTab, setActiveTab] = useState<number>(0)
const navigate = useNavigate()
const [addItemPopupType] = useState<string>('')
@ -80,7 +80,7 @@ export const TabsView = ({
useEffect(() => {
const params = new URLSearchParams(location.search)
const urlTab = params.get('tab')
setActiveTab(urlTab ? Number(urlTab) : 1)
setActiveTab(urlTab ? Number(urlTab) : 0)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [location.search])

View File

@ -40,7 +40,7 @@ export const Tabs: React.FC<TabsProps> = ({ items, setUrlParams }: TabsProps) =>
navigate(newUrl, { replace: false })
},
[location, navigate],
[location.pathname, location.search, navigate, setUrlParams],
)
return (

View File

@ -20,9 +20,10 @@
}
.tiptap p.is-editor-empty:first-child::before {
color: #adb5bd;
color: var(--color-base-content);
opacity: 0.5;
content: attr(data-placeholder);
float: left;
height: 0;
pointer-events: none;
}
}