131 lines
8.5 KiB
Diff
131 lines
8.5 KiB
Diff
diff --git a/plane-src/apps/web/core/components/core/image-picker-popover.tsx b/plane-src/apps/web/core/components/core/image-picker-popover.tsx
|
|
index 431143a..0927b6e 100644
|
|
--- a/plane-src/apps/web/core/components/core/image-picker-popover.tsx
|
|
+++ b/plane-src/apps/web/core/components/core/image-picker-popover.tsx
|
|
@@ -12,6 +12,7 @@ import type { Control } from "react-hook-form";
|
|
import { Controller } from "react-hook-form";
|
|
import useSWR from "swr";
|
|
import { Popover } from "@headlessui/react";
|
|
+import { Check, UploadCloud } from "lucide-react";
|
|
// plane imports
|
|
import { ACCEPTED_COVER_IMAGE_MIME_TYPES_FOR_REACT_DROPZONE, MAX_FILE_SIZE } from "@plane/constants";
|
|
import { useOutsideClickDetector } from "@plane/hooks";
|
|
@@ -113,6 +114,7 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|
);
|
|
|
|
const imagePickerRef = useRef<HTMLDivElement>(null);
|
|
+ const selectedCoverImageUrl = value ? getCoverImageDisplayURL(value, null) : null;
|
|
|
|
const onDrop = useCallback((acceptedFiles: File[]) => {
|
|
setImage(acceptedFiles[0]);
|
|
@@ -215,17 +217,17 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|
|
|
{isOpen && (
|
|
<Popover.Panel
|
|
- className="nodedc-glass-modal nodedc-glass-popup-surface absolute right-0 z-20 mt-3 overflow-hidden rounded-[1.75rem]"
|
|
+ className="nodedc-glass-modal nodedc-glass-popup-surface absolute right-0 z-20 mt-3 overflow-hidden rounded-[1.9rem]"
|
|
static
|
|
>
|
|
<div
|
|
ref={imagePickerRef}
|
|
- className="flex h-[32rem] w-[21rem] flex-col overflow-hidden rounded-[1.75rem] md:h-[38rem] md:w-[38rem]"
|
|
+ className="nodedc-cover-picker flex h-[33rem] w-[21.5rem] flex-col overflow-hidden rounded-[1.9rem] md:h-[39rem] md:w-[42rem]"
|
|
>
|
|
<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">
|
|
+ <Tabs.List className="nodedc-cover-picker-tabs">
|
|
{enabledTabs.map((tab) => (
|
|
- <Tabs.Trigger key={tab.key} value={tab.key} size="md" className="rounded-[0.875rem]">
|
|
+ <Tabs.Trigger key={tab.key} value={tab.key} size="md" className="nodedc-cover-picker-tab">
|
|
{tab.title}
|
|
</Tabs.Trigger>
|
|
))}
|
|
@@ -273,7 +275,7 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|
{unsplashImages.map((image) => (
|
|
<div
|
|
key={image.id}
|
|
- className="nodedc-modal-field relative col-span-2 aspect-video overflow-hidden rounded-[1rem] p-0 md:col-span-1"
|
|
+ className="nodedc-cover-picker-tile group relative col-span-2 aspect-video overflow-hidden rounded-[1.2rem] p-0 md:col-span-1"
|
|
onClick={() => {
|
|
setIsOpen(false);
|
|
onChange(image.urls.regular);
|
|
@@ -282,7 +284,7 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|
<img
|
|
src={image.urls.small}
|
|
alt={image.alt_description}
|
|
- className="absolute inset-0 h-full w-full cursor-pointer rounded-[1rem] object-cover transition-transform duration-200 hover:scale-[1.02]"
|
|
+ className="absolute inset-0 h-full w-full cursor-pointer rounded-[1.2rem] object-cover transition-transform duration-200 group-hover:scale-[1.02]"
|
|
/>
|
|
</div>
|
|
))}
|
|
@@ -308,17 +310,25 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|
<Tabs.Content value="images" className="h-full w-full space-y-4">
|
|
<div className="grid grid-cols-4 gap-3">
|
|
{Object.values(STATIC_COVER_IMAGES).map((imageUrl, index) => (
|
|
- <div
|
|
+ <button
|
|
key={imageUrl}
|
|
- className="nodedc-modal-field relative col-span-2 aspect-video overflow-hidden rounded-[1rem] p-0 md:col-span-1"
|
|
+ type="button"
|
|
+ className="nodedc-cover-picker-tile group relative col-span-2 aspect-video overflow-hidden rounded-[1.2rem] p-0 text-left md:col-span-1"
|
|
+ data-selected={selectedCoverImageUrl === imageUrl}
|
|
onClick={() => handleStaticImageSelect(imageUrl)}
|
|
>
|
|
<img
|
|
src={imageUrl}
|
|
alt={t("image_picker.cover_image_alt", { index: index + 1 })}
|
|
- className="absolute inset-0 h-full w-full cursor-pointer rounded-[1rem] object-cover transition-transform duration-200 hover:scale-[1.02]"
|
|
+ className="absolute inset-0 h-full w-full cursor-pointer rounded-[1.2rem] object-cover transition-transform duration-200 group-hover:scale-[1.02]"
|
|
/>
|
|
- </div>
|
|
+ <div className="absolute inset-0 rounded-[1.2rem] bg-black/0 transition-colors duration-200 group-hover:bg-black/8" />
|
|
+ {selectedCoverImageUrl === imageUrl && (
|
|
+ <div className="absolute top-3 right-3 grid h-8 w-8 place-items-center rounded-full bg-[rgb(var(--nodedc-accent-rgb))] text-[rgb(var(--nodedc-on-accent-rgb))] shadow-[0_10px_24px_rgba(0,0,0,0.28)]">
|
|
+ <Check className="h-4 w-4" strokeWidth={2.4} />
|
|
+ </div>
|
|
+ )}
|
|
+ </button>
|
|
))}
|
|
</div>
|
|
</Tabs.Content>
|
|
@@ -327,9 +337,9 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|
<div className="flex w-full flex-1 items-center gap-3">
|
|
<div
|
|
{...getRootProps()}
|
|
- className={`nodedc-modal-field relative grid h-full w-full cursor-pointer place-items-center overflow-hidden rounded-[1.35rem] p-6 text-center ${
|
|
+ className={`nodedc-cover-picker-upload 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/80 hover:bg-white/6"
|
|
+ ? "border-2 border-dashed border-white/10 hover:bg-white/6"
|
|
: ""
|
|
}`}
|
|
>
|
|
@@ -348,10 +358,16 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|
/>
|
|
</>
|
|
) : (
|
|
- <div>
|
|
- <span className="mt-2 block text-13 font-medium text-secondary">
|
|
+ <div className="flex max-w-[18rem] flex-col items-center gap-3">
|
|
+ <div className="grid h-12 w-12 place-items-center rounded-full bg-white/6 text-secondary">
|
|
+ <UploadCloud className="h-5 w-5" />
|
|
+ </div>
|
|
+ <span className="block text-13 font-medium text-secondary">
|
|
{isDragActive ? t("image_picker.drop_here_to_upload") : t("image_picker.drag_and_drop_here")}
|
|
</span>
|
|
+ <span className="text-12 text-tertiary">
|
|
+ {t("image_picker.supported_formats")}
|
|
+ </span>
|
|
</div>
|
|
)}
|
|
|
|
@@ -368,7 +384,7 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|
|
|
<p className="text-13 text-secondary">{t("image_picker.supported_formats")}</p>
|
|
|
|
- <div className="mt-auto flex items-start justify-end gap-3 border-t border-subtle/70 pt-4">
|
|
+ <div className="nodedc-cover-picker-footer mt-auto flex items-start justify-end gap-3 border-t border-subtle/70 pt-4">
|
|
<Button
|
|
variant="secondary"
|
|
onClick={() => {
|