Skip to content

Commit

Permalink
feat(add): ✨ added add dropdown (#177)
Browse files Browse the repository at this point in the history
* feat(add): ✨ added add dropdown

* feat(add): 🚧 stuck in focus issue

* fix(scrapper): ⚡️ added scrapper error proceed condition

* fix(add): 🐛 fixed the add focus issue

* refactor(add modal): ♻️ removed add modal and unused store states
  • Loading branch information
abhishekmg authored Apr 22, 2024
1 parent 9783dcd commit ee8c738
Showing 11 changed files with 164 additions and 213 deletions.
17 changes: 11 additions & 6 deletions src/components/ariaDropdown/ariaDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { useEffect } from "react";
import { type RefObject } from "react";
import { Menu, MenuButton, useMenuState } from "ariakit/menu";

import { type ChildrenTypes } from "../../types/componentTypes";

type AriaDropDownPropertyTypes = {
children: ChildrenTypes;
// the element you want to focus when the menu opens
initialFocusRef?: RefObject<HTMLElement> | undefined;
isOpen?: boolean;
menuButton: ChildrenTypes;
menuButtonActiveClassName?: string;
menuButtonClassName?: string;
@@ -14,22 +17,23 @@ type AriaDropDownPropertyTypes = {
};

const AriaDropDown = (props: AriaDropDownPropertyTypes) => {
const menu = useMenuState({ gutter: 1 });
const menu = useMenuState({
gutter: 1,
defaultOpen: props.isOpen,
setOpen: (value) => menuOpenToggle(value),
});
const {
menuButton,
menuClassName,
menuButtonClassName,
menuOpenToggle = () => null,
children,

// we have this as a prop because i dont want to send menu state to button render prop
menuButtonActiveClassName,
onButtonClick = () => null,
} = props;

useEffect(() => {
menuOpenToggle(menu?.open);
}, [menu?.open, menuOpenToggle]);

return (
<>
<MenuButton
@@ -43,6 +47,7 @@ const AriaDropDown = (props: AriaDropDownPropertyTypes) => {
</MenuButton>
<Menu
className={`${menuClassName ?? ""} focus-visible:outline-none`}
initialFocusRef={props.initialFocusRef}
state={menu}
>
{children}
3 changes: 0 additions & 3 deletions src/components/ariaSlidingMenu/index.tsx
Original file line number Diff line number Diff line change
@@ -181,8 +181,6 @@ export const Menu = React.forwardRef<HTMLDivElement, MenuProps>(
<Ariakit.Menu
autoFocusOnHide={autoFocus}
autoFocusOnShow={autoFocus}
// className="menu"
// className={` z-10 ${currentSliderDropdownSlide === null ? "h-[115px]" : "h-[350px]"} ${dropdownMenuClassName}`}
className={menuClassName}
flip={!isSubmenu}
getAnchorRect={(anchor) =>
@@ -207,7 +205,6 @@ export const Menu = React.forwardRef<HTMLDivElement, MenuProps>(
>
<Ariakit.MenuItem
aria-label="Back to parent menu"
// className={menuItemClassName}
focusOnHover={false}
hideOnClick={false}
onClick={() => {
87 changes: 87 additions & 0 deletions src/components/customDropdowns.tsx/addBookmarkDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { useRef } from "react";
import { isEmpty, isNull } from "lodash";
import { useForm, type SubmitHandler } from "react-hook-form";

import AddBoomarkInputIcon from "../../icons/miscellaneousIcons/addBoomarkInputIcon";
import PlusIconWhite from "../../icons/plusIconWhite";
import {
dropdownMenuClassName,
grayInputClassName,
} from "../../utils/commonClassNames";
import { URL_PATTERN } from "../../utils/constants";
import { AriaDropdown } from "../ariaDropdown";
import Button from "../atoms/button";
import Input from "../atoms/input";

export type AddBookmarkDropdownTypes = {
onAddBookmark: (url: string) => void;
};

const AddBookmarkDropdown = ({ onAddBookmark }: AddBookmarkDropdownTypes) => {
const {
register,
handleSubmit,
formState: { errors },
reset,
clearErrors,
} = useForm<{ url: string }>();
const onSubmit: SubmitHandler<{ url: string }> = (data) => {
onAddBookmark(data.url);
reset({ url: "" });
};

const inputRef = useRef<HTMLInputElement>(null);

const { ref, ...rest } = register("url", {
required: true,
pattern: URL_PATTERN,
});

return (
<AriaDropdown
initialFocusRef={inputRef}
menuButton={
<Button
className="rounded-full p-[7px] hover:bg-black"
title="create"
type="dark"
>
<figure className="h-4 w-4">
<PlusIconWhite />
</figure>
</Button>
}
menuOpenToggle={(value) => {
if (value === false) {
reset({ url: "" });
clearErrors();
}
}}
>
<div className={`relative w-[326px] ${dropdownMenuClassName}`}>
<AddBoomarkInputIcon className="absolute left-[14px] top-[13px] z-[1]" />
<form onSubmit={handleSubmit(onSubmit)}>
<Input
autoFocus
className={`rounded-[11px] pl-[32px] ${grayInputClassName}`}
errorClassName="ml-2"
{...rest}
errorText="Enter valid URL"
isError={!isEmpty(errors)}
placeholder="Add a link or drop a file anywhere"
ref={(event) => {
ref(event);
if (!isNull(inputRef)) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
inputRef.current = event;
}
}}
/>
</form>
</div>
</AriaDropdown>
);
};

export default AddBookmarkDropdown;
41 changes: 41 additions & 0 deletions src/icons/miscellaneousIcons/addBoomarkInputIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const AddBoomarkInputIcon = ({ className = "" }) => (
<svg
className={className}
fill="none"
height="16"
viewBox="0 0 17 16"
width="17"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_8563_33222)">
<rect
height="10.0149"
rx="2.5"
stroke="#707070"
transform="rotate(7.33079 7.15575 3.55971)"
width="8.58873"
x="7.15575"
y="3.55971"
/>
<rect
fill="#FAFAFA"
height="11.1327"
rx="2.5"
stroke="#707070"
transform="rotate(-13.8817 0.744027 3.85372)"
width="9.37244"
x="0.744027"
y="3.85372"
/>
<path d="M6.01514 5.75L7.24241 10.25" stroke="#707070" />
<path d="M8.87891 7.38672L4.37891 8.61399" stroke="#707070" />
</g>
<defs>
<clipPath id="clip0_8563_33222">
<rect fill="white" height="16" transform="translate(0.5)" width="16" />
</clipPath>
</defs>
</svg>
);

export default AddBoomarkInputIcon;
16 changes: 9 additions & 7 deletions src/pageComponents/dashboard/dashboardLayout.tsx
Original file line number Diff line number Diff line change
@@ -54,6 +54,9 @@ import "react-modern-drawer/dist/index.css";
import { isNull } from "lodash";

import { AriaDropdown } from "../../components/ariaDropdown";
import AddBookmarkDropdown, {
type AddBookmarkDropdownTypes,
} from "../../components/customDropdowns.tsx/addBookmarkDropdown";
import CollapseHandle from "../../icons/actionIcons/collapseHandle";
import RenameIcon from "../../icons/actionIcons/renameIcon";
import TrashIconRed from "../../icons/actionIcons/trashIconRed";
@@ -69,6 +72,7 @@ import ShareContent from "./share/shareContent";

type DashboardLayoutProps = {
categoryId: CategoryIdUrlTypes;
onAddBookmark: AddBookmarkDropdownTypes["onAddBookmark"];
onAddNewCategory: (value: string) => Promise<void>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onBookmarksDrop: (event: any) => Promise<void>;
@@ -80,7 +84,6 @@ type DashboardLayoutProps = {
onClearTrash: () => void;
onIconColorChange: CategoryIconsDropdownTypes["onIconColorChange"];
onIconSelect: (value: string, id: number) => void;
onNavAddClick: () => void;
renderMainContent: () => ChildrenTypes;
setBookmarksView: (
value: BookmarksSortByTypes | BookmarksViewTypes | number[] | string[],
@@ -103,7 +106,7 @@ const DashboardLayout = (props: DashboardLayoutProps) => {
onClearTrash,
onIconSelect,
setBookmarksView,
onNavAddClick,
onAddBookmark,
onBookmarksDrop,
updateCategoryName,
onIconColorChange,
@@ -496,8 +499,7 @@ const DashboardLayout = (props: DashboardLayoutProps) => {
{renderSearchBar}
<div className="flex w-[27%] items-center justify-end space-x-3 xl:w-max xl:space-x-2">
{renderViewBasedHeaderOptions()}
{/* {typeof categoryId === "number" && <ShareDropdown />} */}
{currentPath !== TRASH_URL && (
{/* {currentPath !== TRASH_URL && (
<Button
className="rounded-full p-[7px] hover:bg-black"
onClick={onNavAddClick}
@@ -507,10 +509,10 @@ const DashboardLayout = (props: DashboardLayoutProps) => {
<figure className="h-4 w-4">
<PlusIconWhite />
</figure>
{/* <span className="ml-[6px] font-medium leading-[14px] text-white xl:hidden">
Create
</span> */}
</Button>
)} */}
{currentPath !== TRASH_URL && (
<AddBookmarkDropdown onAddBookmark={onAddBookmark} />
)}
</div>
</div>
39 changes: 4 additions & 35 deletions src/pageComponents/dashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -16,8 +16,6 @@ import "react-toastify/dist/ReactToastify.css";

import uniqid from "uniqid";

// import "react-toastify/dist/ReactToastify.minimal.css";

import useAddBookmarkMinDataOptimisticMutation from "../../async/mutationHooks/bookmarks/useAddBookmarkMinDataOptimisticMutation";
import useAddBookmarkScreenshotMutation from "../../async/mutationHooks/bookmarks/useAddBookmarkScreenshotMutation";
import useClearBookmarksInTrashMutation from "../../async/mutationHooks/bookmarks/useClearBookmarksInTrashMutation";
@@ -88,7 +86,6 @@ import { errorToast, successToast } from "../../utils/toastMessages";
import NotFoundPage from "../notFoundPage";
import Settings from "../settings";

import AddBookarkShortcutModal from "./modals/addBookmarkShortcutModal";
import AddModalContent from "./modals/addModalContent";
import SettingsModal from "./modals/settingsModal";
import ShareCategoryModal from "./modals/shareCategoryModal";
@@ -136,10 +133,6 @@ const Dashboard = () => {
(state) => state.toggleShareCategoryModal,
);

const toggleShowAddBookmarkShortcutModal = useModalStore(
(state) => state.toggleShowAddBookmarkShortcutModal,
);

const showDeleteBookmarkWarningModal = useModalStore(
(state) => state.showDeleteBookmarkWarningModal,
);
@@ -160,18 +153,6 @@ const Dashboard = () => {
(state) => state.setShareCategoryId,
);

useEffect(() => {
const down = (event: KeyboardEvent) => {
if (event.key === "k" && event.metaKey && categorySlug !== TRASH_URL) {
toggleShowAddBookmarkShortcutModal();
}
};

document.addEventListener("keydown", down);
return () => document.removeEventListener("keydown", down);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [categorySlug]);

useEffect(() => {
if (!showAddBookmarkModal) {
setIsEdit(false);
@@ -1007,6 +988,10 @@ const Dashboard = () => {
<>
<DashboardLayout
categoryId={CATEGORY_ID}
onAddBookmark={(url) => {
const finalUrl = url?.includes("https://") ? url : `https://${url}`;
void addBookmarkLogic(finalUrl);
}}
onAddNewCategory={async (newCategoryName) => {
if (!isNull(userProfileData?.data)) {
const response = (await mutationApiCall(
@@ -1151,7 +1136,6 @@ const Dashboard = () => {
}),
);
}}
onNavAddClick={() => toggleShowAddBookmarkShortcutModal()}
renderMainContent={renderMainPaneContent}
setBookmarksView={(value, type) => {
bookmarksViewApiLogic(value, type);
@@ -1168,23 +1152,8 @@ const Dashboard = () => {
);
}}
userId={session?.user?.id ?? ""}
// onShareClick={() => {
// if (CATEGORY_ID && !isNull(CATEGORY_ID) && CATEGORY_ID !== "trash") {
// toggleShareCategoryModal();
// setShareCategoryId(CATEGORY_ID as number);
// }
// }}
/>
<ShareCategoryModal />
<AddBookarkShortcutModal
isAddBookmarkLoading={false}
onAddBookmark={(url) => {
const finalUrl = url?.includes("https://") ? url : `https://${url}`;
void addBookmarkLogic(finalUrl);

toggleShowAddBookmarkShortcutModal();
}}
/>
<SettingsModal />
<WarningActionModal
buttonText="Delete"
Loading

0 comments on commit ee8c738

Please sign in to comment.