From 4ba06307ed31712456814906d2c440fc8a8f016f Mon Sep 17 00:00:00 2001 From: DCCONSTRUCTIONS Date: Sun, 19 Apr 2026 14:21:23 +0300 Subject: [PATCH] =?UTF-8?q?UI=20-=20=D0=9C=D0=95=D0=96=D0=9F=D0=A0=D0=9E?= =?UTF-8?q?=D0=95=D0=9A=D0=A2=D0=9D=D0=90=D0=AF=20=D0=9A=D0=9E=D0=9C=D0=9C?= =?UTF-8?q?=D0=A3=D0=9D=D0=98=D0=9A=D0=90=D0=A6=D0=98=D0=AF:=20glass=20she?= =?UTF-8?q?ll=20=D0=B8=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B0=D0=BA=D1=82=D0=BD?= =?UTF-8?q?=D1=8B=D0=B9=20composer=20=D0=BE=D1=82=D0=BA=D1=80=D1=8B=D1=82?= =?UTF-8?q?=D0=BE=D0=B9=20=D0=BA=D0=B0=D1=80=D1=82=D0=BE=D1=87=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B2=D0=BD=D1=83=D1=82=D1=80=D0=B5=D0=BD=D0=BD=D0=B5=D0=B3?= =?UTF-8?q?=D0=BE=20=D0=BA=D0=BE=D0=BD=D1=82=D1=83=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/comments/comment-create.tsx | 19 +++++-- .../components/editor/lite-text/editor.tsx | 3 ++ .../components/editor/lite-text/toolbar.tsx | 49 ++++++++++++++++++- .../issue-detail-widgets/action-buttons.tsx | 10 +++- .../issues/issue-detail-widgets/root.tsx | 3 ++ .../issue-detail-widgets/widget-button.tsx | 16 +++++- .../issue-detail/issue-activity/root.tsx | 24 +++++---- .../issues/issue-detail/subscription.tsx | 6 ++- .../quick-action-dropdowns/issue-detail.tsx | 4 +- .../issues/peek-overview/header.tsx | 20 ++++++-- .../components/issues/peek-overview/view.tsx | 13 +++-- 11 files changed, 138 insertions(+), 29 deletions(-) diff --git a/plane-src/apps/web/core/components/comments/comment-create.tsx b/plane-src/apps/web/core/components/comments/comment-create.tsx index d230a5b..c8a6bc3 100644 --- a/plane-src/apps/web/core/components/comments/comment-create.tsx +++ b/plane-src/apps/web/core/components/comments/comment-create.tsx @@ -26,6 +26,7 @@ type TCommentCreate = { showToolbarInitially?: boolean; projectId?: string; onSubmitCallback?: (elementId: string) => void; + appearance?: "default" | "issue-peek-compact"; }; // services @@ -39,6 +40,7 @@ export const CommentCreate = observer(function CommentCreate(props: TCommentCrea showToolbarInitially = false, projectId, onSubmitCallback, + appearance = "default", } = props; // states const [uploadedAssetIds, setUploadedAssetIds] = useState([]); @@ -89,10 +91,13 @@ export const CommentCreate = observer(function CommentCreate(props: TCommentCrea const commentHTML = watch("comment_html"); const isEmpty = isCommentEmpty(commentHTML ?? undefined); + const isCompactAppearance = appearance === "issue-peek-compact"; return (
{ if ( e.key === "Enter" && @@ -128,7 +133,6 @@ export const CommentCreate = observer(function CommentCreate(props: TCommentCrea }} ref={editorRef} initialValue={value ?? "

"} - containerClassName="min-h-min" onChange={(comment_json, comment_html) => onChange(comment_html)} accessSpecifier={accessValue ?? EIssueCommentAccessSpecifier.INTERNAL} handleAccessChange={onAccessChange} @@ -144,7 +148,16 @@ export const CommentCreate = observer(function CommentCreate(props: TCommentCrea return asset_id; }} showToolbarInitially={showToolbarInitially} - parentClassName="p-2" + parentClassName={cn( + isCompactAppearance + ? "rounded-[20px] border border-subtle/70 bg-layer-2/75 p-4 backdrop-blur-xl" + : "p-2" + )} + variant={isCompactAppearance ? "full" : "full"} + toolbarMode={isCompactAppearance ? "compact-comment" : "default"} + showPlaceholderOnEmpty={isCompactAppearance} + editorClassName={cn(isCompactAppearance && "min-h-[112px]")} + containerClassName={cn(isCompactAppearance ? "min-h-[112px] border-none p-0" : "min-h-min")} displayConfig={{ fontSize: "small-font", }} diff --git a/plane-src/apps/web/core/components/editor/lite-text/editor.tsx b/plane-src/apps/web/core/components/editor/lite-text/editor.tsx index 257f106..34c18ef 100644 --- a/plane-src/apps/web/core/components/editor/lite-text/editor.tsx +++ b/plane-src/apps/web/core/components/editor/lite-text/editor.tsx @@ -45,6 +45,7 @@ type LiteTextEditorWrapperProps = MakeOptional< parentClassName?: string; editorClassName?: string; submitButtonText?: string; + toolbarMode?: "default" | "compact-comment"; } & ( | { editable: false; @@ -81,6 +82,7 @@ export const LiteTextEditor = React.forwardRef(function LiteTextEditor( editorClassName = "", showPlaceholderOnEmpty = true, submitButtonText = "common.comment", + toolbarMode = "default", ...rest } = props; // states @@ -217,6 +219,7 @@ export const LiteTextEditor = React.forwardRef(function LiteTextEditor( editorRef={editorRef} showSubmitButton={showSubmitButton} submitButtonText={submitButtonText} + mode={toolbarMode} />
)} diff --git a/plane-src/apps/web/core/components/editor/lite-text/toolbar.tsx b/plane-src/apps/web/core/components/editor/lite-text/toolbar.tsx index d23100a..c66f142 100644 --- a/plane-src/apps/web/core/components/editor/lite-text/toolbar.tsx +++ b/plane-src/apps/web/core/components/editor/lite-text/toolbar.tsx @@ -5,6 +5,7 @@ */ import React, { useEffect, useState, useCallback } from "react"; +import { ArrowUp, Paperclip, SmilePlus } from "lucide-react"; import type { LucideIcon } from "lucide-react"; import { EIssueCommentAccessSpecifier } from "@plane/constants"; @@ -20,7 +21,7 @@ import { Tooltip } from "@plane/propel/tooltip"; // constants import { cn } from "@plane/utils"; import type { ToolbarMenuItem } from "@/constants/editor"; -import { TOOLBAR_ITEMS } from "@/constants/editor"; +import { IMAGE_ITEM, TOOLBAR_ITEMS } from "@/constants/editor"; // helpers type Props = { @@ -34,6 +35,7 @@ type Props = { showSubmitButton: boolean; editorRef: EditorRefApi | null; submitButtonText?: string; + mode?: "default" | "compact-comment"; }; type TCommentAccessType = { @@ -56,6 +58,13 @@ const COMMENT_ACCESS_SPECIFIERS: TCommentAccessType[] = [ ]; const toolbarItems = TOOLBAR_ITEMS.lite; +const EMOJI_ITEM: ToolbarMenuItem<"emoji"> = { + itemKey: "emoji", + renderKey: "emoji", + name: "Emoji", + icon: SmilePlus, + editors: ["lite", "document"], +}; export function IssueCommentToolbar(props: Props) { const { t } = useTranslation(); @@ -70,6 +79,7 @@ export function IssueCommentToolbar(props: Props) { showSubmitButton, editorRef, submitButtonText = "common.comment", + mode = "default", } = props; // State to manage active states of toolbar items const [activeStates, setActiveStates] = useState>({}); @@ -102,6 +112,43 @@ export function IssueCommentToolbar(props: Props) { const isEditorReadyToDiscard = editorRef?.isEditorReadyToDiscard(); const isSubmitButtonDisabled = isCommentEmpty || !isEditorReadyToDiscard; + if (mode === "compact-comment") { + return ( +
+
+ + + + + + +
+ {showSubmitButton && ( + + )} +
+ ); + } + return (
{showAccessSpecifier && ( diff --git a/plane-src/apps/web/core/components/issues/issue-detail-widgets/action-buttons.tsx b/plane-src/apps/web/core/components/issues/issue-detail-widgets/action-buttons.tsx index e9b1ac4..815df3b 100644 --- a/plane-src/apps/web/core/components/issues/issue-detail-widgets/action-buttons.tsx +++ b/plane-src/apps/web/core/components/issues/issue-detail-widgets/action-buttons.tsx @@ -10,6 +10,7 @@ import { useTranslation } from "@plane/i18n"; import { LinkIcon, ViewsIcon, RelationPropertyIcon } from "@plane/propel/icons"; // plane imports import type { TIssueServiceType, TWorkItemWidgets } from "@plane/types"; +import { cn } from "@plane/utils"; // plane web imports import { WorkItemAdditionalWidgetActionButtons } from "@/plane-web/components/issues/issue-detail-widgets/action-buttons"; // local imports @@ -26,15 +27,16 @@ type Props = { disabled: boolean; issueServiceType: TIssueServiceType; hideWidgets?: TWorkItemWidgets[]; + compactView?: boolean; }; export function IssueDetailWidgetActionButtons(props: Props) { - const { workspaceSlug, projectId, issueId, disabled, issueServiceType, hideWidgets } = props; + const { workspaceSlug, projectId, issueId, disabled, issueServiceType, hideWidgets, compactView = false } = props; // translation const { t } = useTranslation(); return ( -
+
{!hideWidgets?.includes("sub-work-items") && ( } disabled={disabled} + compactView={compactView} /> } disabled={disabled} @@ -57,6 +60,7 @@ export function IssueDetailWidgetActionButtons(props: Props) { title={t("issue.add.relation")} icon={} disabled={disabled} + compactView={compactView} /> } disabled={disabled} @@ -70,6 +74,7 @@ export function IssueDetailWidgetActionButtons(props: Props) { title={t("issue.add.link")} icon={} disabled={disabled} + compactView={compactView} /> } disabled={disabled} @@ -86,6 +91,7 @@ export function IssueDetailWidgetActionButtons(props: Props) { title={t("common.attach")} icon={} disabled={disabled} + compactView={compactView} /> } disabled={disabled} diff --git a/plane-src/apps/web/core/components/issues/issue-detail-widgets/root.tsx b/plane-src/apps/web/core/components/issues/issue-detail-widgets/root.tsx index 2218ec3..b918945 100644 --- a/plane-src/apps/web/core/components/issues/issue-detail-widgets/root.tsx +++ b/plane-src/apps/web/core/components/issues/issue-detail-widgets/root.tsx @@ -20,6 +20,7 @@ type Props = { renderWidgetModals?: boolean; issueServiceType: TIssueServiceType; hideWidgets?: TWorkItemWidgets[]; + compactView?: boolean; }; export function IssueDetailWidgets(props: Props) { @@ -31,6 +32,7 @@ export function IssueDetailWidgets(props: Props) { renderWidgetModals = true, issueServiceType, hideWidgets, + compactView = false, } = props; return ( @@ -43,6 +45,7 @@ export function IssueDetailWidgets(props: Props) { disabled={disabled} issueServiceType={issueServiceType} hideWidgets={hideWidgets} + compactView={compactView} /> + diff --git a/plane-src/apps/web/core/components/issues/issue-detail/issue-activity/root.tsx b/plane-src/apps/web/core/components/issues/issue-detail/issue-activity/root.tsx index 66e3bad..f70352e 100644 --- a/plane-src/apps/web/core/components/issues/issue-detail/issue-activity/root.tsx +++ b/plane-src/apps/web/core/components/issues/issue-detail/issue-activity/root.tsx @@ -15,6 +15,7 @@ import { useLocalStorage } from "@plane/hooks"; import { useTranslation } from "@plane/i18n"; //types import type { TFileSignedURLResponse, TIssueComment } from "@plane/types"; +import { cn } from "@plane/utils"; // components import { CommentCreate } from "@/components/comments/comment-create"; // hooks @@ -34,6 +35,7 @@ type TIssueActivity = { issueId: string; disabled?: boolean; isIntakeIssue?: boolean; + compactComposer?: boolean; }; export type TActivityOperations = { @@ -44,7 +46,7 @@ export type TActivityOperations = { }; export const IssueActivity = observer(function IssueActivity(props: TIssueActivity) { - const { workspaceSlug, projectId, issueId, disabled = false, isIntakeIssue = false } = props; + const { workspaceSlug, projectId, issueId, disabled = false, isIntakeIssue = false, compactComposer = false } = props; // i18n const { t } = useTranslation(); // hooks @@ -92,15 +94,19 @@ export const IssueActivity = observer(function IssueActivity(props: TIssueActivi const project = getProjectById(projectId); const renderCommentCreationBox = useMemo( () => ( - +
+ {compactComposer &&
{t("issue.comments.placeholder")}
} + +
), - [workspaceSlug, issueId, activityOperations, projectId] + [workspaceSlug, issueId, activityOperations, projectId, compactComposer, t] ); if (!project) return <>; diff --git a/plane-src/apps/web/core/components/issues/issue-detail/subscription.tsx b/plane-src/apps/web/core/components/issues/issue-detail/subscription.tsx index d9573d6..b139679 100644 --- a/plane-src/apps/web/core/components/issues/issue-detail/subscription.tsx +++ b/plane-src/apps/web/core/components/issues/issue-detail/subscription.tsx @@ -16,6 +16,7 @@ import { Button } from "@plane/propel/button"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; import { EIssueServiceType } from "@plane/types"; import { Loader } from "@plane/ui"; +import { cn } from "@plane/utils"; // hooks import { useIssueDetail } from "@/hooks/store/use-issue-detail"; import { useUserPermissions } from "@/hooks/store/user"; @@ -25,10 +26,11 @@ export type TIssueSubscription = { projectId: string; issueId: string; serviceType?: EIssueServiceType; + buttonClassName?: string; }; export const IssueSubscription = observer(function IssueSubscription(props: TIssueSubscription) { - const { workspaceSlug, projectId, issueId, serviceType = EIssueServiceType.ISSUES } = props; + const { workspaceSlug, projectId, issueId, serviceType = EIssueServiceType.ISSUES, buttonClassName } = props; const { t } = useTranslation(); // hooks const { @@ -84,7 +86,7 @@ export const IssueSubscription = observer(function IssueSubscription(props: TIss