Fullscreen mode for content editor
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useRef, useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import type { FormEvent, ChangeEvent } from 'react';
|
||||
import { createBrowserSupabase } from '../../lib/supabase';
|
||||
import {
|
||||
@@ -16,6 +16,8 @@ import {
|
||||
ListsToggle,
|
||||
BlockTypeSelect,
|
||||
InsertImage,
|
||||
Separator,
|
||||
ButtonWithTooltip,
|
||||
} from '@mdxeditor/editor';
|
||||
import '@mdxeditor/editor/style.css';
|
||||
import type { Dict } from '../../lib/i18n';
|
||||
@@ -71,9 +73,69 @@ async function imageUploadHandler(file: File): Promise<string> {
|
||||
}
|
||||
}
|
||||
|
||||
function ContentEditor({ content, onChange }: ContentEditorProps) {
|
||||
function ExpandIcon() {
|
||||
return (
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path d="M8 3H5a2 2 0 0 0-2 2v3" />
|
||||
<path d="M16 3h3a2 2 0 0 1 2 2v3" />
|
||||
<path d="M8 21H5a2 2 0 0 1-2-2v-3" />
|
||||
<path d="M16 21h3a2 2 0 0 0 2-2v-3" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function CollapseIcon() {
|
||||
return (
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path d="M3 8h3a2 2 0 0 0 2-2V3" />
|
||||
<path d="M21 8h-3a2 2 0 0 1-2-2V3" />
|
||||
<path d="M3 16h3a2 2 0 0 1 2 2v3" />
|
||||
<path d="M21 16h-3a2 2 0 0 0-2 2v3" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function ContentEditor({ content, onChange }: ContentEditorProps) {
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!expanded) return;
|
||||
const previousOverflow = document.body.style.overflow;
|
||||
document.body.style.overflow = 'hidden';
|
||||
function handleKeyDown(e: KeyboardEvent) {
|
||||
if (e.key === 'Escape') setExpanded(false);
|
||||
}
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
return () => {
|
||||
document.body.style.overflow = previousOverflow;
|
||||
document.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [expanded]);
|
||||
|
||||
return (
|
||||
<div className={expanded ? 'content-editor content-editor--expanded' : 'content-editor'}>
|
||||
<MDXEditor
|
||||
className={expanded ? 'mdxeditor-full-height' : undefined}
|
||||
markdown={content}
|
||||
onChange={onChange}
|
||||
plugins={[
|
||||
@@ -91,14 +153,23 @@ function ContentEditor({ content, onChange }: ContentEditorProps) {
|
||||
<BoldItalicUnderlineToggles />
|
||||
<BlockTypeSelect />
|
||||
<ListsToggle />
|
||||
|
||||
<Separator />
|
||||
<InsertImage />
|
||||
<Separator />
|
||||
<ButtonWithTooltip
|
||||
type="button"
|
||||
title={expanded ? 'Collapse' : 'Expand'}
|
||||
onClick={() => setExpanded((v) => !v)}
|
||||
>
|
||||
{expanded ? <CollapseIcon /> : <ExpandIcon />}
|
||||
</ButtonWithTooltip>
|
||||
</>
|
||||
),
|
||||
}),
|
||||
]}
|
||||
contentEditableClassName="prose prose-sm max-w-none textarea"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default function EventEditor({ dict: t, event }: Props) {
|
||||
|
||||
@@ -45,6 +45,21 @@
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.content-editor--expanded {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1000;
|
||||
background: var(--surface);
|
||||
padding: var(--space-4);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.mdxeditor {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.form-error {
|
||||
background: var(--danger-soft);
|
||||
color: var(--danger);
|
||||
|
||||
Reference in New Issue
Block a user