forked from github/plane
fix: mobile responsive sidebar close on item tap (#3661)
This commit is contained in:
parent
e51e4761b9
commit
1d2e331cec
@ -3,12 +3,20 @@ import { Menu } from "lucide-react";
|
||||
import { useApplication } from "hooks/store";
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
export const SidebarHamburgerToggle: FC = observer(() => {
|
||||
const { theme: themStore } = useApplication();
|
||||
type Props = {
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
export const SidebarHamburgerToggle: FC<Props> = observer((props) => {
|
||||
const { onClick } = props
|
||||
const { theme: themeStore } = useApplication();
|
||||
return (
|
||||
<div
|
||||
className="w-7 h-7 flex-shrink-0 rounded flex justify-center items-center bg-custom-background-80 transition-all hover:bg-custom-background-90 cursor-pointer group md:hidden"
|
||||
onClick={() => themStore.toggleMobileSidebar()}
|
||||
onClick={() => {
|
||||
if (onClick) onClick()
|
||||
else themeStore.toggleMobileSidebar()
|
||||
}}
|
||||
>
|
||||
<Menu size={14} className="text-custom-text-200 group-hover:text-custom-text-100 transition-all" />
|
||||
</div>
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
MoreHorizontal,
|
||||
} from "lucide-react";
|
||||
// hooks
|
||||
import { useApplication,useEventTracker, useProject } from "hooks/store";
|
||||
import { useApplication, useEventTracker, useProject } from "hooks/store";
|
||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||
import useToast from "hooks/use-toast";
|
||||
// helpers
|
||||
@ -131,7 +131,7 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
|
||||
|
||||
const handleProjectClick = () => {
|
||||
if (window.innerWidth < 768) {
|
||||
themeStore.toggleSidebar();
|
||||
themeStore.toggleMobileSidebar();
|
||||
}
|
||||
};
|
||||
|
||||
@ -147,8 +147,7 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
|
||||
{({ open }) => (
|
||||
<>
|
||||
<div
|
||||
className={`group relative flex w-full items-center rounded-md px-2 py-1 text-custom-sidebar-text-10 hover:bg-custom-sidebar-background-80 ${
|
||||
snapshot?.isDragging ? "opacity-60" : ""
|
||||
className={`group relative flex w-full items-center rounded-md px-2 py-1 text-custom-sidebar-text-10 hover:bg-custom-sidebar-background-80 ${snapshot?.isDragging ? "opacity-60" : ""
|
||||
} ${isMenuActive ? "!bg-custom-sidebar-background-80" : ""}`}
|
||||
>
|
||||
{provided && (
|
||||
@ -158,10 +157,8 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className={`absolute -left-2.5 top-1/2 hidden -translate-y-1/2 rounded p-0.5 text-custom-sidebar-text-400 ${
|
||||
isCollapsed ? "" : "group-hover:!flex"
|
||||
} ${project.sort_order === null ? "cursor-not-allowed opacity-60" : ""} ${
|
||||
isMenuActive ? "!flex" : ""
|
||||
className={`absolute -left-2.5 top-1/2 hidden -translate-y-1/2 rounded p-0.5 text-custom-sidebar-text-400 ${isCollapsed ? "" : "group-hover:!flex"
|
||||
} ${project.sort_order === null ? "cursor-not-allowed opacity-60" : ""} ${isMenuActive ? "!flex" : ""
|
||||
}`}
|
||||
{...provided?.dragHandleProps}
|
||||
>
|
||||
@ -173,13 +170,11 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
|
||||
<Tooltip tooltipContent={`${project.name}`} position="right" className="ml-2" disabled={!isCollapsed}>
|
||||
<Disclosure.Button
|
||||
as="div"
|
||||
className={`flex flex-grow cursor-pointer select-none items-center truncate text-left text-sm font-medium ${
|
||||
isCollapsed ? "justify-center" : `justify-between`
|
||||
className={`flex flex-grow cursor-pointer select-none items-center truncate text-left text-sm font-medium ${isCollapsed ? "justify-center" : `justify-between`
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`flex w-full flex-grow items-center gap-x-2 truncate ${
|
||||
isCollapsed ? "justify-center" : ""
|
||||
className={`flex w-full flex-grow items-center gap-x-2 truncate ${isCollapsed ? "justify-center" : ""
|
||||
}`}
|
||||
>
|
||||
{project.emoji ? (
|
||||
@ -200,8 +195,7 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
|
||||
</div>
|
||||
{!isCollapsed && (
|
||||
<ChevronDown
|
||||
className={`hidden h-4 w-4 flex-shrink-0 ${open ? "rotate-180" : ""} ${
|
||||
isMenuActive ? "!block" : ""
|
||||
className={`hidden h-4 w-4 flex-shrink-0 ${open ? "rotate-180" : ""} ${isMenuActive ? "!block" : ""
|
||||
} mb-0.5 text-custom-sidebar-text-400 duration-300 group-hover:!block`}
|
||||
/>
|
||||
)}
|
||||
@ -326,8 +320,7 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
|
||||
disabled={!isCollapsed}
|
||||
>
|
||||
<div
|
||||
className={`group flex items-center gap-2.5 rounded-md px-2 py-1.5 text-xs font-medium outline-none ${
|
||||
router.asPath.includes(item.href)
|
||||
className={`group flex items-center gap-2.5 rounded-md px-2 py-1.5 text-xs font-medium outline-none ${router.asPath.includes(item.href)
|
||||
? "bg-custom-primary-100/10 text-custom-primary-100"
|
||||
: "text-custom-sidebar-text-300 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80"
|
||||
} ${isCollapsed ? "justify-center" : ""}`}
|
||||
|
@ -10,6 +10,7 @@ import { FileText, HelpCircle, MessagesSquare, MoveLeft, Zap } from "lucide-reac
|
||||
import { DiscordIcon, GithubIcon, Tooltip } from "@plane/ui";
|
||||
// assets
|
||||
import packageJson from "package.json";
|
||||
import useSize from "hooks/use-window-size";
|
||||
|
||||
const helpOptions = [
|
||||
{
|
||||
@ -42,9 +43,11 @@ export interface WorkspaceHelpSectionProps {
|
||||
export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observer(() => {
|
||||
// store hooks
|
||||
const {
|
||||
theme: { sidebarCollapsed, toggleSidebar },
|
||||
theme: { sidebarCollapsed, toggleSidebar, toggleMobileSidebar },
|
||||
commandPalette: { toggleShortcutModal },
|
||||
} = useApplication();
|
||||
|
||||
const [windowWidth] = useSize();
|
||||
// states
|
||||
const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false);
|
||||
// refs
|
||||
@ -57,8 +60,7 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={`flex w-full items-center justify-between gap-1 self-baseline border-t border-custom-border-200 bg-custom-sidebar-background-100 px-4 py-2 ${
|
||||
isCollapsed ? "flex-col" : ""
|
||||
className={`flex w-full items-center justify-between gap-1 self-baseline border-t border-custom-border-200 bg-custom-sidebar-background-100 px-4 py-2 ${isCollapsed ? "flex-col" : ""
|
||||
}`}
|
||||
>
|
||||
{!isCollapsed && (
|
||||
@ -70,8 +72,7 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
|
||||
<Tooltip tooltipContent="Shortcuts">
|
||||
<button
|
||||
type="button"
|
||||
className={`grid place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 ${
|
||||
isCollapsed ? "w-full" : ""
|
||||
className={`grid place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 ${isCollapsed ? "w-full" : ""
|
||||
}`}
|
||||
onClick={() => toggleShortcutModal(true)}
|
||||
>
|
||||
@ -81,8 +82,7 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
|
||||
<Tooltip tooltipContent="Help">
|
||||
<button
|
||||
type="button"
|
||||
className={`grid place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 ${
|
||||
isCollapsed ? "w-full" : ""
|
||||
className={`grid place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 ${isCollapsed ? "w-full" : ""
|
||||
}`}
|
||||
onClick={() => setIsNeedHelpOpen((prev) => !prev)}
|
||||
>
|
||||
@ -93,7 +93,7 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
|
||||
<button
|
||||
type="button"
|
||||
className="grid place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 md:hidden"
|
||||
onClick={() => toggleSidebar()}
|
||||
onClick={() => windowWidth <= 768 ? toggleMobileSidebar() : toggleSidebar()}
|
||||
>
|
||||
<MoveLeft className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
@ -101,10 +101,9 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
|
||||
<Tooltip tooltipContent={`${isCollapsed ? "Expand" : "Hide"}`}>
|
||||
<button
|
||||
type="button"
|
||||
className={`hidden place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 md:grid ${
|
||||
isCollapsed ? "w-full" : ""
|
||||
className={`hidden place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 md:grid ${isCollapsed ? "w-full" : ""
|
||||
}`}
|
||||
onClick={() => toggleSidebar()}
|
||||
onClick={() => windowWidth <= 768 ? toggleMobileSidebar() : toggleSidebar()}
|
||||
>
|
||||
<MoveLeft className={`h-3.5 w-3.5 duration-300 ${isCollapsed ? "rotate-180" : ""}`} />
|
||||
</button>
|
||||
@ -122,8 +121,7 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
|
||||
leaveTo="transform opacity-0 scale-95"
|
||||
>
|
||||
<div
|
||||
className={`absolute bottom-2 min-w-[10rem] ${
|
||||
isCollapsed ? "left-full" : "-left-[75px]"
|
||||
className={`absolute bottom-2 min-w-[10rem] ${isCollapsed ? "left-full" : "-left-[75px]"
|
||||
} divide-y divide-custom-border-200 whitespace-nowrap rounded bg-custom-background-100 p-1 shadow-custom-shadow-xs`}
|
||||
ref={helpOptionsRef}
|
||||
>
|
||||
|
@ -54,7 +54,7 @@ export const WorkspaceSidebarDropdown = observer(() => {
|
||||
const { workspaceSlug } = router.query;
|
||||
// store hooks
|
||||
const {
|
||||
theme: { sidebarCollapsed, toggleSidebar },
|
||||
theme: { sidebarCollapsed, toggleMobileSidebar },
|
||||
} = useApplication();
|
||||
const { setTrackElement } = useEventTracker();
|
||||
const { currentUser, updateCurrentUser, isUserInstanceAdmin, signOut } = useUser();
|
||||
@ -98,7 +98,7 @@ export const WorkspaceSidebarDropdown = observer(() => {
|
||||
};
|
||||
const handleItemClick = () => {
|
||||
if (window.innerWidth < 768) {
|
||||
toggleSidebar();
|
||||
toggleMobileSidebar();
|
||||
}
|
||||
};
|
||||
const workspacesList = Object.values(workspaces ?? {});
|
||||
@ -110,14 +110,12 @@ export const WorkspaceSidebarDropdown = observer(() => {
|
||||
<>
|
||||
<Menu.Button className="group/menu-button h-full w-full truncate rounded-md text-sm font-medium text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:outline-none">
|
||||
<div
|
||||
className={`flex items-center gap-x-2 truncate rounded p-1 ${
|
||||
sidebarCollapsed ? "justify-center" : "justify-between"
|
||||
className={`flex items-center gap-x-2 truncate rounded p-1 ${sidebarCollapsed ? "justify-center" : "justify-between"
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-2 truncate">
|
||||
<div
|
||||
className={`relative grid h-6 w-6 flex-shrink-0 place-items-center uppercase ${
|
||||
!activeWorkspace?.logo && "rounded bg-custom-primary-500 text-white"
|
||||
className={`relative grid h-6 w-6 flex-shrink-0 place-items-center uppercase ${!activeWorkspace?.logo && "rounded bg-custom-primary-500 text-white"
|
||||
}`}
|
||||
>
|
||||
{activeWorkspace?.logo && activeWorkspace.logo !== "" ? (
|
||||
@ -138,8 +136,7 @@ export const WorkspaceSidebarDropdown = observer(() => {
|
||||
</div>
|
||||
{!sidebarCollapsed && (
|
||||
<ChevronDown
|
||||
className={`mx-1 hidden h-4 w-4 flex-shrink-0 group-hover/menu-button:block ${
|
||||
open ? "rotate-180" : ""
|
||||
className={`mx-1 hidden h-4 w-4 flex-shrink-0 group-hover/menu-button:block ${open ? "rotate-180" : ""
|
||||
} text-custom-sidebar-text-400 duration-300`}
|
||||
/>
|
||||
)}
|
||||
@ -179,8 +176,7 @@ export const WorkspaceSidebarDropdown = observer(() => {
|
||||
>
|
||||
<div className="flex items-center justify-start gap-2.5 truncate">
|
||||
<span
|
||||
className={`relative flex h-6 w-6 flex-shrink-0 items-center justify-center p-2 text-xs uppercase ${
|
||||
!workspace?.logo && "rounded bg-custom-primary-500 text-white"
|
||||
className={`relative flex h-6 w-6 flex-shrink-0 items-center justify-center p-2 text-xs uppercase ${!workspace?.logo && "rounded bg-custom-primary-500 text-white"
|
||||
}`}
|
||||
>
|
||||
{workspace?.logo && workspace.logo !== "" ? (
|
||||
@ -194,8 +190,7 @@ export const WorkspaceSidebarDropdown = observer(() => {
|
||||
)}
|
||||
</span>
|
||||
<h5
|
||||
className={`truncate text-sm font-medium ${
|
||||
workspaceSlug === workspace.slug ? "" : "text-custom-text-200"
|
||||
className={`truncate text-sm font-medium ${workspaceSlug === workspace.slug ? "" : "text-custom-text-200"
|
||||
}`}
|
||||
>
|
||||
{workspace.name}
|
||||
|
@ -31,7 +31,7 @@ export const WorkspaceSidebarMenu = observer(() => {
|
||||
|
||||
const handleLinkClick = (itemKey: string) => {
|
||||
if (window.innerWidth < 768) {
|
||||
themeStore.toggleSidebar();
|
||||
themeStore.toggleMobileSidebar();
|
||||
}
|
||||
captureEvent(SIDEBAR_CLICKED, {
|
||||
destination: itemKey,
|
||||
@ -52,8 +52,7 @@ export const WorkspaceSidebarMenu = observer(() => {
|
||||
disabled={!themeStore?.sidebarCollapsed}
|
||||
>
|
||||
<div
|
||||
className={`group flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium outline-none ${
|
||||
link.highlight(router.asPath, `/${workspaceSlug}`)
|
||||
className={`group flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium outline-none ${link.highlight(router.asPath, `/${workspaceSlug}`)
|
||||
? "bg-custom-primary-100/10 text-custom-primary-100"
|
||||
: "text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80"
|
||||
} ${themeStore?.sidebarCollapsed ? "justify-center" : ""}`}
|
||||
|
@ -7,6 +7,7 @@ import { CustomMenu } from "@plane/ui";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { useApplication } from "hooks/store";
|
||||
|
||||
interface IProfilePreferenceSettingsLayout {
|
||||
children: ReactNode;
|
||||
@ -16,6 +17,7 @@ interface IProfilePreferenceSettingsLayout {
|
||||
export const ProfilePreferenceSettingsLayout: FC<IProfilePreferenceSettingsLayout> = (props) => {
|
||||
const { children, header } = props;
|
||||
const router = useRouter();
|
||||
const { theme: themeStore } = useApplication();
|
||||
|
||||
const showMenuItem = () => {
|
||||
const item = router.asPath.split('/');
|
||||
@ -42,7 +44,7 @@ export const ProfilePreferenceSettingsLayout: FC<IProfilePreferenceSettingsLayou
|
||||
return (
|
||||
<ProfileSettingsLayout header={
|
||||
<div className="md:hidden flex flex-shrink-0 gap-4 items-center justify-start border-b border-custom-border-200 p-4">
|
||||
<SidebarHamburgerToggle />
|
||||
<SidebarHamburgerToggle onClick={() => themeStore.toggleSidebar()} />
|
||||
<CustomMenu
|
||||
maxHeight={"md"}
|
||||
className="flex flex-grow justify-center text-custom-text-200 text-sm"
|
||||
|
@ -40,7 +40,7 @@ export const ProfileLayoutSidebar = observer(() => {
|
||||
const { setToastAlert } = useToast();
|
||||
// store hooks
|
||||
const {
|
||||
theme: { sidebarCollapsed, toggleSidebar },
|
||||
theme: { sidebarCollapsed, toggleSidebar, toggleMobileSidebar },
|
||||
} = useApplication();
|
||||
const { currentUser, currentUserSettings, signOut } = useUser();
|
||||
const { workspaces } = useWorkspace();
|
||||
@ -78,7 +78,7 @@ export const ProfileLayoutSidebar = observer(() => {
|
||||
|
||||
const handleItemClick = () => {
|
||||
if (window.innerWidth < 768) {
|
||||
toggleSidebar();
|
||||
toggleMobileSidebar();
|
||||
}
|
||||
};
|
||||
|
||||
@ -111,7 +111,7 @@ export const ProfileLayoutSidebar = observer(() => {
|
||||
`}
|
||||
>
|
||||
<div ref={ref} className="flex h-full w-full flex-col gap-y-4">
|
||||
<Link href={`/${redirectWorkspaceSlug}`}>
|
||||
<Link href={`/${redirectWorkspaceSlug}`} onClick={handleItemClick}>
|
||||
<div
|
||||
className={`flex flex-shrink-0 items-center gap-2 truncate px-4 pt-4 ${sidebarCollapsed ? "justify-center" : ""
|
||||
}`}
|
||||
|
@ -3,7 +3,7 @@ import useSWR from "swr";
|
||||
import Link from "next/link";
|
||||
import { observer } from "mobx-react";
|
||||
//hooks
|
||||
import { useUser } from "hooks/store";
|
||||
import { useApplication, useUser } from "hooks/store";
|
||||
// services
|
||||
import { UserService } from "services/user.service";
|
||||
// layouts
|
||||
@ -29,11 +29,12 @@ const ProfileActivityPage: NextPageWithLayout = observer(() => {
|
||||
const { data: userActivity } = useSWR(USER_ACTIVITY, () => userService.getUserActivity());
|
||||
// store hooks
|
||||
const { currentUser } = useUser();
|
||||
const { theme: themeStore } = useApplication();
|
||||
|
||||
return (
|
||||
<section className="mx-auto mt-5 md:mt-16 flex h-full w-full flex-col overflow-hidden px-8 pb-8 lg:w-3/5">
|
||||
<div className="flex items-center border-b border-custom-border-100 gap-4 pb-3.5">
|
||||
<SidebarHamburgerToggle />
|
||||
<SidebarHamburgerToggle onClick={() => themeStore.toggleSidebar()} />
|
||||
<h3 className="text-xl font-medium">Activity</h3>
|
||||
</div>
|
||||
{userActivity ? (
|
||||
|
@ -3,7 +3,7 @@ import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
// hooks
|
||||
import { useUser } from "hooks/store";
|
||||
import { useApplication, useUser } from "hooks/store";
|
||||
// services
|
||||
import { UserService } from "services/user.service";
|
||||
// hooks
|
||||
@ -32,7 +32,8 @@ const userService = new UserService();
|
||||
|
||||
const ChangePasswordPage: NextPageWithLayout = observer(() => {
|
||||
const [isPageLoading, setIsPageLoading] = useState(true);
|
||||
|
||||
// hooks
|
||||
const { theme: themeStore } = useApplication();
|
||||
const { currentUser } = useUser();
|
||||
|
||||
const router = useRouter();
|
||||
@ -89,7 +90,7 @@ const ChangePasswordPage: NextPageWithLayout = observer(() => {
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="block md:hidden flex-shrink-0 border-b border-custom-border-200 p-4">
|
||||
<SidebarHamburgerToggle />
|
||||
<SidebarHamburgerToggle onClick={() => themeStore.toggleSidebar()} />
|
||||
</div>
|
||||
<form
|
||||
onSubmit={handleSubmit(handleChangePassword)}
|
||||
|
@ -5,7 +5,7 @@ import { observer } from "mobx-react-lite";
|
||||
// services
|
||||
import { FileService } from "services/file.service";
|
||||
// hooks
|
||||
import { useUser } from "hooks/store";
|
||||
import { useApplication, useUser } from "hooks/store";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
import useToast from "hooks/use-toast";
|
||||
// layouts
|
||||
@ -58,6 +58,7 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
|
||||
const { currentUser: myProfile, updateCurrentUser, currentUserLoader } = useUser();
|
||||
// custom hooks
|
||||
const { } = useUserAuth({ user: myProfile, isLoading: currentUserLoader });
|
||||
const { theme: themeStore } = useApplication();
|
||||
|
||||
useEffect(() => {
|
||||
reset({ ...defaultValues, ...myProfile });
|
||||
@ -139,7 +140,7 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
|
||||
<>
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="block md:hidden flex-shrink-0 border-b border-custom-border-200 p-4">
|
||||
<SidebarHamburgerToggle />
|
||||
<SidebarHamburgerToggle onClick={() => themeStore.toggleSidebar()} />
|
||||
</div>
|
||||
<div className="overflow-hidden">
|
||||
<Controller
|
||||
|
Loading…
Reference in New Issue
Block a user