ux: textarea auto-grow, preview toggle in toolbar, prose-lg on richtext, no more bottom preview btn
This commit is contained in:
@@ -258,6 +258,14 @@ export function NoteEditor({ note, readOnly = false, onClose, fullPage = false }
|
||||
return () => document.removeEventListener('paste', handlePaste, { capture: true } as any)
|
||||
}, [t])
|
||||
|
||||
// Auto-grow textarea as content grows
|
||||
useEffect(() => {
|
||||
const el = textareaRef.current
|
||||
if (!el) return
|
||||
el.style.height = 'auto'
|
||||
el.style.height = Math.max(el.scrollHeight, 280) + 'px'
|
||||
}, [content])
|
||||
|
||||
const handleRemoveImage = (index: number) => {
|
||||
const removedUrl = images[index]
|
||||
setImages(images.filter((_, i) => i !== index))
|
||||
@@ -700,6 +708,23 @@ export function NoteEditor({ note, readOnly = false, onClose, fullPage = false }
|
||||
compact
|
||||
/>
|
||||
|
||||
{/* Preview toggle — only for text/markdown, in toolbar where it's visible */}
|
||||
{(noteType === 'text' || noteType === 'markdown') && !readOnly && (
|
||||
<button
|
||||
onClick={() => setShowMarkdownPreview(v => !v)}
|
||||
title={showMarkdownPreview ? 'Revenir à l\'édition' : 'Prévisualiser le rendu'}
|
||||
className={cn(
|
||||
'flex items-center gap-2 px-3 py-1.5 rounded-full border transition-all duration-300 text-xs font-medium',
|
||||
showMarkdownPreview
|
||||
? 'bg-foreground text-background border-foreground'
|
||||
: 'border-black/20 dark:border-white/20 text-foreground hover:bg-black/5 dark:hover:bg-white/5'
|
||||
)}
|
||||
>
|
||||
<Eye size={16} />
|
||||
<span>{showMarkdownPreview ? 'Éditer' : 'Aperçu'}</span>
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* AI — rounded-full, exact prototype style */}
|
||||
<button
|
||||
onClick={() => { setAiOpen(v => !v); setInfoOpen(false) }}
|
||||
@@ -811,23 +836,25 @@ export function NoteEditor({ note, readOnly = false, onClose, fullPage = false }
|
||||
)}
|
||||
|
||||
{/* Content area — max-w-2xl, like prototype */}
|
||||
<div className="max-w-2xl mx-auto space-y-8 pb-32">
|
||||
<div className="max-w-2xl mx-auto pb-32">
|
||||
{noteType === 'richtext' ? (
|
||||
<RichTextEditor
|
||||
content={content}
|
||||
onChange={(v) => { setContent(v); setIsDirty(true) }}
|
||||
className="min-h-[60vh] text-lg font-light leading-relaxed text-foreground/80"
|
||||
onImageUpload={uploadImageFile}
|
||||
/>
|
||||
<div className="prose prose-lg dark:prose-invert max-w-none [&_.notion-editor]:min-h-[280px]">
|
||||
<RichTextEditor
|
||||
content={content}
|
||||
onChange={(v) => { setContent(v); setIsDirty(true) }}
|
||||
className="min-h-[280px] text-lg font-light leading-relaxed"
|
||||
onImageUpload={uploadImageFile}
|
||||
/>
|
||||
</div>
|
||||
) : (noteType === 'markdown' || noteType === 'text') && showMarkdownPreview ? (
|
||||
<div
|
||||
className="min-h-[300px] cursor-text prose prose-lg dark:prose-invert max-w-none leading-relaxed"
|
||||
className="min-h-[280px] cursor-text prose prose-lg dark:prose-invert max-w-none leading-relaxed"
|
||||
onClick={() => !readOnly && setShowMarkdownPreview(false)}
|
||||
>
|
||||
<MarkdownContent content={content} />
|
||||
{!readOnly && (
|
||||
<p className="text-[11px] text-foreground/30 mt-6 select-none not-prose">
|
||||
Click to edit
|
||||
<p className="text-[11px] text-foreground/30 mt-8 select-none not-prose italic">
|
||||
Cliquez pour éditer
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
@@ -836,22 +863,13 @@ export function NoteEditor({ note, readOnly = false, onClose, fullPage = false }
|
||||
<textarea
|
||||
ref={textareaRef}
|
||||
dir="auto"
|
||||
placeholder={t('notes.takeNote') || "Type '/' for commands…"}
|
||||
placeholder={t('notes.takeNote') || "Commencez à écrire… tapez '/' pour les commandes"}
|
||||
value={content}
|
||||
onFocus={() => setShowMarkdownPreview(false)}
|
||||
onChange={(e) => { setContent(e.target.value); setIsDirty(true) }}
|
||||
disabled={readOnly}
|
||||
className="w-full min-h-[60vh] border-0 outline-none px-0 bg-transparent text-lg leading-relaxed font-light resize-none placeholder:text-foreground/20 text-foreground/80"
|
||||
className="w-full min-h-[280px] border-0 outline-none px-0 bg-transparent text-lg leading-relaxed font-light resize-none overflow-hidden placeholder:text-foreground/20 text-foreground/80"
|
||||
/>
|
||||
{content && !readOnly && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowMarkdownPreview(true)}
|
||||
className="mt-2 text-[11px] text-foreground/40 hover:text-foreground flex items-center gap-1.5 transition-colors"
|
||||
>
|
||||
<Eye className="h-3 w-3" /> Preview
|
||||
</button>
|
||||
)}
|
||||
{!readOnly && (
|
||||
<MarkdownSlashCommands
|
||||
textareaRef={textareaRef as React.RefObject<HTMLTextAreaElement>}
|
||||
|
||||
Reference in New Issue
Block a user