Skip to content

Commit

Permalink
Merge pull request #356 from makeplane/style/kanban_board
Browse files Browse the repository at this point in the history
style: kanban board
  • Loading branch information
aaryan610 committed Mar 1, 2023
2 parents 2c0b27d + 8589ce7 commit 99cf2d4
Show file tree
Hide file tree
Showing 15 changed files with 479 additions and 117 deletions.
8 changes: 7 additions & 1 deletion apps/app/components/core/board-view/all-boards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@ export const AllBoards: React.FC<Props> = ({
<div className="h-[calc(100vh-157px)] lg:h-[calc(100vh-115px)] w-full">
<div className="h-full w-full overflow-hidden">
<div className="h-full w-full">
<div className="flex h-full gap-x-4 overflow-x-auto overflow-y-hidden">
<div className="flex h-full gap-x-9 overflow-x-auto overflow-y-hidden">
{Object.keys(groupedByIssues).map((singleGroup, index) => {
const currentState =
selectedGroup === "state_detail.name"
? states?.find((s) => s.name === singleGroup)
: null;

const stateId =
selectedGroup === "state_detail.name"
? states?.find((s) => s.name === singleGroup)?.id ?? null
Expand All @@ -56,6 +61,7 @@ export const AllBoards: React.FC<Props> = ({
<SingleBoard
key={index}
type={type}
currentState={currentState}
bgColor={bgColor}
groupTitle={singleGroup}
groupedByIssues={groupedByIssues}
Expand Down
33 changes: 14 additions & 19 deletions apps/app/components/core/board-view/board-header.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
import React from "react";

// react-beautiful-dnd
import { DraggableProvided } from "react-beautiful-dnd";
// icons
import {
ArrowsPointingInIcon,
ArrowsPointingOutIcon,
EllipsisHorizontalIcon,
PlusIcon,
} from "@heroicons/react/24/outline";
import { ArrowsPointingInIcon, ArrowsPointingOutIcon, PlusIcon } from "@heroicons/react/24/outline";
// helpers
import { addSpaceIfCamelCase } from "helpers/string.helper";
// types
import { IIssue, IProjectMember, NestedKeyOf } from "types";
import { IIssue, IProjectMember, IState, NestedKeyOf } from "types";
import { getStateGroupIcon } from "components/icons";
type Props = {
groupedByIssues: {
[key: string]: IIssue[];
};
currentState?: IState | null;
selectedGroup: NestedKeyOf<IIssue> | null;
groupTitle: string;
bgColor?: string;
Expand All @@ -28,6 +23,7 @@ type Props = {

export const BoardHeader: React.FC<Props> = ({
groupedByIssues,
currentState,
selectedGroup,
groupTitle,
bgColor,
Expand All @@ -54,22 +50,19 @@ export const BoardHeader: React.FC<Props> = ({

return (
<div
className={`flex justify-between p-3 pb-0 ${
className={`flex justify-between px-1 ${
!isCollapsed ? "flex-col rounded-md border bg-gray-50" : ""
}`}
>
<div className={`flex items-center ${!isCollapsed ? "flex-col gap-2" : "gap-1"}`}>
<div
className={`flex cursor-pointer items-center gap-x-1 rounded-md bg-slate-900 px-2 ${
className={`flex cursor-pointer items-center gap-x-3.5 ${
!isCollapsed ? "mb-2 flex-col gap-y-2 py-2" : ""
}`}
style={{
border: `2px solid ${bgColor}`,
backgroundColor: `${bgColor}20`,
}}
>
{currentState && getStateGroupIcon(currentState.group, "20", "20", bgColor)}
<h2
className={`text-[0.9rem] font-medium capitalize`}
className={`text-xl font-semibold capitalize`}
style={{
writingMode: !isCollapsed ? "vertical-rl" : "horizontal-tb",
}}
Expand All @@ -80,14 +73,16 @@ export const BoardHeader: React.FC<Props> = ({
? assignees
: addSpaceIfCamelCase(groupTitle)}
</h2>
<span className="ml-0.5 text-sm text-gray-500">{groupedByIssues[groupTitle].length}</span>
<span className="ml-0.5 text-sm bg-gray-100 py-1 px-3 rounded-full">
{groupedByIssues[groupTitle].length}
</span>
</div>
</div>

<div className={`flex items-center ${!isCollapsed ? "flex-col pb-2" : ""}`}>
<button
type="button"
className="grid h-7 w-7 place-items-center rounded p-1 outline-none duration-300 hover:bg-gray-200"
className="grid h-7 w-7 place-items-center rounded p-1 text-gray-700 outline-none duration-300 hover:bg-gray-100"
onClick={() => {
setIsCollapsed((prevData) => !prevData);
}}
Expand All @@ -100,7 +95,7 @@ export const BoardHeader: React.FC<Props> = ({
</button>
<button
type="button"
className="grid h-7 w-7 place-items-center rounded p-1 outline-none duration-300 hover:bg-gray-200"
className="grid h-7 w-7 place-items-center rounded p-1 text-gray-700 outline-none duration-300 hover:bg-gray-100"
onClick={addIssueToState}
>
<PlusIcon className="h-4 w-4" />
Expand Down
33 changes: 20 additions & 13 deletions apps/app/components/core/board-view/single-board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ import { BoardHeader, SingleBoardIssue } from "components/core";
import { CustomMenu } from "components/ui";
// icons
import { PlusIcon } from "@heroicons/react/24/outline";
// helpers
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
// types
import { IIssue, IProjectMember, NestedKeyOf, UserAuth } from "types";
import { IIssue, IProjectMember, IState, NestedKeyOf, UserAuth } from "types";

type Props = {
type?: "issue" | "cycle" | "module";
currentState?: IState | null;
bgColor?: string;
groupTitle: string;
groupedByIssues: {
Expand All @@ -37,6 +40,7 @@ type Props = {

export const SingleBoard: React.FC<Props> = ({
type,
currentState,
bgColor,
groupTitle,
groupedByIssues,
Expand Down Expand Up @@ -71,10 +75,11 @@ export const SingleBoard: React.FC<Props> = ({
const isNotAllowed = userAuth.isGuest || userAuth.isViewer;

return (
<div className={`h-full flex-shrink-0 rounded ${!isCollapsed ? "" : "w-80 border bg-gray-50"}`}>
<div className={`h-full flex-shrink-0 rounded ${!isCollapsed ? "" : "w-96 bg-gray-50"}`}>
<div className={`${!isCollapsed ? "" : "flex h-full flex-col space-y-3"}`}>
<BoardHeader
addIssueToState={addIssueToState}
currentState={currentState}
bgColor={bgColor}
selectedGroup={selectedGroup}
groupTitle={groupTitle}
Expand All @@ -86,7 +91,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 overflow-y-auto ${
className={`relative h-full p-1 overflow-y-auto ${
snapshot.isDraggingOver ? "bg-indigo-50 bg-opacity-50" : ""
} ${!isCollapsed ? "hidden" : "block"}`}
ref={provided.innerRef}
Expand All @@ -104,7 +109,7 @@ export const SingleBoard: React.FC<Props> = ({
snapshot.isDraggingOver ? "block" : "hidden"
} top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2 text-xs whitespace-nowrap bg-white p-2 rounded pointer-events-none z-[99999999]`}
>
This board is ordered by {orderBy}
This board is ordered by {replaceUnderscoreIfSnakeCase(orderBy ?? "")}
</div>
</>
)}
Expand Down Expand Up @@ -148,21 +153,23 @@ export const SingleBoard: React.FC<Props> = ({
{type === "issue" ? (
<button
type="button"
className="flex items-center rounded p-2 text-xs font-medium outline-none duration-300 hover:bg-gray-100"
className="flex items-center gap-2 text-theme font-medium outline-none"
onClick={addIssueToState}
>
<PlusIcon className="mr-1 h-3 w-3" />
Create
<PlusIcon className="h-4 w-4" />
Add Issue
</button>
) : (
<CustomMenu
label={
<span className="flex items-center gap-1">
<PlusIcon className="h-3 w-3" />
Add issue
</span>
customButton={
<button
type="button"
className="flex items-center gap-2 text-theme font-medium outline-none"
>
<PlusIcon className="h-4 w-4" />
Add Issue
</button>
}
className="mt-1"
optionsPosition="left"
noBorder
>
Expand Down
12 changes: 6 additions & 6 deletions apps/app/components/core/board-view/single-issue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,15 @@ export const SingleBoardIssue: React.FC<Props> = ({

return (
<div
className={`rounded border bg-white shadow-sm mb-3 ${
snapshot.isDragging ? "border-theme bg-indigo-50 shadow-lg" : ""
className={`rounded bg-white shadow mb-3 ${
snapshot.isDragging ? "border-2 border-theme shadow-lg" : ""
}`}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={getStyle(provided.draggableProps.style, snapshot)}
>
<div className="group/card relative select-none p-2">
<div className="group/card relative select-none p-4">
{!isNotAllowed && (
<div className="absolute top-1.5 right-1.5 z-10 opacity-0 group-hover/card:opacity-100">
{type && !isNotAllowed && (
Expand All @@ -214,19 +214,19 @@ export const SingleBoardIssue: React.FC<Props> = ({
<Link href={`/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`}>
<a>
{properties.key && (
<div className="mb-2 text-xs font-medium text-gray-500">
<div className="mb-2.5 text-xs font-medium text-gray-700">
{issue.project_detail.identifier}-{issue.sequence_id}
</div>
)}
<h5
className="mb-3 text-sm group-hover:text-theme"
className="text-sm group-hover:text-theme"
style={{ lineClamp: 3, WebkitLineClamp: 3 }}
>
{issue.name}
</h5>
</a>
</Link>
<div className="relative flex flex-wrap items-center gap-x-1 gap-y-2 text-xs">
<div className="relative flex flex-wrap items-center gap-2 mt-2.5 text-xs">
{properties.priority && selectedGroup !== "priority" && (
<ViewPrioritySelect
issue={issue}
Expand Down
4 changes: 2 additions & 2 deletions apps/app/components/core/issues-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -371,13 +371,13 @@ export const IssuesView: React.FC<Props> = ({
<div
className={`${
trashBox ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"
} fixed z-20 top-12 left-1/2 -translate-x-1/2 flex items-center gap-2 bg-red-100 border-2 border-red-500 p-3 text-xs rounded ${
} fixed z-20 top-9 right-9 flex justify-center items-center gap-2 bg-red-100 border-2 border-red-500 p-3 w-96 h-28 text-xs italic text-red-500 font-medium rounded ${
snapshot.isDraggingOver ? "bg-red-500 text-white" : ""
} duration-200`}
ref={provided.innerRef}
{...provided.droppableProps}
>
<TrashIcon className="h-3 w-3" />
<TrashIcon className="h-4 w-4" />
Drop issue here to delete
</div>
)}
Expand Down
21 changes: 21 additions & 0 deletions apps/app/components/icons/backlog-state-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";

import type { Props } from "./types";

export const BacklogStateIcon: React.FC<Props> = ({
width = "20",
height = "20",
className,
color = "#858e96",
}) => (
<svg
width={width}
height={height}
className={className}
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="10" cy="10" r="9" stroke={color} strokeLinecap="round" strokeDasharray="4 4" />
</svg>
);
78 changes: 78 additions & 0 deletions apps/app/components/icons/cancelled-state-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from "react";

import type { Props } from "./types";

export const CancelledStateIcon: React.FC<Props> = ({
width = "20",
height = "20",
className,
color = "#f2655a",
}) => (
<svg
width={width}
height={height}
className={className}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 84.36 84.36"
>
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M20.45,7.69a39.74,39.74,0,0,1,43.43.54"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M76.67,20.45a39.76,39.76,0,0,1-.53,43.43"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M63.92,76.67a39.78,39.78,0,0,1-43.44-.53"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M7.69,63.92a39.75,39.75,0,0,1,.54-43.44"
/>
<circle className="cls-2" fill={color} cx="42.18" cy="42.18" r="31.04" />
<path
className="cls-3"
fill="none"
strokeWidth={3}
stroke="#ffffff"
strokeLinecap="square"
strokeMiterlimit={10}
d="M32.64,32.44q9.54,9.75,19.09,19.48"
/>
<path
className="cls-3"
fill="none"
strokeWidth={3}
stroke="#ffffff"
strokeLinecap="square"
strokeMiterlimit={10}
d="M32.64,51.92,51.73,32.44"
/>
</g>
</g>
</svg>
);
Loading

1 comment on commit 99cf2d4

@vercel
Copy link

@vercel vercel bot commented on 99cf2d4 Mar 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

plane-dev – ./apps/app

plane-dev-git-develop-caravel.vercel.app
plane-dev.vercel.app
plane-dev-caravel.vercel.app

Please sign in to comment.