mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
style: peek overview
This commit is contained in:
parent
0aa02a603d
commit
899d49b1f0
@ -1,10 +1,9 @@
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { MoveRight } from "lucide-react";
|
||||
import { Link2, MoveRight } from "lucide-react";
|
||||
import { Listbox, Transition } from "@headlessui/react";
|
||||
// ui
|
||||
import { setToast, TOAST_TYPE } from "@plane/ui";
|
||||
import { Icon } from "@/components/ui";
|
||||
import { CenterPanelIcon, FullScreenPanelIcon, setToast, SidePanelIcon, TOAST_TYPE } from "@plane/ui";
|
||||
// helpers
|
||||
import { copyTextToClipboard } from "@/helpers/string.helper";
|
||||
// hooks
|
||||
@ -18,21 +17,21 @@ type Props = {
|
||||
issueDetails: IIssue | undefined;
|
||||
};
|
||||
|
||||
const peekModes: {
|
||||
const PEEK_MODES: {
|
||||
key: IPeekMode;
|
||||
icon: string;
|
||||
icon: any;
|
||||
label: string;
|
||||
}[] = [
|
||||
{ key: "side", icon: "side_navigation", label: "Side Peek" },
|
||||
{ key: "side", icon: SidePanelIcon, label: "Side Peek" },
|
||||
{
|
||||
key: "modal",
|
||||
icon: "dialogs",
|
||||
label: "Modal Peek",
|
||||
icon: CenterPanelIcon,
|
||||
label: "Modal",
|
||||
},
|
||||
{
|
||||
key: "full",
|
||||
icon: "nearby",
|
||||
label: "Full Screen Peek",
|
||||
icon: FullScreenPanelIcon,
|
||||
label: "Full Screen",
|
||||
},
|
||||
];
|
||||
|
||||
@ -47,20 +46,22 @@ export const PeekOverviewHeader: React.FC<Props> = observer((props) => {
|
||||
|
||||
copyTextToClipboard(urlToCopy).then(() => {
|
||||
setToast({
|
||||
type: TOAST_TYPE.INFO,
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
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 (
|
||||
<>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
{peekMode === "side" && (
|
||||
<button type="button" onClick={handleClose}>
|
||||
<MoveRight className="h-4 w-4" strokeWidth={2} />
|
||||
<button type="button" onClick={handleClose} className="text-custom-text-300 hover:text-custom-text-200">
|
||||
<MoveRight className="size-4" />
|
||||
</button>
|
||||
)}
|
||||
<Listbox
|
||||
@ -69,8 +70,10 @@ export const PeekOverviewHeader: React.FC<Props> = observer((props) => {
|
||||
onChange={(val) => setPeekMode(val)}
|
||||
className="relative flex-shrink-0 text-left"
|
||||
>
|
||||
<Listbox.Button className={`grid place-items-center ${peekMode === "full" ? "rotate-45" : ""}`}>
|
||||
<Icon iconName={peekModes.find((m) => m.key === peekMode)?.icon ?? ""} className="text-[1rem]" />
|
||||
<Listbox.Button
|
||||
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>
|
||||
|
||||
<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">
|
||||
<div className="space-y-1 p-2">
|
||||
{peekModes.map((mode) => (
|
||||
{PEEK_MODES.map((mode) => (
|
||||
<Listbox.Option
|
||||
key={mode.key}
|
||||
value={mode.key}
|
||||
@ -117,8 +120,13 @@ export const PeekOverviewHeader: React.FC<Props> = observer((props) => {
|
||||
</div>
|
||||
{isClipboardWriteAllowed && (peekMode === "side" || peekMode === "modal") && (
|
||||
<div className="flex flex-shrink-0 items-center gap-2">
|
||||
<button type="button" onClick={handleCopyLink} className="-rotate-45 focus:outline-none" tabIndex={1}>
|
||||
<Icon iconName="link" className="text-[1rem]" />
|
||||
<button
|
||||
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>
|
||||
</div>
|
||||
)}
|
||||
|
@ -16,10 +16,10 @@ export const PeekOverviewIssueDetails: React.FC<Props> = (props) => {
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<h6 className="font-medium text-custom-text-200">
|
||||
{issueDetails.project_detail.identifier}-{issueDetails.sequence_id}
|
||||
<h6 className="text-base font-medium text-custom-text-400">
|
||||
{issueDetails.project_detail?.identifier}-{issueDetails?.sequence_id}
|
||||
</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>" && (
|
||||
<RichTextReadOnlyEditor
|
||||
initialValue={
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { CalendarCheck2 } from "lucide-react";
|
||||
import { CalendarCheck2, Signal } from "lucide-react";
|
||||
// ui
|
||||
import { StateGroupIcon, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
import { DoubleCircleIcon, StateGroupIcon, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { Icon } from "@/components/ui";
|
||||
// constants
|
||||
import { issueGroupFilter, issuePriorityFilter } from "@/constants/issue";
|
||||
import { issuePriorityFilter } from "@/constants/issue";
|
||||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
||||
@ -20,7 +20,6 @@ type Props = {
|
||||
|
||||
export const PeekOverviewIssueProperties: React.FC<Props> = ({ issueDetails, mode }) => {
|
||||
const state = issueDetails.state_detail;
|
||||
const stateGroup = issueGroupFilter(state.group);
|
||||
|
||||
const priority = issueDetails.priority ? issuePriorityFilter(issueDetails.priority) : null;
|
||||
|
||||
@ -50,28 +49,22 @@ export const PeekOverviewIssueProperties: React.FC<Props> = ({ issueDetails, mod
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className={`space-y-4 ${mode === "full" ? "pt-3" : ""}`}>
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<div className="flex w-1/4 flex-shrink-0 items-center gap-2 font-medium">
|
||||
<Icon iconName="radio_button_checked" className="flex-shrink-0 !text-base" />
|
||||
<span className="flex-grow truncate">State</span>
|
||||
<div className={`space-y-2 ${mode === "full" ? "pt-3" : ""}`}>
|
||||
<div className="flex items-center gap-3 h-8">
|
||||
<div className="flex items-center gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<DoubleCircleIcon className="size-4 flex-shrink-0" />
|
||||
<span>State</span>
|
||||
</div>
|
||||
<div className="w-3/4">
|
||||
{stateGroup && (
|
||||
<div className="inline-flex rounded bg-custom-background-80 px-2.5 py-0.5 text-sm">
|
||||
<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 className="w-3/4 flex items-center gap-1.5 py-0.5 text-sm">
|
||||
<StateGroupIcon stateGroup={state.group} color={state.color} />
|
||||
{addSpaceIfCamelCase(state?.name ?? "")}
|
||||
</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">
|
||||
<Icon iconName="signal_cellular_alt" className="flex-shrink-0 !text-base" />
|
||||
<span className="flex-grow truncate">Priority</span>
|
||||
<div className="flex items-center gap-3 h-8">
|
||||
<div className="flex items-center gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<Signal className="size-4 flex-shrink-0" />
|
||||
<span>Priority</span>
|
||||
</div>
|
||||
<div className="w-3/4">
|
||||
<div
|
||||
@ -96,23 +89,21 @@ export const PeekOverviewIssueProperties: React.FC<Props> = ({ issueDetails, mod
|
||||
</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">
|
||||
<Icon iconName="calendar_today" className="flex-shrink-0 !text-base" />
|
||||
<span className="flex-grow truncate">Due date</span>
|
||||
|
||||
<div className="flex items-center gap-3 h-8">
|
||||
<div className="flex items-center gap-1 w-1/4 flex-shrink-0 text-sm text-custom-text-300">
|
||||
<CalendarCheck2 className="size-4 flex-shrink-0" />
|
||||
<span>Due date</span>
|
||||
</div>
|
||||
<div>
|
||||
{issueDetails.target_date ? (
|
||||
<div
|
||||
className={cn(
|
||||
"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,
|
||||
issueDetails.state_detail.group
|
||||
),
|
||||
}
|
||||
)}
|
||||
className={cn("flex items-center gap-1.5 rounded py-0.5 text-xs text-custom-text-100", {
|
||||
"text-red-500": shouldHighlightIssueDueDate(
|
||||
issueDetails.target_date,
|
||||
issueDetails.state_detail.group
|
||||
),
|
||||
})}
|
||||
>
|
||||
<CalendarCheck2 className="size-3" />
|
||||
{renderFormattedDate(issueDetails.target_date)}
|
||||
|
Loading…
Reference in New Issue
Block a user