UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: канонизация окна и helper обложек проекта

This commit is contained in:
DCCONSTRUCTIONS 2026-04-23 11:55:06 +03:00
parent c8a669e01c
commit e53209d533
19 changed files with 31 additions and 59 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 379 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 KiB

View File

@ -215,23 +215,23 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
{isOpen && (
<Popover.Panel
className="absolute right-0 z-20 mt-2 rounded-md border border-subtle bg-surface-1 shadow-raised-200"
className="nodedc-glass-modal nodedc-glass-popup-surface absolute right-0 z-20 mt-3 overflow-hidden rounded-[1.75rem]"
static
>
<div
ref={imagePickerRef}
className="flex h-96 w-80 flex-col overflow-auto rounded border border-subtle bg-surface-1 shadow-raised-200 md:h-[36rem] md:w-[36rem]"
className="flex h-[32rem] w-[21rem] flex-col overflow-hidden rounded-[1.75rem] md:h-[38rem] md:w-[38rem]"
>
<Tabs defaultValue={enabledTabs[0]?.key || "images"} className="flex h-full flex-col p-3">
<Tabs.List className="flex rounded bg-layer-3 p-1">
<Tabs defaultValue={enabledTabs[0]?.key || "images"} className="flex h-full flex-col px-4 pt-4 pb-3">
<Tabs.List className="rounded-[1rem] bg-layer-3/80 p-1">
{enabledTabs.map((tab) => (
<Tabs.Trigger key={tab.key} value={tab.key} size="md">
<Tabs.Trigger key={tab.key} value={tab.key} size="md" className="rounded-[0.875rem]">
{tab.title}
</Tabs.Trigger>
))}
<Tabs.Indicator />
</Tabs.List>
<div className="vertical-scrollbar mt-3 scrollbar-sm flex-1 overflow-x-hidden overflow-y-auto p-3">
<div className="vertical-scrollbar mt-4 scrollbar-sm flex-1 overflow-x-hidden overflow-y-auto px-1 pb-1">
<Tabs.Content value="unsplash" className="h-full w-full space-y-4">
{(unsplashImages || !unsplashError) && (
<>
@ -254,21 +254,26 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
onChange={(e) => setFormData({ ...formData, search: e.target.value })}
ref={ref}
placeholder={t("image_picker.search_placeholder")}
className="w-full text-13"
className="nodedc-modal-input w-full !px-4 !py-3 text-13"
/>
)}
/>
<Button variant="primary" size="xl" onClick={() => setSearchParams(formData.search)}>
<Button
variant="primary"
size="lg"
className="nodedc-modal-primary-button min-w-[8rem]"
onClick={() => setSearchParams(formData.search)}
>
{t("image_picker.search_button")}
</Button>
</div>
{unsplashImages ? (
unsplashImages.length > 0 ? (
<div className="grid grid-cols-4 gap-4">
<div className="grid grid-cols-4 gap-3">
{unsplashImages.map((image) => (
<div
key={image.id}
className="relative col-span-2 aspect-video md:col-span-1"
className="nodedc-modal-field relative col-span-2 aspect-video overflow-hidden rounded-[1rem] p-0 md:col-span-1"
onClick={() => {
setIsOpen(false);
onChange(image.urls.regular);
@ -277,7 +282,7 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
<img
src={image.urls.small}
alt={image.alt_description}
className="absolute top-0 left-0 h-full w-full cursor-pointer rounded-sm object-cover"
className="absolute inset-0 h-full w-full cursor-pointer rounded-[1rem] object-cover transition-transform duration-200 hover:scale-[1.02]"
/>
</div>
))}
@ -301,36 +306,36 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
)}
</Tabs.Content>
<Tabs.Content value="images" className="h-full w-full space-y-4">
<div className="grid grid-cols-4 gap-4">
<div className="grid grid-cols-4 gap-3">
{Object.values(STATIC_COVER_IMAGES).map((imageUrl, index) => (
<div
key={imageUrl}
className="relative col-span-2 aspect-video md:col-span-1"
className="nodedc-modal-field relative col-span-2 aspect-video overflow-hidden rounded-[1rem] p-0 md:col-span-1"
onClick={() => handleStaticImageSelect(imageUrl)}
>
<img
src={imageUrl}
alt={t("image_picker.cover_image_alt", { index: index + 1 })}
className="absolute top-0 left-0 h-full w-full cursor-pointer rounded-sm object-cover transition-opacity hover:opacity-80"
className="absolute inset-0 h-full w-full cursor-pointer rounded-[1rem] object-cover transition-transform duration-200 hover:scale-[1.02]"
/>
</div>
))}
</div>
</Tabs.Content>
<Tabs.Content value="upload" className="h-full w-full">
<div className="flex h-full w-full flex-col gap-y-2">
<div className="flex h-full w-full flex-col gap-y-3">
<div className="flex w-full flex-1 items-center gap-3">
<div
{...getRootProps()}
className={`relative grid h-full w-full cursor-pointer place-items-center rounded-lg p-12 text-center focus:ring-2 focus:ring-accent-strong focus:ring-offset-2 focus:outline-none ${
className={`nodedc-modal-field relative grid h-full w-full cursor-pointer place-items-center overflow-hidden rounded-[1.35rem] p-6 text-center ${
(image === null && isDragActive) || !value
? "border-2 border-dashed border-subtle hover:bg-surface-2"
? "border-2 border-dashed border-subtle/80 hover:bg-white/6"
: ""
}`}
>
<button
type="button"
className="absolute top-0 right-0 z-40 -translate-y-1/2 rounded-sm bg-surface-2 px-2 py-0.5 text-11 font-medium text-secondary"
className="nodedc-modal-chip absolute top-3 right-3 z-40 !min-h-0 !px-3 !py-1 text-11 font-medium"
>
{t("image_picker.edit")}
</button>
@ -339,7 +344,7 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
<img
src={image ? URL.createObjectURL(image) : getCoverImageDisplayURL(value, "")}
alt="image"
className="h-full w-full rounded-lg object-cover"
className="h-full w-full rounded-[1rem] object-cover"
/>
</>
) : (
@ -363,19 +368,20 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
<p className="text-13 text-secondary">{t("image_picker.supported_formats")}</p>
<div className="flex h-12 items-start justify-end gap-2">
<div className="mt-auto flex items-start justify-end gap-3 border-t border-subtle/70 pt-4">
<Button
variant="secondary"
onClick={() => {
setIsOpen(false);
setImage(null);
}}
className="nodedc-modal-secondary-button min-w-[8rem]"
>
{t("cancel")}
</Button>
<Button
variant="primary"
className="w-full"
className="nodedc-modal-primary-button min-w-[12rem]"
onClick={handleSubmit}
disabled={!image}
loading={isImageUploading}

View File

@ -7,33 +7,16 @@
import type { EFileAssetType } from "@plane/types";
import { getFileURL } from "@plane/utils";
import CoverImage1 from "@/app/assets/cover-images/image_1.jpg?url";
import CoverImage1 from "@/app/assets/cover-images/image_1.png?url";
import CoverImage10 from "@/app/assets/cover-images/image_10.jpg?url";
import CoverImage11 from "@/app/assets/cover-images/image_11.jpg?url";
import CoverImage11 from "@/app/assets/cover-images/image_11.png?url";
import CoverImage12 from "@/app/assets/cover-images/image_12.jpg?url";
import CoverImage13 from "@/app/assets/cover-images/image_13.jpg?url";
import CoverImage14 from "@/app/assets/cover-images/image_14.jpg?url";
import CoverImage15 from "@/app/assets/cover-images/image_15.jpg?url";
import CoverImage16 from "@/app/assets/cover-images/image_16.jpg?url";
import CoverImage17 from "@/app/assets/cover-images/image_17.jpg?url";
import CoverImage18 from "@/app/assets/cover-images/image_18.jpg?url";
import CoverImage19 from "@/app/assets/cover-images/image_19.jpg?url";
import CoverImage2 from "@/app/assets/cover-images/image_2.jpg?url";
import CoverImage20 from "@/app/assets/cover-images/image_20.jpg?url";
import CoverImage21 from "@/app/assets/cover-images/image_21.jpg?url";
import CoverImage22 from "@/app/assets/cover-images/image_22.jpg?url";
import CoverImage23 from "@/app/assets/cover-images/image_23.jpg?url";
import CoverImage24 from "@/app/assets/cover-images/image_24.jpg?url";
import CoverImage25 from "@/app/assets/cover-images/image_25.jpg?url";
import CoverImage26 from "@/app/assets/cover-images/image_26.jpg?url";
import CoverImage27 from "@/app/assets/cover-images/image_27.jpg?url";
import CoverImage28 from "@/app/assets/cover-images/image_28.jpg?url";
import CoverImage29 from "@/app/assets/cover-images/image_29.jpg?url";
import CoverImage3 from "@/app/assets/cover-images/image_3.jpg?url";
import CoverImage4 from "@/app/assets/cover-images/image_4.jpg?url";
import CoverImage5 from "@/app/assets/cover-images/image_5.jpg?url";
import CoverImage6 from "@/app/assets/cover-images/image_6.jpg?url";
import CoverImage7 from "@/app/assets/cover-images/image_7.jpg?url";
import CoverImage6 from "@/app/assets/cover-images/image_6.webp?url";
import CoverImage7 from "@/app/assets/cover-images/image_7.webp?url";
import CoverImage8 from "@/app/assets/cover-images/image_8.jpg?url";
import CoverImage9 from "@/app/assets/cover-images/image_9.jpg?url";
@ -58,23 +41,6 @@ export const STATIC_COVER_IMAGES = {
IMAGE_10: CoverImage10,
IMAGE_11: CoverImage11,
IMAGE_12: CoverImage12,
IMAGE_13: CoverImage13,
IMAGE_14: CoverImage14,
IMAGE_15: CoverImage15,
IMAGE_16: CoverImage16,
IMAGE_17: CoverImage17,
IMAGE_18: CoverImage18,
IMAGE_19: CoverImage19,
IMAGE_20: CoverImage20,
IMAGE_21: CoverImage21,
IMAGE_22: CoverImage22,
IMAGE_23: CoverImage23,
IMAGE_24: CoverImage24,
IMAGE_25: CoverImage25,
IMAGE_26: CoverImage26,
IMAGE_27: CoverImage27,
IMAGE_28: CoverImage28,
IMAGE_29: CoverImage29,
} as const;
export const DEFAULT_COVER_IMAGE_URL = STATIC_COVER_IMAGES.IMAGE_1;