UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: унификация нижнего dock и CTA-кнопки

This commit is contained in:
DCCONSTRUCTIONS 2026-04-21 10:22:22 +03:00
parent bcd4d676db
commit e4a59e7a54
7 changed files with 67 additions and 18 deletions

View File

@ -17,7 +17,6 @@ import {
WORK_ITEM_TRACKER_ELEMENTS, WORK_ITEM_TRACKER_ELEMENTS,
} from "@plane/constants"; } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { NewTabIcon, WorkItemsIcon } from "@plane/propel/icons"; import { NewTabIcon, WorkItemsIcon } from "@plane/propel/icons";
import { Tooltip } from "@plane/propel/tooltip"; import { Tooltip } from "@plane/propel/tooltip";
import { EIssuesStoreType } from "@plane/types"; import { EIssuesStoreType } from "@plane/types";
@ -25,6 +24,7 @@ import { Breadcrumbs, Header } from "@plane/ui";
// components // components
import { BreadcrumbLink } from "@/components/common/breadcrumb-link"; import { BreadcrumbLink } from "@/components/common/breadcrumb-link";
import { CountChip } from "@/components/common/count-chip"; import { CountChip } from "@/components/common/count-chip";
import { AppHeaderPrimaryActionButton } from "@/components/core/app-header/primary-action-button";
// constants // constants
import { HeaderFilters } from "@/components/issues/filters"; import { HeaderFilters } from "@/components/issues/filters";
// helpers // helpers
@ -117,18 +117,14 @@ export const IssuesHeader = observer(function IssuesHeader() {
/> />
</div> </div>
{canUserCreateIssue && ( {canUserCreateIssue && (
<Button <AppHeaderPrimaryActionButton
variant="primary"
size="lg"
className="nodedc-toolbar-primary nodedc-toolbar-primary-wide"
onClick={() => { onClick={() => {
toggleCreateIssueModal(true, EIssuesStoreType.PROJECT); toggleCreateIssueModal(true, EIssuesStoreType.PROJECT);
}} }}
data-ph-element={WORK_ITEM_TRACKER_ELEMENTS.HEADER_ADD_BUTTON.WORK_ITEMS} data-ph-element={WORK_ITEM_TRACKER_ELEMENTS.HEADER_ADD_BUTTON.WORK_ITEMS}
> >
<div className="block sm:hidden">{t("issue.label", { count: 1 })}</div> {t("app_header.add_task")}
<div className="hidden sm:block">{t("issue.add.label")}</div> </AppHeaderPrimaryActionButton>
</Button>
)} )}
</Header.RightItem> </Header.RightItem>
</Header> </Header>

View File

@ -10,10 +10,10 @@ import { useParams } from "next/navigation";
import { RefreshCcw } from "lucide-react"; import { RefreshCcw } from "lucide-react";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { TransferIcon } from "@plane/propel/icons"; import { TransferIcon } from "@plane/propel/icons";
import { Breadcrumbs, Header } from "@plane/ui"; import { Breadcrumbs, Header } from "@plane/ui";
import { BreadcrumbLink } from "@/components/common/breadcrumb-link"; import { BreadcrumbLink } from "@/components/common/breadcrumb-link";
import { AppHeaderPrimaryActionButton } from "@/components/core/app-header/primary-action-button";
import { useProject } from "@/hooks/store/use-project"; import { useProject } from "@/hooks/store/use-project";
import { useProjectExternalContours } from "@/hooks/store/use-project-external-contours"; import { useProjectExternalContours } from "@/hooks/store/use-project-external-contours";
import { useUserPermissions } from "@/hooks/store/user"; import { useUserPermissions } from "@/hooks/store/user";
@ -69,14 +69,9 @@ export const ProjectExternalContoursHeader = observer(function ProjectExternalCo
modalState={createIssueModal} modalState={createIssueModal}
handleModalClose={() => setCreateIssueModal(false)} handleModalClose={() => setCreateIssueModal(false)}
/> />
<Button <AppHeaderPrimaryActionButton onClick={() => setCreateIssueModal(true)}>
variant="primary" {t("app_header.add_task")}
size="lg" </AppHeaderPrimaryActionButton>
onClick={() => setCreateIssueModal(true)}
className="nodedc-external-primary-button min-w-[14rem]"
>
{t("external_contours_page.header.add_request")}
</Button>
</div> </div>
) : null} ) : null}
</Header.RightItem> </Header.RightItem>

View File

@ -55,7 +55,7 @@ export const AppHeader = observer(function AppHeader(props: AppHeaderProps) {
return ( return (
<div ref={containerRef} className={cn("fixed right-0 bottom-0 z-[18]", className)} style={dockStyle}> <div ref={containerRef} className={cn("fixed right-0 bottom-0 z-[18]", className)} style={dockStyle}>
<Row className={cn("flex h-11 w-full items-center gap-2 border-t border-subtle bg-surface-1", rowClassName)}> <Row className={cn("nodedc-bottom-dock flex h-11 w-full items-center gap-2", rowClassName)}>
<ExtendedAppHeader header={header} /> <ExtendedAppHeader header={header} />
</Row> </Row>
{mobileHeader && mobileHeader} {mobileHeader && mobileHeader}

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import type { ComponentProps } from "react";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { cn } from "@plane/utils";
type TPrimaryActionButtonProps = ComponentProps<typeof Button>;
export const AppHeaderPrimaryActionButton = (props: TPrimaryActionButtonProps) => {
const { children, className, ...buttonProps } = props;
const { t } = useTranslation();
return (
<Button
variant="primary"
size="lg"
className={cn("nodedc-toolbar-primary nodedc-toolbar-primary-wide", className)}
{...buttonProps}
>
{children ?? t("app_header.add_task")}
</Button>
);
};

View File

@ -255,6 +255,30 @@
0 6px 18px rgba(0, 0, 0, 0.2); 0 6px 18px rgba(0, 0, 0, 0.2);
} }
.nodedc-bottom-dock {
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.024) 0%, rgba(255, 255, 255, 0.008) 100%),
rgba(7, 7, 10, 0.72) !important;
border: 0 !important;
outline: none !important;
box-shadow:
0 -18px 46px rgba(0, 0, 0, 0.3),
0 -4px 18px rgba(0, 0, 0, 0.16);
-webkit-backdrop-filter: blur(34px);
backdrop-filter: blur(34px);
}
.nodedc-bottom-dock [class~="bg-surface-1"] {
background: transparent !important;
}
.nodedc-bottom-dock [class~="border-t"],
.nodedc-bottom-dock [class~="border-b"],
.nodedc-bottom-dock [class~="border-subtle"] {
border-width: 0 !important;
border-color: transparent !important;
}
.nodedc-glass-modal [data-slot="button"], .nodedc-glass-modal [data-slot="button"],
.nodedc-glass-modal [data-slot="icon-button"] { .nodedc-glass-modal [data-slot="icon-button"] {
border: none !important; border: none !important;

View File

@ -508,6 +508,9 @@ export default {
no_data_yet: "No Data yet", no_data_yet: "No Data yet",
syncing: "Syncing", syncing: "Syncing",
add_work_item: "Add work item", add_work_item: "Add work item",
app_header: {
add_task: "Add task",
},
advanced_description_placeholder: "Press '/' for commands", advanced_description_placeholder: "Press '/' for commands",
create_work_item: "Create work item", create_work_item: "Create work item",
attachments: "Attachments", attachments: "Attachments",

View File

@ -664,6 +664,9 @@ export default {
no_data_yet: "Нет данных", no_data_yet: "Нет данных",
syncing: "Синхронизация", syncing: "Синхронизация",
add_work_item: "Добавить рабочий элемент", add_work_item: "Добавить рабочий элемент",
app_header: {
add_task: "Добавить задачу",
},
advanced_description_placeholder: "Нажмите '/' для команд", advanced_description_placeholder: "Нажмите '/' для команд",
create_work_item: "Создать рабочий элемент", create_work_item: "Создать рабочий элемент",
attachments: "Вложения", attachments: "Вложения",