v3: editor fixes
This commit is contained in:
@@ -22,6 +22,7 @@ import { ErrorCard } from "./ErrorCard.tsx";
|
||||
import { FileDropZone } from "./FileDropZone.tsx";
|
||||
import { friendlyFetchError } from "../utils/apiError.ts";
|
||||
import { MAX_FILE_SIZE } from "../config/upload.ts";
|
||||
import { TextEditor } from "./TextEditor.tsx";
|
||||
|
||||
type Mode = "url" | "file";
|
||||
type Phase = "create" | "playlist";
|
||||
@@ -98,10 +99,10 @@ export function DumpCreateModal({ onClose }: DumpCreateModalProps) {
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Escape key to close
|
||||
// Escape key to close (skip if a picker/dropdown already handled it)
|
||||
useEffect(() => {
|
||||
const handler = (e: KeyboardEvent) => {
|
||||
if (e.key === "Escape") onClose();
|
||||
if (e.key === "Escape" && !e.defaultPrevented) onClose();
|
||||
};
|
||||
document.addEventListener("keydown", handler);
|
||||
return () => document.removeEventListener("keydown", handler);
|
||||
@@ -389,10 +390,10 @@ export function DumpCreateModal({ onClose }: DumpCreateModalProps) {
|
||||
<label htmlFor="dc-comment">
|
||||
Why are you dumping this?
|
||||
</label>
|
||||
<textarea
|
||||
<TextEditor
|
||||
id="dc-comment"
|
||||
value={comment}
|
||||
onChange={(e) => setComment(e.target.value)}
|
||||
onChange={setComment}
|
||||
disabled={submitting}
|
||||
placeholder="Tell the community what makes this worth their time..."
|
||||
rows={3}
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { Playlist, RawPlaylist } from "../model.ts";
|
||||
import { deserializePlaylist } from "../model.ts";
|
||||
import { useAuth } from "../hooks/useAuth.ts";
|
||||
import { ErrorCard } from "./ErrorCard.tsx";
|
||||
import { TextEditor } from "./TextEditor.tsx";
|
||||
|
||||
interface PlaylistCreateFormProps {
|
||||
/** If provided, the new playlist will have this dump added to it. */
|
||||
@@ -67,10 +68,10 @@ export function PlaylistCreateForm(
|
||||
autoFocus
|
||||
required
|
||||
/>
|
||||
<textarea
|
||||
<TextEditor
|
||||
placeholder="Description (optional)"
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
onChange={setDescription}
|
||||
rows={3}
|
||||
/>
|
||||
<div className="visibility-toggle">
|
||||
|
||||
@@ -144,11 +144,21 @@ export const TextEditor = forwardRef<TextEditorHandle, TextEditorProps>(
|
||||
<EmojiPicker.Root
|
||||
onEmojiSelect={(e) => handleEmojiSelect(e.emoji)}
|
||||
>
|
||||
<EmojiPicker.Search
|
||||
ref={emojiSearchRef}
|
||||
defaultValue={emojiQuery}
|
||||
placeholder="Search emoji…"
|
||||
/>
|
||||
<div className="emoji-picker-search-row">
|
||||
<EmojiPicker.Search
|
||||
ref={emojiSearchRef}
|
||||
defaultValue={emojiQuery}
|
||||
placeholder="Search emoji…"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="emoji-picker-close-btn"
|
||||
onClick={closeEmoji}
|
||||
aria-label="Close emoji picker"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
<EmojiPicker.Viewport
|
||||
ref={emojiViewportRef}
|
||||
// tabIndex={-1} makes the div programmatically focusable so
|
||||
|
||||
Reference in New Issue
Block a user