feat: dropdown enhancements

This commit is contained in:
Henry
2024-11-20 22:35:20 +00:00
parent da061430b3
commit db80839f98
16 changed files with 76 additions and 98 deletions

View File

@@ -4,13 +4,13 @@ export default function Dropdown({
items,
children,
}: {
items: { label: string; action: () => void }[];
items: { label: string; action: () => void; icon?: React.ReactNode }[];
children: React.ReactNode;
}) {
return (
<Menu as="div" className="relative inline-block text-left">
<div>
<Menu.Button className="flex h-8 w-8 items-center justify-center rounded-[5px] hover:bg-light-200 dark:hover:bg-dark-200">
<Menu.Button className="flex h-7 w-7 items-center justify-center rounded-[5px] hover:bg-light-200 dark:hover:bg-dark-200">
{children}
</Menu.Button>
</div>
@@ -24,14 +24,15 @@ export default function Dropdown({
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 z-30 mt-2 w-56 origin-top-right rounded-md border border-light-200 bg-light-50 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-dark-400 dark:bg-dark-300">
<div className="flex">
<Menu.Items className="absolute right-0 z-30 mt-2 w-56 origin-top-right rounded-md border border-light-200 bg-light-50 p-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-dark-400 dark:bg-dark-300">
<div className="flex flex-col">
{items.map((item) => (
<Menu.Item key={item.label}>
<button
onClick={item.action}
className="m-1 w-full rounded-[5px] px-3 py-2 text-left text-sm text-neutral-900 hover:bg-light-200 dark:text-dark-1000 dark:hover:bg-dark-400"
className="flex w-auto items-center gap-2 rounded-[5px] px-2.5 py-1.5 text-left text-sm text-neutral-900 hover:bg-light-200 dark:text-dark-950 dark:hover:bg-dark-400"
>
{item.icon}
{item.label}
</button>
</Menu.Item>

View File

@@ -19,7 +19,7 @@ const FeedbackButton: React.FC = () => {
<button
type="button"
onMouseEnter={handleMouseEnter}
className="flex items-center rounded-md border-[1px] border-light-600 bg-light-50 px-2.5 py-1.5 text-sm font-normal text-neutral-900 shadow-sm dark:border-dark-600 dark:bg-dark-50 dark:text-dark-1000"
className="flex items-center rounded-md border-[1px] border-light-600 bg-light-50 px-2.5 py-1.5 text-sm font-normal text-neutral-900 shadow-sm dark:border-dark-400 dark:bg-dark-50 dark:text-dark-1000"
>
<LottieIcon
index={index}

View File

@@ -50,7 +50,7 @@ export default function SideNavigation({
return (
<>
<nav className="flex w-72 flex-col justify-between border-r border-light-600 px-3 pb-3 pt-5 dark:border-dark-600">
<nav className="flex w-72 flex-col justify-between border-r border-light-600 px-3 pb-3 pt-5 dark:border-dark-400">
<div>
<WorkspaceMenu />
<ul role="list" className="space-y-1">

View File

@@ -7,7 +7,7 @@ export default function Dashboard(props: { children: React.ReactNode }) {
return (
<div className="flex h-screen flex-col items-center bg-light-100 dark:bg-dark-50">
<div className="m-auto flex h-16 min-h-16 w-full justify-between border-b border-light-600 px-5 py-2 align-middle dark:border-dark-600">
<div className="m-auto flex h-16 min-h-16 w-full justify-between border-b border-light-600 px-5 py-2 align-middle dark:border-dark-400">
<div className="my-auto flex w-full items-center justify-between">
<h1 className="text-lg font-bold tracking-tight text-neutral-900 dark:text-dark-1000">
kan.bn

View File

@@ -1,5 +1,5 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/dashboard";
import Dashboard from "~/components/Dashboard";
import Popup from "~/components/Popup";
import BoardView from "~/views/board";

View File

@@ -1,5 +1,5 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/dashboard";
import Dashboard from "~/components/Dashboard";
import Popup from "~/components/Popup";
import BoardsView from "~/views/boards";

View File

@@ -1,5 +1,5 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/dashboard";
import Dashboard from "~/components/Dashboard";
import Popup from "~/components/Popup";
import CardView from "~/views/card";

View File

@@ -1,5 +1,5 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/dashboard";
import Dashboard from "~/components/Dashboard";
import Popup from "~/components/Popup";
import MembersView from "~/views/members";

View File

@@ -1,5 +1,5 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/dashboard";
import Dashboard from "~/components/Dashboard";
import SettingsView from "~/views/settings";
import Popup from "~/components/Popup";

View File

@@ -1,12 +1,17 @@
import { type ReactNode } from "react";
import { HiOutlinePlusSmall } from "react-icons/hi2";
import {
HiOutlinePlusSmall,
HiEllipsisHorizontal,
HiOutlineTrash,
HiOutlineSquaresPlus,
} from "react-icons/hi2";
import { Draggable } from "react-beautiful-dnd";
import { useForm } from "react-hook-form";
import { api } from "~/utils/api";
import { useModal } from "~/providers/modal";
import ListDropdown from "./ListDropdown";
import Dropdown from "~/components/Dropdown";
interface ListProps {
children: ReactNode;
@@ -60,6 +65,11 @@ export default function List({
});
};
const handleOpenDeleteListConfirmation = () => {
setSelectedPublicListId(list.publicId);
openModal("DELETE_LIST");
};
return (
<Draggable key={list.publicId} draggableId={list.publicId} index={index}>
{(provided) => (
@@ -85,7 +95,7 @@ export default function List({
</form>
<div>
<button
className="mx-1 inline-flex h-fit items-center rounded-md p-1 px-1 text-sm font-semibold text-dark-50 hover:bg-light-400 dark:hover:bg-dark-400"
className="mx-1 inline-flex h-fit items-center rounded-md p-1 px-1 text-sm font-semibold text-dark-50 hover:bg-light-400 dark:hover:bg-dark-200"
onClick={() => openNewCardForm(list.publicId)}
>
<HiOutlinePlusSmall
@@ -93,11 +103,28 @@ export default function List({
aria-hidden="true"
/>
</button>
<ListDropdown
setSelectedPublicListId={() =>
setSelectedPublicListId(list.publicId)
}
/>
<div className="relative mr-1 inline-block">
<Dropdown
items={[
{
label: "Add a card",
action: () => openNewCardForm(list.publicId),
icon: (
<HiOutlineSquaresPlus className="h-[18px] w-[18px] text-dark-900" />
),
},
{
label: "Delete list",
action: handleOpenDeleteListConfirmation,
icon: (
<HiOutlineTrash className="h-[18px] w-[18px] text-dark-900" />
),
},
]}
>
<HiEllipsisHorizontal className="h-5 w-5 text-dark-900" />
</Dropdown>
</div>
</div>
</div>
{children}

View File

@@ -1,52 +0,0 @@
import { Fragment } from "react";
import { Menu, Transition } from "@headlessui/react";
import { HiEllipsisHorizontal } from "react-icons/hi2";
import { useModal } from "~/providers/modal";
interface ListDropdownProps {
setSelectedPublicListId: () => void;
}
export default function ListDropdown({
setSelectedPublicListId,
}: ListDropdownProps) {
const { openModal } = useModal();
const handleOpenDeleteListConfirmation = () => {
setSelectedPublicListId();
openModal("DELETE_LIST");
};
return (
<Menu as="div" className="relative inline-block text-left">
<div>
<Menu.Button className="mr-1 inline-flex h-fit items-center rounded-md p-1 px-1 text-sm font-semibold text-dark-50 hover:bg-light-400 dark:hover:bg-dark-400">
<HiEllipsisHorizontal className="h-5 w-5 text-dark-900" />
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="dark-text-dark-1000 absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md border border-light-400 bg-light-50 text-neutral-900 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-dark-400 dark:bg-dark-300">
<div className="flex">
<Menu.Item>
<button
onClick={handleOpenDeleteListConfirmation}
className="m-1 w-full rounded-[5px] px-3 py-2 text-left text-sm text-neutral-900 hover:bg-light-200 dark:text-dark-1000 dark:hover:bg-dark-400"
>
Delete list
</button>
</Menu.Item>
</div>
</Menu.Items>
</Transition>
</Menu>
);
}

View File

@@ -16,7 +16,6 @@ import { formatToArray } from "~/utils/helpers";
import { useBoard } from "~/providers/board";
import { useModal } from "~/providers/modal";
import { useWorkspace } from "~/providers/workspace";
import { PageHead } from "~/components/PageHead";
import Modal from "~/components/modal";
import PatternedBackground from "~/components/PatternedBackground";
@@ -147,7 +146,7 @@ export default function BoardPage() {
<div className="z-10 flex w-full justify-between p-8">
{isLoading ? (
<div className="flex space-x-2">
<div className="h-[2.3rem] w-[150px] animate-pulse rounded-[5px] bg-light-200 dark:bg-dark-200" />
<div className="h-[2.3rem] w-[150px] animate-pulse rounded-[5px] bg-light-200 dark:bg-dark-100" />
</div>
) : (
<form
@@ -184,9 +183,9 @@ export default function BoardPage() {
<div className="scrollbar-w-none z-0 flex-1 overflow-y-hidden overflow-x-scroll overscroll-contain scrollbar scrollbar-track-light-200 scrollbar-thumb-light-400 scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-h-[8px] dark:scrollbar-track-dark-100 dark:scrollbar-thumb-dark-300">
{isLoading ? (
<div className="ml-[2rem] flex">
<div className="0 mr-5 h-[500px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
<div className="0 mr-5 h-[275px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
<div className="0 mr-5 h-[375px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
<div className="0 mr-5 h-[500px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
<div className="0 mr-5 h-[275px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
<div className="0 mr-5 h-[375px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
</div>
) : (
<DragDropContext onDragEnd={onDragEnd}>
@@ -236,7 +235,7 @@ export default function BoardPage() {
}}
key={card.publicId}
href={`/cards/${card.publicId}`}
className={`mb-2 flex !cursor-pointer flex-col rounded-md border border-light-200 bg-light-50 px-3 py-2 text-sm text-neutral-900 dark:border-dark-200 dark:bg-dark-300 dark:text-dark-1000 dark:hover:bg-dark-400 ${
className={`mb-2 flex !cursor-pointer flex-col rounded-md border border-light-200 bg-light-50 px-3 py-2 text-sm text-neutral-900 dark:border-dark-200 dark:bg-dark-200 dark:text-dark-1000 dark:hover:bg-dark-300 ${
card.publicId.startsWith("PLACEHOLDER")
? "pointer-events-none"
: ""

View File

@@ -15,9 +15,9 @@ export function BoardsList() {
if (isLoading)
return (
<div className="grid w-full grid-cols-1 gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xxl:grid-cols-5">
<div className="mr-5 flex h-[150px] w-full animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
<div className="mr-5 flex h-[150px] w-full animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
<div className="mr-5 flex h-[150px] w-full animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
<div className="mr-5 flex h-[150px] w-full animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
<div className="mr-5 flex h-[150px] w-full animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
<div className="mr-5 flex h-[150px] w-full animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
</div>
);
@@ -27,7 +27,7 @@ export function BoardsList() {
<div className="grid w-full grid-cols-1 gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xxl:grid-cols-5">
{data?.map((board) => (
<Link key={board.publicId} href={`boards/${board.publicId}`}>
<div className="align-center relative mr-5 flex h-[150px] w-full items-center justify-center rounded-md border border-dashed border-light-600 bg-light-50 shadow-sm hover:bg-light-200 dark:border-dark-600 dark:bg-dark-50 dark:hover:bg-dark-100">
<div className="align-center relative mr-5 flex h-[150px] w-full items-center justify-center rounded-md border border-dashed border-light-400 bg-light-50 shadow-sm hover:bg-light-200 dark:border-dark-600 dark:bg-dark-50 dark:hover:bg-dark-100">
<PatternedBackground />
<p className="text-md px-4 font-medium text-neutral-900 dark:text-dark-1000">
{board.name}

View File

@@ -9,7 +9,7 @@ import { usePopup } from "~/providers/popup";
import Avatar from "~/components/Avatar";
import Button from "~/components/Button";
import Dropdown from "~/components/Dropdown";
import { HiEllipsisHorizontal } from "react-icons/hi2";
import { HiEllipsisHorizontal, HiPencil } from "react-icons/hi2";
interface FormValues {
comment: string;
@@ -69,7 +69,7 @@ const Comment = ({
return (
<div
key={publicId}
className="group relative flex w-full flex-col rounded-xl border border-light-600 bg-light-200 p-5 text-light-900 focus-visible:outline-none dark:border-dark-600 dark:bg-dark-100 dark:text-dark-1000 sm:text-sm sm:leading-6"
className="group relative flex w-full flex-col rounded-xl border border-light-600 bg-light-200 p-4 text-light-900 focus-visible:outline-none dark:border-dark-400 dark:bg-dark-100 dark:text-dark-1000 sm:text-sm sm:leading-6"
>
<div className="flex justify-between">
<div className="flex items-center space-x-2">
@@ -96,16 +96,19 @@ const Comment = ({
</p>
</div>
<Dropdown
items={[
{
label: "Edit",
action: () => setIsEditing(true),
},
]}
>
<HiEllipsisHorizontal className="h-5 w-5" />
</Dropdown>
<div className="absolute right-4 top-4">
<Dropdown
items={[
{
label: "Edit comment",
action: () => setIsEditing(true),
icon: <HiPencil className="h-[18px] w-[18px] text-dark-900" />,
},
]}
>
<HiEllipsisHorizontal className="h-5 w-5 text-light-900 dark:text-dark-800" />
</Dropdown>
</div>
</div>
{!isEditing ? (
<p className="mt-2 text-sm">{comment}</p>

View File

@@ -43,7 +43,7 @@ const NewCommentForm = ({ cardPublicId }: { cardPublicId: string }) => {
return (
<form
onSubmit={handleSubmit(onSubmit)}
className="flex w-full flex-col rounded-xl border border-light-600 bg-light-200 p-5 text-light-900 focus-visible:outline-none dark:border-dark-600 dark:bg-dark-100 dark:text-dark-1000 sm:text-sm sm:leading-6"
className="flex w-full flex-col rounded-xl border border-light-600 bg-light-200 p-4 text-light-900 focus-visible:outline-none dark:border-dark-400 dark:bg-dark-100 dark:text-dark-1000 sm:text-sm sm:leading-6"
>
<ContentEditable
placeholder="Add a comment..."
@@ -56,7 +56,7 @@ const NewCommentForm = ({ cardPublicId }: { cardPublicId: string }) => {
<button
type="submit"
disabled={addCommentMutation.isPending}
className="flex h-8 w-8 items-center justify-center rounded-full border border-light-600 bg-light-300 hover:bg-light-400 disabled:opacity-50 dark:border-dark-600 dark:bg-dark-300 dark:hover:bg-dark-400"
className="flex h-8 w-8 items-center justify-center rounded-full border border-light-600 bg-light-300 hover:bg-light-400 disabled:opacity-50 dark:border-dark-400 dark:bg-dark-200 dark:hover:bg-dark-400"
>
{addCommentMutation.isPending ? (
<LoadingSpinner size="sm" />

View File

@@ -175,7 +175,7 @@ export default function CardPage() {
</div>
</form>
</div>
<div className="border-t-[1px] border-light-600 pt-12 dark:border-dark-600">
<div className="border-t-[1px] border-light-600 pt-12 dark:border-dark-400">
<h2 className="text-md pb-4 font-medium text-light-900 dark:text-dark-1000">
Activity
</h2>