styling fixes
This commit is contained in:
@@ -159,7 +159,7 @@ export default function CommentBlock(props: CommentBlockProps) {
|
|||||||
|
|
||||||
const isAnonymous = () => props.privilegeLevel === "anonymous";
|
const isAnonymous = () => props.privilegeLevel === "anonymous";
|
||||||
|
|
||||||
const replyIconColor = () => "#fb923c";
|
const replyIconColor = () => "var(--color-peach)";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -169,13 +169,13 @@ export default function CommentBlock(props: CommentBlockProps) {
|
|||||||
onClick={collapseCommentToggle}
|
onClick={collapseCommentToggle}
|
||||||
class="ml-5 w-full px-2 lg:w-3/4"
|
class="ml-5 w-full px-2 lg:w-3/4"
|
||||||
>
|
>
|
||||||
<div class="my-auto mt-1 mr-2 h-8 border-l-2 border-black dark:border-white" />
|
<div class="border-text my-auto mt-1 mr-2 h-8 border-l-2" />
|
||||||
</button>
|
</button>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
{/* Expanded state */}
|
{/* Expanded state */}
|
||||||
<Show when={!commentCollapsed()}>
|
<Show when={!commentCollapsed()}>
|
||||||
<div class="z-[500] transition-all duration-300 ease-in-out">
|
<div class="z-500 transition-all duration-300 ease-in-out">
|
||||||
<div class="my-4 flex w-full overflow-x-hidden overflow-y-hidden lg:w-3/4">
|
<div class="my-4 flex w-full overflow-x-hidden overflow-y-hidden lg:w-3/4">
|
||||||
{/* Vote buttons column */}
|
{/* Vote buttons column */}
|
||||||
<div
|
<div
|
||||||
@@ -191,8 +191,8 @@ export default function CommentBlock(props: CommentBlockProps) {
|
|||||||
<div
|
<div
|
||||||
class={`h-5 w-5 ${
|
class={`h-5 w-5 ${
|
||||||
hasUpvoted()
|
hasUpvoted()
|
||||||
? "fill-emerald-500"
|
? "fill-green"
|
||||||
: `fill-black hover:fill-emerald-500 dark:fill-white ${
|
: `fill-text hover:fill-green ${
|
||||||
isAnonymous() ? "tooltip z-50" : ""
|
isAnonymous() ? "tooltip z-50" : ""
|
||||||
}`
|
}`
|
||||||
}`}
|
}`}
|
||||||
@@ -218,8 +218,8 @@ export default function CommentBlock(props: CommentBlockProps) {
|
|||||||
<div
|
<div
|
||||||
class={`h-5 w-5 ${
|
class={`h-5 w-5 ${
|
||||||
hasDownvoted()
|
hasDownvoted()
|
||||||
? "fill-rose-500"
|
? "fill-red"
|
||||||
: `fill-black hover:fill-rose-500 dark:fill-white ${
|
: `fill-text hover:fill-red ${
|
||||||
isAnonymous() ? "tooltip z-50" : ""
|
isAnonymous() ? "tooltip z-50" : ""
|
||||||
}`
|
}`
|
||||||
}`}
|
}`}
|
||||||
@@ -239,7 +239,7 @@ export default function CommentBlock(props: CommentBlockProps) {
|
|||||||
{/* Collapse toggle line */}
|
{/* Collapse toggle line */}
|
||||||
<button onClick={collapseCommentToggle} class="z-0 px-2">
|
<button onClick={collapseCommentToggle} class="z-0 px-2">
|
||||||
<div
|
<div
|
||||||
class="border-l-2 border-black transition-all duration-300 ease-in-out dark:border-white"
|
class="border-text border-l-2 transition-all duration-300 ease-in-out"
|
||||||
style={{ height: `${toggleHeight()}px` }}
|
style={{ height: `${toggleHeight()}px` }}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
@@ -292,7 +292,7 @@ export default function CommentBlock(props: CommentBlockProps) {
|
|||||||
<TrashIcon
|
<TrashIcon
|
||||||
height={24}
|
height={24}
|
||||||
width={24}
|
width={24}
|
||||||
stroke="red"
|
stroke="var(--color-red)"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ export default function CommentDeletionPrompt(
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<div class="fixed top-48 z-50 h-fit w-11/12 sm:w-4/5 md:w-2/3">
|
<div class="fixed top-48 z-100 h-fit w-11/12 sm:w-4/5 md:w-2/3">
|
||||||
<div
|
<div
|
||||||
id="delete_prompt"
|
id="delete_prompt"
|
||||||
class="fade-in rounded-md bg-red-400 px-8 py-4 shadow-lg dark:bg-red-900"
|
class="fade-in bg-red rounded-md px-8 py-4 shadow-lg brightness-110"
|
||||||
>
|
>
|
||||||
<button class="absolute right-4" onClick={() => {}}>
|
<button class="absolute right-4" onClick={() => {}}>
|
||||||
<Xmark strokeWidth={0.5} color="white" height={50} width={50} />
|
<Xmark strokeWidth={0.5} color="white" height={50} width={50} />
|
||||||
@@ -56,7 +56,7 @@ export default function CommentDeletionPrompt(
|
|||||||
<div class="py-4 text-center text-3xl tracking-wide">
|
<div class="py-4 text-center text-3xl tracking-wide">
|
||||||
Comment Deletion
|
Comment Deletion
|
||||||
</div>
|
</div>
|
||||||
<div class="mx-auto w-3/4 rounded bg-zinc-50 px-6 py-4 dark:bg-zinc-800">
|
<div class="bg-surface0 mx-auto w-3/4 rounded px-6 py-4">
|
||||||
<div class="flex overflow-x-auto overflow-y-hidden select-text">
|
<div class="flex overflow-x-auto overflow-y-hidden select-text">
|
||||||
{/* Comment body will be passed as prop */}
|
{/* Comment body will be passed as prop */}
|
||||||
</div>
|
</div>
|
||||||
@@ -132,9 +132,9 @@ export default function CommentDeletionPrompt(
|
|||||||
disabled={props.commentDeletionLoading || !isDeleteEnabled()}
|
disabled={props.commentDeletionLoading || !isDeleteEnabled()}
|
||||||
class={`${
|
class={`${
|
||||||
props.commentDeletionLoading || !isDeleteEnabled()
|
props.commentDeletionLoading || !isDeleteEnabled()
|
||||||
? "bg-zinc-400"
|
? "bg-surface2 opacity-50"
|
||||||
: "border-orange-500 bg-orange-400 hover:bg-orange-500"
|
: "border-red bg-red hover:brightness-125"
|
||||||
} rounded border px-4 py-2 text-white shadow-md transition-all duration-300 ease-in-out active:scale-90`}
|
} rounded border px-4 py-2 text-base shadow-md transition-all duration-300 ease-in-out active:scale-90`}
|
||||||
>
|
>
|
||||||
Delete
|
Delete
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default function CommentInputBlock(props: CommentInputBlockProps) {
|
|||||||
if (props.privilegeLevel === "user" || props.privilegeLevel === "admin") {
|
if (props.privilegeLevel === "user" || props.privilegeLevel === "admin") {
|
||||||
return (
|
return (
|
||||||
<div class="flex w-full justify-center select-none">
|
<div class="flex w-full justify-center select-none">
|
||||||
<div class="h-fit w-3/4 md:w-1/2">
|
<div class="h-fit w-3/4">
|
||||||
<form onSubmit={newCommentWrapper}>
|
<form onSubmit={newCommentWrapper}>
|
||||||
<div class="textarea-group blog">
|
<div class="textarea-group blog">
|
||||||
<textarea
|
<textarea
|
||||||
@@ -43,9 +43,9 @@ export default function CommentInputBlock(props: CommentInputBlockProps) {
|
|||||||
disabled={props.commentSubmitLoading}
|
disabled={props.commentSubmitLoading}
|
||||||
class={`${
|
class={`${
|
||||||
props.commentSubmitLoading
|
props.commentSubmitLoading
|
||||||
? "bg-zinc-400"
|
? "bg-surface2 opacity-50"
|
||||||
: "border-orange-500 bg-orange-400 hover:bg-orange-500"
|
: "border-sapphire bg-blue hover:brightness-125"
|
||||||
} rounded border px-4 py-2 font-light text-white shadow-md transition-all duration-300 ease-in-out active:scale-90`}
|
} rounded border px-4 py-2 text-base font-light shadow-md transition-all duration-300 ease-in-out active:scale-90`}
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -130,7 +130,16 @@ export default function CommentSectionWrapper(
|
|||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
const updateChannel = () => {
|
const updateChannel = () => {
|
||||||
if (socket && socket.readyState === WebSocket.OPEN) {
|
if (!socket || socket.readyState !== WebSocket.OPEN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!props.currentUserID || !props.id) {
|
||||||
|
console.warn("Cannot update channel: missing userID or postID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
socket.send(
|
socket.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
action: "channelUpdate",
|
action: "channelUpdate",
|
||||||
@@ -139,13 +148,23 @@ export default function CommentSectionWrapper(
|
|||||||
invoker_id: props.currentUserID
|
invoker_id: props.currentUserID
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error sending channel update:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Comment creation
|
// Comment creation
|
||||||
const newComment = async (commentBody: string, parentCommentID?: number) => {
|
const newComment = async (commentBody: string, parentCommentID?: number) => {
|
||||||
setCommentSubmitLoading(true);
|
setCommentSubmitLoading(true);
|
||||||
|
|
||||||
|
if (!props.currentUserID) {
|
||||||
|
console.warn("Cannot create comment: user not authenticated");
|
||||||
|
setCommentSubmitLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (commentBody && socket) {
|
if (commentBody && socket) {
|
||||||
|
try {
|
||||||
socket.send(
|
socket.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
action: "commentCreation",
|
action: "commentCreation",
|
||||||
@@ -156,8 +175,22 @@ export default function CommentSectionWrapper(
|
|||||||
invokerID: props.currentUserID
|
invokerID: props.currentUserID
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error sending comment creation:", error);
|
||||||
|
// Fallback to HTTP API on WebSocket error
|
||||||
|
await fallbackCommentCreation(commentBody, parentCommentID);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fallback to HTTP API if WebSocket unavailable
|
// Fallback to HTTP API if WebSocket unavailable
|
||||||
|
await fallbackCommentCreation(commentBody, parentCommentID);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fallbackCommentCreation = async (
|
||||||
|
commentBody: string,
|
||||||
|
parentCommentID?: number
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
const domain = import.meta.env.VITE_DOMAIN;
|
const domain = import.meta.env.VITE_DOMAIN;
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`${domain}/api/database/comments/create/blog/${props.id}`,
|
`${domain}/api/database/comments/create/blog/${props.id}`,
|
||||||
@@ -179,6 +212,9 @@ export default function CommentSectionWrapper(
|
|||||||
commentParent: parentCommentID
|
commentParent: parentCommentID
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in fallback comment creation:", error);
|
||||||
|
setCommentSubmitLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -237,7 +273,15 @@ export default function CommentSectionWrapper(
|
|||||||
// Comment updating
|
// Comment updating
|
||||||
const editComment = async (body: string, comment_id: number) => {
|
const editComment = async (body: string, comment_id: number) => {
|
||||||
setCommentEditLoading(true);
|
setCommentEditLoading(true);
|
||||||
|
|
||||||
|
if (!props.currentUserID) {
|
||||||
|
console.warn("Cannot edit comment: user not authenticated");
|
||||||
|
setCommentEditLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (socket) {
|
if (socket) {
|
||||||
|
try {
|
||||||
socket.send(
|
socket.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
action: "commentUpdate",
|
action: "commentUpdate",
|
||||||
@@ -248,6 +292,10 @@ export default function CommentSectionWrapper(
|
|||||||
invokerID: props.currentUserID
|
invokerID: props.currentUserID
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error sending comment update:", error);
|
||||||
|
setCommentEditLoading(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -290,7 +338,15 @@ export default function CommentSectionWrapper(
|
|||||||
deletionType: DeletionType
|
deletionType: DeletionType
|
||||||
) => {
|
) => {
|
||||||
setCommentDeletionLoading(true);
|
setCommentDeletionLoading(true);
|
||||||
|
|
||||||
|
if (!props.currentUserID) {
|
||||||
|
console.warn("Cannot delete comment: user not authenticated");
|
||||||
|
setCommentDeletionLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (socket) {
|
if (socket) {
|
||||||
|
try {
|
||||||
socket.send(
|
socket.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
action: "commentDeletion",
|
action: "commentDeletion",
|
||||||
@@ -301,6 +357,10 @@ export default function CommentSectionWrapper(
|
|||||||
postID: props.id
|
postID: props.id
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error sending comment deletion:", error);
|
||||||
|
setCommentDeletionLoading(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -393,7 +453,13 @@ export default function CommentSectionWrapper(
|
|||||||
|
|
||||||
// Reaction handling
|
// Reaction handling
|
||||||
const commentReaction = (reactionType: ReactionType, commentID: number) => {
|
const commentReaction = (reactionType: ReactionType, commentID: number) => {
|
||||||
|
if (!props.currentUserID) {
|
||||||
|
console.warn("Cannot react to comment: user not authenticated");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (socket) {
|
if (socket) {
|
||||||
|
try {
|
||||||
socket.send(
|
socket.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
action: "commentReaction",
|
action: "commentReaction",
|
||||||
@@ -404,6 +470,9 @@ export default function CommentSectionWrapper(
|
|||||||
reactionType: reactionType
|
reactionType: reactionType
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error sending comment reaction:", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export default function CommentSorting(props: CommentSortingProps) {
|
|||||||
{(topLevelComment) => (
|
{(topLevelComment) => (
|
||||||
<div
|
<div
|
||||||
onClick={() => checkForDoubleClick(topLevelComment.id)}
|
onClick={() => checkForDoubleClick(topLevelComment.id)}
|
||||||
class="mt-4 max-w-full rounded bg-white py-2 pl-2 shadow select-none sm:pl-4 md:pl-8 lg:pl-12 dark:bg-zinc-900"
|
class="bg-crust mt-4 max-w-full rounded py-2 pl-2 shadow-xl select-none sm:pl-4 md:pl-8 lg:pl-12"
|
||||||
>
|
>
|
||||||
<Show
|
<Show
|
||||||
when={showingBlock().get(topLevelComment.id)}
|
when={showingBlock().get(topLevelComment.id)}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export default function CommentSortingSelect(props: CommentSortingSelectProps) {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setIsOpen(!isOpen())}
|
onClick={() => setIsOpen(!isOpen())}
|
||||||
class="focus-visible:ring-opacity-75 relative w-full cursor-default rounded-lg bg-white py-2 pr-10 pl-3 text-left shadow-md focus:outline-none focus-visible:border-orange-600 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm dark:bg-zinc-900"
|
class="focus-visible:border-peach focus-visible:ring-offset-peach bg-surface0 focus-visible:ring-opacity-75 relative w-full cursor-default rounded-lg py-2 pr-10 pl-3 text-left shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 sm:text-sm"
|
||||||
>
|
>
|
||||||
<span class="block truncate">{selectedLabel()}</span>
|
<span class="block truncate">{selectedLabel()}</span>
|
||||||
<span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
<span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
||||||
@@ -51,13 +51,13 @@ export default function CommentSortingSelect(props: CommentSortingSelectProps) {
|
|||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
height={24}
|
height={24}
|
||||||
width={24}
|
width={24}
|
||||||
class="fill-zinc-900 dark:fill-white"
|
class="fill-text"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<Show when={isOpen()}>
|
<Show when={isOpen()}>
|
||||||
<div class="ring-opacity-5 absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black transition duration-100 ease-in focus:outline-none sm:text-sm dark:bg-zinc-900">
|
<div class="ring-opacity-5 bg-surface0 ring-overlay0 absolute mt-1 max-h-60 w-full overflow-auto rounded-md py-1 text-base shadow-lg ring-1 focus:outline-none sm:text-sm">
|
||||||
<For each={SORTING_OPTIONS}>
|
<For each={SORTING_OPTIONS}>
|
||||||
{(sort) => (
|
{(sort) => (
|
||||||
<button
|
<button
|
||||||
@@ -65,8 +65,8 @@ export default function CommentSortingSelect(props: CommentSortingSelectProps) {
|
|||||||
onClick={() => handleSelect(sort.val)}
|
onClick={() => handleSelect(sort.val)}
|
||||||
class={`relative w-full cursor-default py-2 pr-4 pl-10 text-left select-none ${
|
class={`relative w-full cursor-default py-2 pr-4 pl-10 text-left select-none ${
|
||||||
props.selectedSorting.val === sort.val
|
props.selectedSorting.val === sort.val
|
||||||
? "bg-orange-100 text-orange-900"
|
? "bg-peach text-base brightness-75"
|
||||||
: "text-zinc-900 hover:bg-orange-50 dark:text-white dark:hover:bg-zinc-800"
|
: "text-text hover:brightness-125"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
@@ -79,12 +79,12 @@ export default function CommentSortingSelect(props: CommentSortingSelectProps) {
|
|||||||
{sort.label}
|
{sort.label}
|
||||||
</span>
|
</span>
|
||||||
<Show when={props.selectedSorting.val === sort.val}>
|
<Show when={props.selectedSorting.val === sort.val}>
|
||||||
<span class="absolute inset-y-0 left-0 flex items-center pl-3 text-orange-600">
|
<span class="text-peach absolute inset-y-0 left-0 flex items-center pl-3">
|
||||||
<Check
|
<Check
|
||||||
strokeWidth={1}
|
strokeWidth={1}
|
||||||
height={24}
|
height={24}
|
||||||
width={24}
|
width={24}
|
||||||
class="stroke-zinc-900 dark:stroke-white"
|
class="stroke-text"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</Show>
|
</Show>
|
||||||
|
|||||||
@@ -25,12 +25,17 @@ export default function EditCommentModal(props: EditCommentModalProps) {
|
|||||||
<div class="fixed top-48 h-fit w-11/12 sm:w-4/5 md:w-2/3">
|
<div class="fixed top-48 h-fit w-11/12 sm:w-4/5 md:w-2/3">
|
||||||
<div
|
<div
|
||||||
id="edit_prompt"
|
id="edit_prompt"
|
||||||
class="fade-in z-50 rounded-md bg-zinc-600 px-8 py-4 shadow-lg dark:bg-zinc-800"
|
class="fade-in bg-surface1 z-50 rounded-md px-8 py-4 shadow-lg"
|
||||||
>
|
>
|
||||||
<button class="absolute right-4" onClick={() => {}}>
|
<button class="absolute right-4" onClick={() => {}}>
|
||||||
<Xmark strokeWidth={0.5} color="white" height={50} width={50} />
|
<Xmark
|
||||||
|
strokeWidth={0.5}
|
||||||
|
color="var(--color-text)"
|
||||||
|
height={50}
|
||||||
|
width={50}
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
<div class="py-4 text-center text-3xl tracking-wide text-zinc-50">
|
<div class="text-text py-4 text-center text-3xl tracking-wide">
|
||||||
Edit Comment
|
Edit Comment
|
||||||
</div>
|
</div>
|
||||||
<form onSubmit={editCommentWrapper}>
|
<form onSubmit={editCommentWrapper}>
|
||||||
@@ -40,7 +45,7 @@ export default function EditCommentModal(props: EditCommentModalProps) {
|
|||||||
ref={bodyRef}
|
ref={bodyRef}
|
||||||
placeholder=" "
|
placeholder=" "
|
||||||
value={props.commentBody}
|
value={props.commentBody}
|
||||||
class="underlinedInput w-full bg-transparent text-blue-300"
|
class="underlinedInput text-blue w-full bg-transparent"
|
||||||
rows={4}
|
rows={4}
|
||||||
/>
|
/>
|
||||||
<span class="bar" />
|
<span class="bar" />
|
||||||
@@ -51,17 +56,17 @@ export default function EditCommentModal(props: EditCommentModalProps) {
|
|||||||
type="submit"
|
type="submit"
|
||||||
disabled={props.editCommentLoading}
|
disabled={props.editCommentLoading}
|
||||||
class={`${
|
class={`${
|
||||||
props.editCommentLoading ? "bg-zinc-400" : ""
|
props.editCommentLoading
|
||||||
} rounded border px-4 py-2 text-white shadow-md transition-all duration-300 ease-in-out hover:border-blue-500 hover:bg-blue-400 active:scale-90`}
|
? "bg-surface2 opacity-50"
|
||||||
|
: "border-sapphire bg-blue hover:brightness-125"
|
||||||
|
} rounded border px-4 py-2 text-base shadow-md transition-all duration-300 ease-in-out active:scale-90`}
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<Show when={showNoChange()}>
|
<Show when={showNoChange()}>
|
||||||
<div class="text-center text-red-500 italic">
|
<div class="text-red text-center italic">No change detected</div>
|
||||||
No change detected
|
|
||||||
</div>
|
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export default function ReactionBar(props: ReactionBarProps) {
|
|||||||
<div
|
<div
|
||||||
class={`${
|
class={`${
|
||||||
props.showingReactionOptions
|
props.showingReactionOptions
|
||||||
? "bg-zinc-50 px-2 py-4 shadow-inner dark:bg-zinc-700"
|
? "bg-surface0 px-2 py-4 shadow-inner brightness-90"
|
||||||
: ""
|
: ""
|
||||||
} fade-in scrollYDisabled ml-2 flex min-h-[1.5rem] w-48 max-w-[1/4] flex-row overflow-scroll rounded-md py-1 sm:w-56 md:w-fit md:overflow-hidden`}
|
} fade-in scrollYDisabled ml-2 flex min-h-[1.5rem] w-48 max-w-[1/4] flex-row overflow-scroll rounded-md py-1 sm:w-56 md:w-fit md:overflow-hidden`}
|
||||||
>
|
>
|
||||||
@@ -57,7 +57,7 @@ export default function ReactionBar(props: ReactionBarProps) {
|
|||||||
{({ type, Component }) => (
|
{({ type, Component }) => (
|
||||||
<Show when={shouldShowEmoji(type)}>
|
<Show when={shouldShowEmoji(type)}>
|
||||||
<div class="fade-in mx-1 flex">
|
<div class="fade-in mx-1 flex">
|
||||||
<div class={hasUserReacted(type) ? "text-green-500" : ""}>
|
<div class={hasUserReacted(type) ? "text-green" : ""}>
|
||||||
<Show when={getReactionCount(type) > 0}>
|
<Show when={getReactionCount(type) > 0}>
|
||||||
{getReactionCount(type)}
|
{getReactionCount(type)}
|
||||||
</Show>
|
</Show>
|
||||||
|
|||||||
@@ -348,12 +348,10 @@ export default function TextEditor(props: TextEditorProps) {
|
|||||||
|
|
||||||
const title = window.prompt("Section title:", "Click to expand");
|
const title = window.prompt("Section title:", "Click to expand");
|
||||||
|
|
||||||
if (title !== null) {
|
if (title !== null && title.trim() !== "") {
|
||||||
instance
|
const content = {
|
||||||
.chain()
|
|
||||||
.focus()
|
|
||||||
.insertContent({
|
|
||||||
type: "details",
|
type: "details",
|
||||||
|
attrs: { open: true },
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: "detailsSummary",
|
type: "detailsSummary",
|
||||||
@@ -363,14 +361,37 @@ export default function TextEditor(props: TextEditorProps) {
|
|||||||
type: "detailsContent",
|
type: "detailsContent",
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: "paragraph",
|
type: "paragraph"
|
||||||
content: [{ type: "text", text: "Add your content here..." }]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
};
|
||||||
.run();
|
|
||||||
|
const { from } = instance.state.selection;
|
||||||
|
instance.chain().focus().insertContent(content).run();
|
||||||
|
|
||||||
|
// Move cursor to the paragraph inside detailsContent
|
||||||
|
// Structure: details (from+1) > detailsSummary > detailsContent > paragraph
|
||||||
|
// We need to position inside the paragraph which is roughly from + title.length + 3 nodes deep
|
||||||
|
setTimeout(() => {
|
||||||
|
const { state } = instance;
|
||||||
|
let targetPos = from;
|
||||||
|
|
||||||
|
// Navigate through the document to find the paragraph inside detailsContent
|
||||||
|
state.doc.nodesBetween(from, from + 200, (node, pos) => {
|
||||||
|
if (node.type.name === "detailsContent") {
|
||||||
|
// Position cursor at the start of the first child (paragraph)
|
||||||
|
targetPos = pos + 1;
|
||||||
|
return false; // Stop iteration
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (targetPos > from) {
|
||||||
|
instance.commands.setTextSelection(targetPos);
|
||||||
|
instance.commands.focus();
|
||||||
|
}
|
||||||
|
}, 10);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user