style: peek overview

This commit is contained in:
Aaryan Khandelwal 2024-06-04 22:13:05 +05:30
parent 0aa02a603d
commit 899d49b1f0
3 changed files with 56 additions and 57 deletions

View File

@ -1,10 +1,9 @@
import React from "react"; import React from "react";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { MoveRight } from "lucide-react"; import { Link2, MoveRight } from "lucide-react";
import { Listbox, Transition } from "@headlessui/react"; import { Listbox, Transition } from "@headlessui/react";
// ui // ui
import { setToast, TOAST_TYPE } from "@plane/ui"; import { CenterPanelIcon, FullScreenPanelIcon, setToast, SidePanelIcon, TOAST_TYPE } from "@plane/ui";
import { Icon } from "@/components/ui";
// helpers // helpers
import { copyTextToClipboard } from "@/helpers/string.helper"; import { copyTextToClipboard } from "@/helpers/string.helper";
// hooks // hooks
@ -18,21 +17,21 @@ type Props = {
issueDetails: IIssue | undefined; issueDetails: IIssue | undefined;
}; };
const peekModes: { const PEEK_MODES: {
key: IPeekMode; key: IPeekMode;
icon: string; icon: any;
label: string; label: string;
}[] = [ }[] = [
{ key: "side", icon: "side_navigation", label: "Side Peek" }, { key: "side", icon: SidePanelIcon, label: "Side Peek" },
{ {
key: "modal", key: "modal",
icon: "dialogs", icon: CenterPanelIcon,
label: "Modal Peek", label: "Modal",
}, },
{ {
key: "full", key: "full",
icon: "nearby", icon: FullScreenPanelIcon,
label: "Full Screen Peek", label: "Full Screen",
}, },
]; ];
@ -47,20 +46,22 @@ export const PeekOverviewHeader: React.FC<Props> = observer((props) => {
copyTextToClipboard(urlToCopy).then(() => { copyTextToClipboard(urlToCopy).then(() => {
setToast({ setToast({
type: TOAST_TYPE.INFO, type: TOAST_TYPE.SUCCESS,
title: "Link copied!", title: "Link copied!",
message: "Issue link copied to clipboard", message: "Issue link copied to clipboard.",
}); });
}); });
}; };
const Icon = PEEK_MODES.find((m) => m.key === peekMode)?.icon ?? SidePanelIcon;
return ( return (
<> <>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
{peekMode === "side" && ( {peekMode === "side" && (
<button type="button" onClick={handleClose}> <button type="button" onClick={handleClose} className="text-custom-text-300 hover:text-custom-text-200">
<MoveRight className="h-4 w-4" strokeWidth={2} /> <MoveRight className="size-4" />
</button> </button>
)} )}
<Listbox <Listbox
@ -69,8 +70,10 @@ export const PeekOverviewHeader: React.FC<Props> = observer((props) => {
onChange={(val) => setPeekMode(val)} onChange={(val) => setPeekMode(val)}
className="relative flex-shrink-0 text-left" className="relative flex-shrink-0 text-left"
> >
<Listbox.Button className={`grid place-items-center ${peekMode === "full" ? "rotate-45" : ""}`}> <Listbox.Button
<Icon iconName={peekModes.find((m) => m.key === peekMode)?.icon ?? ""} className="text-[1rem]" /> className={`grid place-items-center text-custom-text-300 hover:text-custom-text-200 ${peekMode === "full" ? "rotate-45" : ""}`}
>
<Icon className="h-4 w-4 text-custom-text-300 hover:text-custom-text-200" />
</Listbox.Button> </Listbox.Button>
<Transition <Transition
@ -84,7 +87,7 @@ export const PeekOverviewHeader: React.FC<Props> = observer((props) => {
> >
<Listbox.Options className="absolute left-0 z-10 mt-1 min-w-[8rem] origin-top-left overflow-y-auto whitespace-nowrap rounded-md border border-custom-border-300 bg-custom-background-90 text-xs shadow-lg focus:outline-none"> <Listbox.Options className="absolute left-0 z-10 mt-1 min-w-[8rem] origin-top-left overflow-y-auto whitespace-nowrap rounded-md border border-custom-border-300 bg-custom-background-90 text-xs shadow-lg focus:outline-none">
<div className="space-y-1 p-2"> <div className="space-y-1 p-2">
{peekModes.map((mode) => ( {PEEK_MODES.map((mode) => (
<Listbox.Option <Listbox.Option
key={mode.key} key={mode.key}
value={mode.key} value={mode.key}
@ -117,8 +120,13 @@ export const PeekOverviewHeader: React.FC<Props> = observer((props) => {
</div> </div>
{isClipboardWriteAllowed && (peekMode === "side" || peekMode === "modal") && ( {isClipboardWriteAllowed && (peekMode === "side" || peekMode === "modal") && (
<div className="flex flex-shrink-0 items-center gap-2"> <div className="flex flex-shrink-0 items-center gap-2">
<button type="button" onClick={handleCopyLink} className="-rotate-45 focus:outline-none" tabIndex={1}> <button
<Icon iconName="link" className="text-[1rem]" /> type="button"
onClick={handleCopyLink}
className="focus:outline-none text-custom-text-300 hover:text-custom-text-200"
tabIndex={1}
>
<Link2 className="h-4 w-4 -rotate-45" />
</button> </button>
</div> </div>
)} )}

View File

@ -16,10 +16,10 @@ export const PeekOverviewIssueDetails: React.FC<Props> = (props) => {
return ( return (
<div className="space-y-2"> <div className="space-y-2">
<h6 className="font-medium text-custom-text-200"> <h6 className="text-base font-medium text-custom-text-400">
{issueDetails.project_detail.identifier}-{issueDetails.sequence_id} {issueDetails.project_detail?.identifier}-{issueDetails?.sequence_id}
</h6> </h6>
<h4 className="break-words text-2xl font-semibold">{issueDetails.name}</h4> <h4 className="break-words text-2xl font-medium">{issueDetails.name}</h4>
{description !== "" && description !== "<p></p>" && ( {description !== "" && description !== "<p></p>" && (
<RichTextReadOnlyEditor <RichTextReadOnlyEditor
initialValue={ initialValue={

View File

@ -1,10 +1,10 @@
import { CalendarCheck2 } from "lucide-react"; import { CalendarCheck2, Signal } from "lucide-react";
// ui // ui
import { StateGroupIcon, TOAST_TYPE, setToast } from "@plane/ui"; import { DoubleCircleIcon, StateGroupIcon, TOAST_TYPE, setToast } from "@plane/ui";
// components // components
import { Icon } from "@/components/ui"; import { Icon } from "@/components/ui";
// constants // constants
import { issueGroupFilter, issuePriorityFilter } from "@/constants/issue"; import { issuePriorityFilter } from "@/constants/issue";
// helpers // helpers
import { cn } from "@/helpers/common.helper"; import { cn } from "@/helpers/common.helper";
import { renderFormattedDate } from "@/helpers/date-time.helper"; import { renderFormattedDate } from "@/helpers/date-time.helper";
@ -20,7 +20,6 @@ type Props = {
export const PeekOverviewIssueProperties: React.FC<Props> = ({ issueDetails, mode }) => { export const PeekOverviewIssueProperties: React.FC<Props> = ({ issueDetails, mode }) => {
const state = issueDetails.state_detail; const state = issueDetails.state_detail;
const stateGroup = issueGroupFilter(state.group);
const priority = issueDetails.priority ? issuePriorityFilter(issueDetails.priority) : null; const priority = issueDetails.priority ? issuePriorityFilter(issueDetails.priority) : null;
@ -50,28 +49,22 @@ export const PeekOverviewIssueProperties: React.FC<Props> = ({ issueDetails, mod
</div> </div>
</div> </div>
)} )}
<div className={`space-y-4 ${mode === "full" ? "pt-3" : ""}`}> <div className={`space-y-2 ${mode === "full" ? "pt-3" : ""}`}>
<div className="flex items-center gap-2 text-sm"> <div className="flex items-center gap-3 h-8">
<div className="flex w-1/4 flex-shrink-0 items-center gap-2 font-medium"> <div className="flex items-center gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
<Icon iconName="radio_button_checked" className="flex-shrink-0 !text-base" /> <DoubleCircleIcon className="size-4 flex-shrink-0" />
<span className="flex-grow truncate">State</span> <span>State</span>
</div> </div>
<div className="w-3/4"> <div className="w-3/4 flex items-center gap-1.5 py-0.5 text-sm">
{stateGroup && ( <StateGroupIcon stateGroup={state.group} color={state.color} />
<div className="inline-flex rounded bg-custom-background-80 px-2.5 py-0.5 text-sm"> {addSpaceIfCamelCase(state?.name ?? "")}
<div className="flex items-center gap-1.5 text-left text-custom-text-100">
<StateGroupIcon stateGroup={state.group} color={state.color} />
{addSpaceIfCamelCase(state?.name ?? "")}
</div>
</div>
)}
</div> </div>
</div> </div>
<div className="flex items-center gap-2 text-sm"> <div className="flex items-center gap-3 h-8">
<div className="flex w-1/4 flex-shrink-0 items-center gap-2 font-medium"> <div className="flex items-center gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
<Icon iconName="signal_cellular_alt" className="flex-shrink-0 !text-base" /> <Signal className="size-4 flex-shrink-0" />
<span className="flex-grow truncate">Priority</span> <span>Priority</span>
</div> </div>
<div className="w-3/4"> <div className="w-3/4">
<div <div
@ -96,23 +89,21 @@ export const PeekOverviewIssueProperties: React.FC<Props> = ({ issueDetails, mod
</div> </div>
</div> </div>
</div> </div>
<div className="flex items-center gap-2 text-sm">
<div className="flex w-1/4 flex-shrink-0 items-center gap-2 font-medium"> <div className="flex items-center gap-3 h-8">
<Icon iconName="calendar_today" className="flex-shrink-0 !text-base" /> <div className="flex items-center gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
<span className="flex-grow truncate">Due date</span> <CalendarCheck2 className="size-4 flex-shrink-0" />
<span>Due date</span>
</div> </div>
<div> <div>
{issueDetails.target_date ? ( {issueDetails.target_date ? (
<div <div
className={cn( className={cn("flex items-center gap-1.5 rounded py-0.5 text-xs text-custom-text-100", {
"flex h-6 items-center gap-1 rounded border border-custom-border-100 bg-custom-background-80 px-2.5 py-1 text-xs text-custom-text-100", "text-red-500": shouldHighlightIssueDueDate(
{ issueDetails.target_date,
"text-red-500": shouldHighlightIssueDueDate( issueDetails.state_detail.group
issueDetails.target_date, ),
issueDetails.state_detail.group })}
),
}
)}
> >
<CalendarCheck2 className="size-3" /> <CalendarCheck2 className="size-3" />
{renderFormattedDate(issueDetails.target_date)} {renderFormattedDate(issueDetails.target_date)}