bb-plane-fork/apps/space/components/editor/toolbar.tsx
sriram veeraghanta 7fb6696c67
chore: space folders (#8707)
* chore: change the space folders structure

* fix: format
2026-03-05 14:03:54 +05:30

119 lines
4.1 KiB
TypeScript

/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React, { useEffect, useState, useCallback } from "react";
// plane imports
import { TOOLBAR_ITEMS } from "@plane/editor";
import type { ToolbarMenuItem, EditorRefApi } from "@plane/editor";
import { Button } from "@plane/propel/button";
import { Tooltip } from "@plane/propel/tooltip";
import { cn } from "@plane/utils";
type Props = {
executeCommand: (item: ToolbarMenuItem) => void;
handleSubmit: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
isCommentEmpty: boolean;
isSubmitting: boolean;
showSubmitButton: boolean;
editorRef: EditorRefApi | null;
};
const toolbarItems = TOOLBAR_ITEMS.lite;
export function IssueCommentToolbar(props: Props) {
const { executeCommand, handleSubmit, isCommentEmpty, editorRef, isSubmitting, showSubmitButton } = props;
// states
const [activeStates, setActiveStates] = useState<Record<string, boolean>>({});
// Function to update active states
const updateActiveStates = useCallback(() => {
if (!editorRef) return;
const newActiveStates: Record<string, boolean> = {};
Object.values(toolbarItems)
.flat()
.forEach((item) => {
// TODO: update this while toolbar homogenization
// @ts-expect-error type mismatch here
newActiveStates[item.renderKey] = editorRef.isMenuItemActive({
itemKey: item.itemKey,
...item.extraProps,
});
});
setActiveStates(newActiveStates);
}, [editorRef]);
// useEffect to call updateActiveStates when isActive prop changes
useEffect(() => {
if (!editorRef) return;
const unsubscribe = editorRef.onStateChange(updateActiveStates);
updateActiveStates();
return () => unsubscribe();
}, [editorRef, updateActiveStates]);
return (
<div className="flex h-9 w-full items-stretch gap-1.5 overflow-x-scroll">
<div className="flex w-full items-stretch justify-between gap-2 rounded-sm border-[0.5px] border-subtle p-1">
<div className="flex items-stretch">
{Object.keys(toolbarItems).map((key, index) => (
<div
key={key}
className={cn("flex items-stretch gap-0.5 border-r border-subtle px-2.5", {
"pl-0": index === 0,
})}
>
{toolbarItems[key].map((item) => {
const isItemActive = activeStates[item.renderKey];
return (
<Tooltip
key={item.renderKey}
tooltipContent={
<p className="flex flex-col gap-1 text-center text-11">
<span className="font-medium">{item.name}</span>
{item.shortcut && <kbd className="text-placeholder">{item.shortcut.join(" + ")}</kbd>}
</p>
}
>
<button
type="button"
onClick={() => executeCommand(item)}
className={cn(
"grid aspect-square place-items-center rounded-xs p-0.5 text-placeholder hover:bg-layer-transparent-hover",
{
"bg-layer-transparent-hover text-primary": isItemActive,
}
)}
>
<item.icon
className={cn("h-3.5 w-3.5", {
"text-primary": isItemActive,
})}
strokeWidth={2.5}
/>
</button>
</Tooltip>
);
})}
</div>
))}
</div>
{showSubmitButton && (
<div className="sticky right-1">
<Button
type="button"
variant="primary"
onClick={handleSubmit}
disabled={isCommentEmpty}
loading={isSubmitting}
>
Comment
</Button>
</div>
)}
</div>
</div>
);
}