fix: ui improvements (#327)

* fix: kanban board header scroll fix

* style: enable scrollbar style added

* fix: emoji picker overflow

* fix: delete project modal text overflow

* fix: cycle card ellipsis

* fix: tooltip position updated and custom class added

* fix: assignees tooltip overflow

* fix: module card

* fix: my issue page  tooltip and responsive title  added

* fix: home page tooltip and responsiveness
This commit is contained in:
Anmol Singh Bhatia 2023-02-23 16:46:52 +05:30 committed by GitHub
parent 6a10faca68
commit 4caa4e33b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 168 additions and 84 deletions

View File

@ -72,7 +72,7 @@ export const SingleBoard: React.FC<Props> = ({
return (
<div className={`h-full flex-shrink-0 rounded ${!isCollapsed ? "" : "w-80 border bg-gray-50"}`}>
<div className={`${!isCollapsed ? "" : "flex h-full flex-col space-y-3 overflow-y-auto"}`}>
<div className={`${!isCollapsed ? "" : "flex h-full flex-col space-y-3"}`}>
<BoardHeader
addIssueToState={addIssueToState}
bgColor={bgColor}
@ -86,7 +86,7 @@ export const SingleBoard: React.FC<Props> = ({
<StrictModeDroppable key={groupTitle} droppableId={groupTitle}>
{(provided, snapshot) => (
<div
className={`relative mt-3 h-full px-3 pb-3 ${
className={`relative mt-3 h-full px-3 pb-3 overflow-y-auto ${
snapshot.isDraggingOver ? "bg-indigo-50 bg-opacity-50" : ""
} ${!isCollapsed ? "hidden" : "block"}`}
ref={provided.innerRef}

View File

@ -87,7 +87,7 @@ export const SingleCycleCard: React.FC<TSingleStatProps> = (props) => {
<div className="rounded-md border bg-white p-3">
<div className="grid grid-cols-9 gap-2 divide-x">
<div className="col-span-3 flex flex-col space-y-3">
<div className="flex items-center justify-between gap-2">
<div className="flex items-start justify-between gap-2">
<Link href={`/${workspaceSlug}/projects/${projectId as string}/cycles/${cycle.id}`}>
<a>
<h2 className="font-medium w-full max-w-[175px] lg:max-w-[225px] xl:max-w-[300px] text-ellipsis overflow-hidden">

View File

@ -59,7 +59,7 @@ const EmojiIconPicker: React.FC<Props> = ({ label, value, onChange }) => {
leaveTo="transform opacity-0 scale-95"
>
<Popover.Panel className="absolute z-10 mt-2 w-80 rounded-md bg-white shadow-lg">
<div className="h-80 w-80 overflow-auto rounded border bg-white p-2 shadow-2xl">
<div className="h-72 w-80 overflow-auto rounded border bg-white p-2 shadow-2xl">
<Tab.Group as="div" className="flex h-full w-full flex-col">
<Tab.List className="flex-0 -mx-2 flex justify-around gap-1 rounded border-b p-1">
{tabOptions.map((tab) => (

View File

@ -15,7 +15,7 @@ import {
} from "components/issues/view-select";
// ui
import { AssigneesList } from "components/ui/avatar";
import { CustomMenu } from "components/ui";
import { CustomMenu, Tooltip } from "components/ui";
// types
import { IIssue, Properties } from "types";
// fetch-keys
@ -78,13 +78,20 @@ export const MyIssuesListItem: React.FC<Props> = ({
<Link href={`/${workspaceSlug}/projects/${issue?.project_detail?.id}/issues/${issue.id}`}>
<a className="group relative flex items-center gap-2">
{properties?.key && (
<span className="flex-shrink-0 text-xs text-gray-500">
{issue.project_detail?.identifier}-{issue.sequence_id}
</span>
<Tooltip
tooltipHeading="ID"
tooltipContent={`${issue.project_detail?.identifier}-${issue.sequence_id}`}
>
<span className="flex-shrink-0 text-xs text-gray-500">
{issue.project_detail?.identifier}-{issue.sequence_id}
</span>
</Tooltip>
)}
<span className="w-[275px] md:w-[450px] lg:w-[600px] text-ellipsis overflow-hidden whitespace-nowrap">
{issue.name}
</span>
<Tooltip tooltipHeading="Title" tooltipContent={issue.name}>
<span className="w-auto max-w-lg text-ellipsis overflow-hidden whitespace-nowrap">
{issue.name}
</span>
</Tooltip>
</a>
</Link>
</div>
@ -134,9 +141,23 @@ export const MyIssuesListItem: React.FC<Props> = ({
</div>
)}
{properties.assignee && (
<div className="flex items-center gap-1">
<AssigneesList userIds={issue.assignees ?? []} />
</div>
<Tooltip
position="top-right"
tooltipHeading="Assignees"
tooltipContent={
issue.assignee_details.length > 0
? issue.assignee_details
.map((assignee) =>
assignee?.first_name !== "" ? assignee?.first_name : assignee?.email
)
.join(", ")
: "No Assignee"
}
>
<div className="flex items-center gap-1">
<AssigneesList userIds={issue.assignees ?? []} />
</div>
</Tooltip>
)}
<CustomMenu width="auto" ellipsis>
<CustomMenu.MenuItem onClick={handleDeleteIssue}>Delete permanently</CustomMenu.MenuItem>

View File

@ -57,6 +57,7 @@ export const ViewAssigneeSelect: React.FC<Props> = ({
<div>
<Listbox.Button>
<Tooltip
position="top-right"
tooltipHeading="Assignees"
tooltipContent={
issue.assignee_details.length > 0

View File

@ -2,12 +2,14 @@ import React, { useState } from "react";
import Link from "next/link";
import { useRouter } from "next/router";
import Image from "next/image";
// components
import { DeleteModuleModal } from "components/modules";
// ui
import { AssigneesList, Avatar, CustomMenu } from "components/ui";
// icons
import User from "public/user.png";
import { CalendarDaysIcon } from "@heroicons/react/24/outline";
// helpers
import { renderShortNumericDateFormat } from "helpers/date-time.helper";
@ -67,24 +69,52 @@ export const SingleModuleCard: React.FC<Props> = ({ module, handleEditModule })
</CustomMenu>
</div>
<Link href={`/${workspaceSlug}/projects/${module.project}/modules/${module.id}`}>
<a className="flex flex-col justify-between h-full cursor-pointer rounded-md border bg-white p-3 ">
<span className="w-3/4 text-ellipsis overflow-hidden">{module.name}</span>
<a className="flex flex-col justify-between h-full cursor-default rounded-md border bg-white p-3 ">
<span className="w-3/4 text-ellipsis cursor-pointer overflow-hidden">
{module.name}
</span>
<div className="mt-4 grid grid-cols-2 gap-2 text-xs md:grid-cols-4">
<div className="space-y-2">
<div className="space-y-2 ">
<h6 className="text-gray-500">LEAD</h6>
<div>
<Avatar user={module.lead_detail} />
{module.lead_detail ? (
<Avatar user={module.lead_detail} />
) : (
<div className="flex items-center gap-1">
<Image
src={User}
height="16px"
width="16px"
className="rounded-full"
alt="N/A"
/>
<span>N/A</span>
</div>
)}
</div>
</div>
<div className="space-y-2">
<h6 className="text-gray-500">MEMBERS</h6>
<div className="flex items-center gap-1 text-xs">
<AssigneesList users={module.members_detail} />
<div className="flex items-center gap-1 text-xs">
{module.members_detail && module.members_detail.length > 0 ? (
<AssigneesList users={module.members_detail} length={3} />
) : (
<div className="flex items-center gap-1">
<Image
src={User}
height="16px"
width="16px"
className="rounded-full"
alt="N/A"
/>
<span>N/A</span>
</div>
)}
</div>
</div>
<div className="space-y-2">
<h6 className="text-gray-500">END DATE</h6>
<div className="flex w-min cursor-pointer items-center gap-1 whitespace-nowrap rounded border px-1.5 py-0.5 text-xs shadow-sm">
<div className="flex w-min items-center gap-1 whitespace-nowrap rounded border px-1.5 py-0.5 text-xs shadow-sm">
<CalendarDaysIcon className="h-3 w-3" />
{module.target_date ? renderShortNumericDateFormat(module?.target_date) : "N/A"}
</div>

View File

@ -122,12 +122,12 @@ const ConfirmProjectDeletion: React.FC<TConfirmProjectDeletionProps> = (props) =
aria-hidden="true"
/>
</div>
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full">
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-gray-900">
Delete Project
</Dialog.Title>
<div className="mt-2">
<p className="text-sm text-gray-500">
<p className="text-sm text-gray-500 break-all">
Are you sure you want to delete project - {`"`}
<span className="italic">{selectedProject?.name}</span>
{`"`} ? All of the data related to the project will be permanently
@ -136,7 +136,7 @@ const ConfirmProjectDeletion: React.FC<TConfirmProjectDeletionProps> = (props) =
</div>
<div className="my-3 h-0.5 bg-gray-200" />
<div className="mt-3">
<p className="text-sm">
<p className="text-sm break-all">
Enter the project name{" "}
<span className="font-semibold">{selectedProject?.name}</span> to
continue:

View File

@ -5,9 +5,25 @@ import { Tooltip2 } from "@blueprintjs/popover2";
type Props = {
tooltipHeading?: string;
tooltipContent: string;
position?: "top" | "right" | "bottom" | "left";
position?:
| "top"
| "right"
| "bottom"
| "left"
| "auto"
| "auto-end"
| "auto-start"
| "bottom-left"
| "bottom-right"
| "left-bottom"
| "left-top"
| "right-bottom"
| "right-top"
| "top-left"
| "top-right";
children: JSX.Element;
disabled?: boolean;
className?: string;
};
export const Tooltip: React.FC<Props> = ({
@ -16,11 +32,14 @@ export const Tooltip: React.FC<Props> = ({
position = "top",
children,
disabled = false,
className = "",
}) => (
<Tooltip2
disabled={disabled}
content={
<div className="flex flex-col justify-center items-start gap-1 max-w-[600px] text-xs rounded-md bg-white p-2 shadow-md capitalize text-left">
<div
className={`flex flex-col justify-center items-start gap-1 max-w-[600px] text-xs rounded-md bg-white p-2 shadow-md capitalize text-left ${className}`}
>
{tooltipHeading ? (
<>
<h5 className="font-medium">{tooltipHeading}</h5>

View File

@ -14,7 +14,7 @@ import useIssues from "hooks/use-issues";
// components
import { WorkspaceHomeCardsList, WorkspaceHomeGreetings } from "components/workspace";
// ui
import { Spinner } from "components/ui";
import { Spinner, Tooltip } from "components/ui";
// icons
import {
ArrowRightIcon,
@ -90,69 +90,78 @@ const WorkspacePage: NextPage = () => {
href={`/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`}
>
<a className="group relative flex items-center gap-2">
<span className="">{issue.name}</span>
<Tooltip
position="top-left"
tooltipHeading="Title"
tooltipContent={issue.name}
>
<span className="w-auto max-w-[225px] md:max-w-[175px] lg:max-w-xs xl:max-w-sm text-ellipsis overflow-hidden whitespace-nowrap">
{issue.name}
</span>
</Tooltip>
</a>
</Link>
</div>
<div className="flex flex-shrink-0 flex-wrap items-center gap-x-1 gap-y-2 text-xs">
<div
className={`cursor-pointer rounded px-2 py-1 capitalize shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 ${
issue.priority === "urgent"
? "bg-red-100 text-red-600"
: issue.priority === "high"
? "bg-orange-100 text-orange-500"
: issue.priority === "medium"
? "bg-yellow-100 text-yellow-500"
: issue.priority === "low"
? "bg-green-100 text-green-500"
: "bg-gray-100"
}`}
<Tooltip
tooltipHeading="Priority"
tooltipContent={issue.priority ?? "None"}
>
{getPriorityIcon(issue.priority)}
</div>
<div className="flex cursor-pointer items-center gap-1 rounded border px-2 py-1 text-xs shadow-sm duration-300 hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500">
<span
className="h-1.5 w-1.5 flex-shrink-0 rounded-full"
style={{
backgroundColor: issue.state_detail.color,
}}
/>
{addSpaceIfCamelCase(issue.state_detail.name)}
</div>
<div
className={`group group relative flex flex-shrink-0 cursor-pointer items-center gap-1 rounded border px-2 py-1 text-xs shadow-sm duration-300 hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 ${
issue.target_date === null
? ""
: issue.target_date < new Date().toISOString()
? "text-red-600"
: findHowManyDaysLeft(issue.target_date) <= 3 &&
"text-orange-400"
}`}
>
<CalendarDaysIcon className="h-4 w-4" />
{issue.target_date
? renderShortNumericDateFormat(issue.target_date)
: "N/A"}
<div className="absolute bottom-full right-0 z-10 mb-2 hidden whitespace-nowrap rounded-md bg-white p-2 shadow-md group-hover:block">
<h5 className="mb-1 font-medium text-gray-900">Target date</h5>
<div>
{renderShortNumericDateFormat(issue.target_date ?? "")}
</div>
<div>
{issue.target_date &&
(issue.target_date < new Date().toISOString()
? `Target date has passed by ${findHowManyDaysLeft(
issue.target_date
)} days`
: findHowManyDaysLeft(issue.target_date) <= 3
? `Target date is in ${findHowManyDaysLeft(
issue.target_date
)} days`
: "Target date")}
</div>
<div
className={`cursor-pointer rounded px-2 py-1 capitalize shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 ${
issue.priority === "urgent"
? "bg-red-100 text-red-600"
: issue.priority === "high"
? "bg-orange-100 text-orange-500"
: issue.priority === "medium"
? "bg-yellow-100 text-yellow-500"
: issue.priority === "low"
? "bg-green-100 text-green-500"
: "bg-gray-100"
}`}
>
{getPriorityIcon(issue.priority)}
</div>
</div>
</Tooltip>
<Tooltip
tooltipHeading="State"
tooltipContent={addSpaceIfCamelCase(issue.state_detail.name)}
>
<div className="flex cursor-pointer items-center gap-1 rounded border px-2 py-1 text-xs shadow-sm duration-300 hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500">
<span
className="h-1.5 w-1.5 flex-shrink-0 rounded-full"
style={{
backgroundColor: issue.state_detail.color,
}}
/>
<span>{addSpaceIfCamelCase(issue.state_detail.name)}</span>
</div>
</Tooltip>
<Tooltip
tooltipHeading="Due Date"
tooltipContent={
issue.target_date
? renderShortNumericDateFormat(issue.target_date)
: "N/A"
}
>
<div
className={`flex flex-shrink-0 cursor-pointer items-center gap-1 rounded border px-2 py-1 text-xs shadow-sm duration-300 hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 ${
issue.target_date === null
? ""
: issue.target_date < new Date().toISOString()
? "text-red-600"
: findHowManyDaysLeft(issue.target_date) <= 3 &&
"text-orange-400"
}`}
>
<CalendarDaysIcon className="h-4 w-4" />
{issue.target_date
? renderShortNumericDateFormat(issue.target_date)
: "N/A"}
</div>
</Tooltip>
</div>
</div>
))}

View File

@ -23,6 +23,10 @@
-webkit-font-smoothing: antialiased;
}
.scrollbar-enable::-webkit-scrollbar {
display: block ;
}
/* Scrollbar style */
::-webkit-scrollbar {
display: none;