[WEB-713] style: remove tooltips in mobile responsiveness (#3948)

Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
Ramesh Kumar Chandra 2024-03-12 20:39:36 +05:30 committed by GitHub
parent b930d98665
commit cb632408f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
70 changed files with 327 additions and 147 deletions

View File

@ -29,6 +29,7 @@ interface ITooltipProps {
className?: string;
openDelay?: number;
closeDelay?: number;
isMobile?: boolean;
}
export const Tooltip: React.FC<ITooltipProps> = ({
@ -40,6 +41,7 @@ export const Tooltip: React.FC<ITooltipProps> = ({
className = "",
openDelay = 200,
closeDelay,
isMobile = false,
}) => (
<Tooltip2
disabled={disabled}
@ -47,7 +49,7 @@ export const Tooltip: React.FC<ITooltipProps> = ({
hoverCloseDelay={closeDelay}
content={
<div
className={`relative z-50 max-w-xs gap-1 overflow-hidden break-words rounded-md bg-custom-background-100 p-2 text-xs text-custom-text-200 shadow-md ${className}`}
className={`relative ${isMobile ? "hidden" : "block"} z-50 max-w-xs gap-1 overflow-hidden break-words rounded-md bg-custom-background-100 p-2 text-xs text-custom-text-200 shadow-md ${className}`}
>
{tooltipHeading && <h5 className="font-medium text-custom-text-100">{tooltipHeading}</h5>}
{tooltipContent}

View File

@ -6,6 +6,8 @@ import { renderFormattedDate } from "helpers/date-time.helper";
import { copyTextToClipboard } from "helpers/string.helper";
// types
import { IApiToken } from "@plane/types";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
type Props = {
handleClose: () => void;
@ -14,7 +16,7 @@ type Props = {
export const GeneratedTokenDetails: React.FC<Props> = (props) => {
const { handleClose, tokenDetails } = props;
const { isMobile } = usePlatformOS();
const copyApiToken = (token: string) => {
copyTextToClipboard(token).then(() =>
setToast({
@ -40,7 +42,7 @@ export const GeneratedTokenDetails: React.FC<Props> = (props) => {
className="mt-4 flex w-full items-center justify-between rounded-md border-[0.5px] border-custom-border-200 px-3 py-2 text-sm font-medium outline-none"
>
{tokenDetails.token}
<Tooltip tooltipContent="Copy secret key">
<Tooltip tooltipContent="Copy secret key" isMobile={isMobile}>
<Copy className="h-4 w-4 text-custom-text-400" />
</Tooltip>
</button>

View File

@ -3,6 +3,7 @@ import { XCircle } from "lucide-react";
// components
import { Tooltip } from "@plane/ui";
import { DeleteApiTokenModal } from "components/api-token";
import { usePlatformOS } from "hooks/use-platform-os";
// ui
// helpers
import { renderFormattedDate, calculateTimeAgo } from "helpers/date-time.helper";
@ -17,12 +18,14 @@ export const ApiTokenListItem: React.FC<Props> = (props) => {
const { token } = props;
// states
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
// hooks
const { isMobile } = usePlatformOS();
return (
<>
<DeleteApiTokenModal isOpen={deleteModalOpen} onClose={() => setDeleteModalOpen(false)} tokenId={token.id} />
<div className="group relative flex flex-col justify-center border-b border-custom-border-200 px-4 py-3">
<Tooltip tooltipContent="Delete token">
<Tooltip tooltipContent="Delete token" isMobile={isMobile}>
<button
onClick={() => setDeleteModalOpen(true)}
className="absolute right-4 hidden place-items-center group-hover:grid"
@ -33,9 +36,8 @@ export const ApiTokenListItem: React.FC<Props> = (props) => {
<div className="flex w-4/5 items-center">
<h5 className="truncate text-sm font-medium">{token.label}</h5>
<span
className={`${
token.is_active ? "bg-green-500/10 text-green-500" : "bg-custom-background-80 text-custom-text-400"
} ml-2 flex h-4 max-h-fit items-center rounded-sm px-2 text-xs font-medium`}
className={`${token.is_active ? "bg-green-500/10 text-green-500" : "bg-custom-background-80 text-custom-text-400"
} ml-2 flex h-4 max-h-fit items-center rounded-sm px-2 text-xs font-medium`}
>
{token.is_active ? "Active" : "Expired"}
</span>

View File

@ -20,12 +20,11 @@ import {
} from "components/command-palette";
import { ISSUE_DETAILS } from "constants/fetch-keys";
import { useApplication, useEventTracker, useProject } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// services
import useDebounce from "hooks/use-debounce";
import { IssueService } from "services/issue";
import { WorkspaceService } from "services/workspace.service";
// hooks
// components
// types
import { IWorkspaceSearchResults } from "@plane/types";
// fetch-keys
@ -37,6 +36,7 @@ const issueService = new IssueService();
export const CommandModal: React.FC = observer(() => {
// hooks
const { getProjectById } = useProject();
const { isMobile } = usePlatformOS();
// states
const [placeholder, setPlaceholder] = useState("Type a command or search...");
const [resultsCount, setResultsCount] = useState(0);
@ -197,7 +197,7 @@ export const CommandModal: React.FC = observer(() => {
</div>
)}
{projectId && (
<Tooltip tooltipContent="Toggle workspace level search">
<Tooltip tooltipContent="Toggle workspace level search" isMobile={isMobile}>
<div className="flex flex-shrink-0 cursor-pointer items-center gap-1 self-end text-xs sm:self-center">
<button
type="button"

View File

@ -1,5 +1,6 @@
import Link from "next/link";
import { Tooltip } from "@plane/ui";
import { usePlatformOS } from "hooks/use-platform-os";
type Props = {
label?: string;
@ -9,8 +10,9 @@ type Props = {
export const BreadcrumbLink: React.FC<Props> = (props) => {
const { href, label, icon } = props;
const { isMobile } = usePlatformOS();
return (
<Tooltip tooltipContent={label} position="bottom">
<Tooltip tooltipContent={label} position="bottom" isMobile={isMobile}>
<li className="flex items-center space-x-2" tabIndex={-1}>
<div className="flex flex-wrap items-center gap-2.5">
{href ? (

View File

@ -1,6 +1,7 @@
import { useEffect } from "react";
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import { usePlatformOS } from "hooks/use-platform-os";
// store hooks
// icons
import {
@ -29,9 +30,13 @@ import { IIssueActivity } from "@plane/types";
export const IssueLink = ({ activity }: { activity: IIssueActivity }) => {
const router = useRouter();
const { workspaceSlug } = router.query;
const { isMobile } = usePlatformOS();
return (
<Tooltip tooltipContent={activity?.issue_detail ? activity.issue_detail.name : "This issue has been deleted"}>
<Tooltip
tooltipContent={activity?.issue_detail ? activity.issue_detail.name : "This issue has been deleted"}
isMobile={isMobile}
>
{activity?.issue_detail ? (
<a
aria-disabled={activity.issue === null}

View File

@ -5,7 +5,7 @@ import { Rocket, Search, X } from "lucide-react";
import { Button, LayersIcon, Loader, ToggleSwitch, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
import useDebounce from "hooks/use-debounce";
import { usePlatformOS } from "hooks/use-platform-os";
import { ProjectService } from "services/project";
// ui
// types
@ -40,7 +40,7 @@ export const ExistingIssuesListModal: React.FC<Props> = (props) => {
const [isSearching, setIsSearching] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [isWorkspaceLevel, setIsWorkspaceLevel] = useState(false);
const { isMobile } = usePlatformOS();
const debouncedSearchTerm: string = useDebounce(searchTerm, 500);
const handleClose = () => {
@ -154,7 +154,7 @@ export const ExistingIssuesListModal: React.FC<Props> = (props) => {
</div>
)}
{workspaceLevelToggle && (
<Tooltip tooltipContent="Toggle workspace level search">
<Tooltip tooltipContent="Toggle workspace level search" isMobile={isMobile}>
<div
className={`flex flex-shrink-0 cursor-pointer items-center gap-1 text-xs ${
isWorkspaceLevel ? "text-custom-text-100" : "text-custom-text-200"

View File

@ -7,6 +7,7 @@ import { ExternalLinkIcon, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
import { calculateTimeAgo } from "helpers/date-time.helper";
// hooks
import { useMember } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// types
import { ILinkDetails, UserAuth } from "@plane/types";
@ -19,7 +20,7 @@ type Props = {
export const LinksList: React.FC<Props> = observer(({ links, handleDeleteLink, handleEditLink, userAuth }) => {
const { getUserDetails } = useMember();
const { isMobile } = usePlatformOS();
const isNotAllowed = userAuth.isGuest || userAuth.isViewer;
const copyToClipboard = (text: string) => {
@ -42,7 +43,7 @@ export const LinksList: React.FC<Props> = observer(({ links, handleDeleteLink, h
<span className="py-1">
<LinkIcon className="h-3 w-3 flex-shrink-0" />
</span>
<Tooltip tooltipContent={link.title && link.title !== "" ? link.title : link.url}>
<Tooltip tooltipContent={link.title && link.title !== "" ? link.title : link.url} isMobile={isMobile}>
<span
className="cursor-pointer truncate text-xs"
onClick={() => copyToClipboard(link.title && link.title !== "" ? link.title : link.url)}

View File

@ -4,6 +4,7 @@ import Link from "next/link";
import useSWR from "swr";
// hooks
import { useCycle, useCycleFilter, useIssues, useMember, useProject } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// ui
import { SingleProgressStats } from "components/core";
import {
@ -46,6 +47,8 @@ interface IActiveCycleDetails {
export const ActiveCycleRoot: React.FC<IActiveCycleDetails> = observer((props) => {
// props
const { workspaceSlug, projectId } = props;
// hooks
const { isMobile } = usePlatformOS();
// store hooks
const {
issues: { fetchActiveCycleIssues },
@ -197,7 +200,7 @@ export const ActiveCycleRoot: React.FC<IActiveCycleDetails> = observer((props) =
<span className="h-5 w-5">
<CycleGroupIcon cycleGroup={cycleStatus} className="h-4 w-4" />
</span>
<Tooltip tooltipContent={activeCycle.name} position="top-left">
<Tooltip tooltipContent={activeCycle.name} position="top-left" isMobile={isMobile}>
<h3 className="break-words text-lg font-semibold">{truncateText(activeCycle.name, 70)}</h3>
</Tooltip>
</span>
@ -325,6 +328,7 @@ export const ActiveCycleRoot: React.FC<IActiveCycleDetails> = observer((props) =
<PriorityIcon priority={issue.priority} withContainer size={12} />
<Tooltip
isMobile={isMobile}
tooltipHeading="Issue ID"
tooltipContent={`${currentProjectDetails?.identifier}-${issue.sequence_id}`}
>
@ -332,7 +336,7 @@ export const ActiveCycleRoot: React.FC<IActiveCycleDetails> = observer((props) =
{currentProjectDetails?.identifier}-{issue.sequence_id}
</span>
</Tooltip>
<Tooltip position="top-left" tooltipContent={issue.name}>
<Tooltip position="top-left" tooltipContent={issue.name} isMobile={isMobile}>
<span className="text-[0.825rem] text-custom-text-100">{truncateText(issue.name, 30)}</span>
</Tooltip>
</div>
@ -345,7 +349,7 @@ export const ActiveCycleRoot: React.FC<IActiveCycleDetails> = observer((props) =
buttonVariant="background-with-text"
/>
{issue.target_date && (
<Tooltip tooltipHeading="Target Date" tooltipContent={renderFormattedDate(issue.target_date)}>
<Tooltip tooltipHeading="Target Date" tooltipContent={renderFormattedDate(issue.target_date)} isMobile={isMobile}>
<div className="flex h-full cursor-not-allowed items-center gap-1.5 rounded bg-custom-background-80 px-2 py-0.5 text-xs">
<CalendarCheck className="h-3 w-3 flex-shrink-0" />
<span className="text-xs">{renderFormattedDateWithoutYear(issue.target_date)}</span>

View File

@ -3,6 +3,7 @@ import { observer } from "mobx-react";
import Link from "next/link";
import { useRouter } from "next/router";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// components
import { Info, Star } from "lucide-react";
import { Avatar, AvatarGroup, Tooltip, LayersIcon, CycleGroupIcon, setPromiseToast } from "@plane/ui";
@ -38,6 +39,8 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = observer((props) => {
const { getUserDetails } = useMember();
// computed
const cycleDetails = getCycleById(cycleId);
// hooks
const { isMobile } = usePlatformOS();
if (!cycleDetails) return null;
@ -145,7 +148,7 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = observer((props) => {
<span className="flex-shrink-0">
<CycleGroupIcon cycleGroup={cycleStatus as TCycleGroups} className="h-3.5 w-3.5" />
</span>
<Tooltip tooltipContent={cycleDetails.name} position="top">
<Tooltip tooltipContent={cycleDetails.name} position="top" isMobile={isMobile}>
<span className="truncate text-base font-medium">{cycleDetails.name}</span>
</Tooltip>
</div>
@ -176,7 +179,7 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = observer((props) => {
<span className="text-xs text-custom-text-300">{issueCount}</span>
</div>
{cycleDetails.assignee_ids.length > 0 && (
<Tooltip tooltipContent={`${cycleDetails.assignee_ids.length} Members`}>
<Tooltip tooltipContent={`${cycleDetails.assignee_ids.length} Members`} isMobile={isMobile}>
<div className="flex cursor-default items-center gap-1">
<AvatarGroup showTooltip={false}>
{cycleDetails.assignee_ids.map((assigne_id) => {
@ -190,6 +193,7 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = observer((props) => {
</div>
<Tooltip
isMobile={isMobile}
tooltipContent={isNaN(completionPercentage) ? "0" : `${completionPercentage.toFixed(0)}%`}
position="top-left"
>

View File

@ -5,6 +5,7 @@ import { ListFilter, Search, X } from "lucide-react";
// hooks
import { useCycleFilter } from "hooks/store";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
import { usePlatformOS } from "hooks/use-platform-os";
// components
import { CycleFiltersSelection } from "components/cycles";
import { FiltersDropdown } from "components/issues";
@ -36,6 +37,7 @@ export const CyclesViewHeader: React.FC<Props> = observer((props) => {
updateFilters,
updateSearchQuery,
} = useCycleFilter();
const { isMobile } = usePlatformOS();
// outside click detector hook
useOutsideClickDetector(inputRef, () => {
if (isSearchOpen && searchQuery.trim() === "") setIsSearchOpen(false);
@ -134,7 +136,7 @@ export const CyclesViewHeader: React.FC<Props> = observer((props) => {
</FiltersDropdown>
<div className="flex items-center gap-1 rounded bg-custom-background-80 p-1">
{CYCLE_VIEW_LAYOUTS.map((layout) => (
<Tooltip key={layout.key} tooltipContent={layout.title}>
<Tooltip key={layout.key} tooltipContent={layout.title} isMobile={isMobile}>
<button
type="button"
className={`group grid h-[22px] w-7 place-items-center overflow-hidden rounded transition-all hover:bg-custom-background-100 ${

View File

@ -2,6 +2,7 @@ import Link from "next/link";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// ui
import { Tooltip, ContrastIcon } from "@plane/ui";
// helpers
@ -23,7 +24,7 @@ export const CycleGanttBlock: React.FC<Props> = observer((props) => {
const { getCycleById } = useCycle();
// derived values
const cycleDetails = getCycleById(cycleId);
const { isMobile } = usePlatformOS();
const cycleStatus = cycleDetails?.status.toLocaleLowerCase();
return (
@ -45,6 +46,7 @@ export const CycleGanttBlock: React.FC<Props> = observer((props) => {
>
<div className="absolute left-0 top-0 h-full w-full bg-custom-background-100/50" />
<Tooltip
isMobile={isMobile}
tooltipContent={
<div className="space-y-1">
<h5>{cycleDetails?.name}</h5>

View File

@ -3,6 +3,7 @@ import { observer } from "mobx-react";
import Link from "next/link";
import { useRouter } from "next/router";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
import { Check, Info, Star, User2 } from "lucide-react";
import { Tooltip, CircularProgressIndicator, CycleGroupIcon, AvatarGroup, Avatar, setPromiseToast } from "@plane/ui";
import { CycleQuickActions } from "components/cycles";
@ -33,6 +34,8 @@ export const CyclesListItem: FC<TCyclesListItem> = observer((props) => {
const { cycleId, workspaceSlug, projectId } = props;
// router
const router = useRouter();
// hooks
const { isMobile } = usePlatformOS();
// store hooks
const { captureEvent } = useEventTracker();
const {
@ -164,7 +167,7 @@ export const CyclesListItem: FC<TCyclesListItem> = observer((props) => {
<div className="relative flex items-center gap-2.5 overflow-hidden">
<CycleGroupIcon cycleGroup={cycleStatus} className="h-3.5 w-3.5 flex-shrink-0" />
<Tooltip tooltipContent={cycleDetails.name} position="top">
<Tooltip tooltipContent={cycleDetails.name} position="top" isMobile={isMobile}>
<span className="line-clamp-1 inline-block overflow-hidden truncate text-base font-medium">
{cycleDetails.name}
</span>
@ -196,7 +199,7 @@ export const CyclesListItem: FC<TCyclesListItem> = observer((props) => {
</div>
<div className="relative flex flex-shrink-0 items-center gap-3">
<Tooltip tooltipContent={`${cycleDetails.assignee_ids?.length} Members`}>
<Tooltip tooltipContent={`${cycleDetails.assignee_ids?.length} Members`} isMobile={isMobile}>
<div className="flex w-10 cursor-default items-center justify-center">
{cycleDetails.assignee_ids?.length > 0 ? (
<AvatarGroup showTooltip={false}>

View File

@ -4,7 +4,7 @@ import { cn } from "helpers/common.helper";
// types
import { BACKGROUND_BUTTON_VARIANTS, BORDER_BUTTON_VARIANTS } from "./constants";
import { TButtonVariants } from "./types";
// constants
import { usePlatformOS } from "hooks/use-platform-os";
export type DropdownButtonProps = {
children: React.ReactNode;
@ -27,7 +27,6 @@ type ButtonProps = {
export const DropdownButton: React.FC<DropdownButtonProps> = (props) => {
const { children, className, isActive, tooltipContent, tooltipHeading, showTooltip, variant } = props;
const ButtonToRender: React.FC<ButtonProps> = BORDER_BUTTON_VARIANTS.includes(variant)
? BorderButton
: BACKGROUND_BUTTON_VARIANTS.includes(variant)
@ -49,9 +48,10 @@ export const DropdownButton: React.FC<DropdownButtonProps> = (props) => {
const BorderButton: React.FC<ButtonProps> = (props) => {
const { children, className, isActive, tooltipContent, tooltipHeading, showTooltip } = props;
const { isMobile } = usePlatformOS();
return (
<Tooltip tooltipHeading={tooltipHeading} tooltipContent={tooltipContent} disabled={!showTooltip}>
<Tooltip tooltipHeading={tooltipHeading} tooltipContent={tooltipContent} disabled={!showTooltip} isMobile={isMobile}>
<div
className={cn(
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
@ -67,9 +67,9 @@ const BorderButton: React.FC<ButtonProps> = (props) => {
const BackgroundButton: React.FC<ButtonProps> = (props) => {
const { children, className, tooltipContent, tooltipHeading, showTooltip } = props;
const { isMobile } = usePlatformOS();
return (
<Tooltip tooltipHeading={tooltipHeading} tooltipContent={tooltipContent} disabled={!showTooltip}>
<Tooltip tooltipHeading={tooltipHeading} tooltipContent={tooltipContent} disabled={!showTooltip} isMobile={isMobile}>
<div
className={cn(
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80",
@ -84,9 +84,9 @@ const BackgroundButton: React.FC<ButtonProps> = (props) => {
const TransparentButton: React.FC<ButtonProps> = (props) => {
const { children, className, isActive, tooltipContent, tooltipHeading, showTooltip } = props;
const { isMobile } = usePlatformOS();
return (
<Tooltip tooltipHeading={tooltipHeading} tooltipContent={tooltipContent} disabled={!showTooltip}>
<Tooltip tooltipHeading={tooltipHeading} tooltipContent={tooltipContent} disabled={!showTooltip} isMobile={isMobile}>
<div
className={cn(
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",

View File

@ -8,6 +8,7 @@ import { cn } from "helpers/common.helper";
import { useModule } from "hooks/store";
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
import { usePlatformOS } from "hooks/use-platform-os";
// components
import { DropdownButton } from "../buttons";
// icons
@ -66,6 +67,7 @@ const ButtonContent: React.FC<ButtonContentProps> = (props) => {
} = props;
// store hooks
const { getModuleById } = useModule();
const { isMobile } = usePlatformOS();
if (Array.isArray(value))
return (
@ -92,12 +94,12 @@ const ButtonContent: React.FC<ButtonContentProps> = (props) => {
>
{!hideIcon && <DiceIcon className="h-2.5 w-2.5 flex-shrink-0" />}
{!hideText && (
<Tooltip tooltipHeading="Title" tooltipContent={moduleDetails?.name} disabled={!showTooltip}>
<Tooltip tooltipHeading="Title" tooltipContent={moduleDetails?.name} disabled={!showTooltip} isMobile={isMobile}>
<span className="max-w-40 flex-grow truncate text-xs font-medium">{moduleDetails?.name}</span>
</Tooltip>
)}
{!disabled && (
<Tooltip tooltipContent="Remove" disabled={!showTooltip}>
<Tooltip tooltipContent="Remove" disabled={!showTooltip} isMobile={isMobile}>
<button
type="button"
className="flex-shrink-0"

View File

@ -9,6 +9,7 @@ import { ISSUE_PRIORITIES } from "constants/issue";
import { cn } from "helpers/common.helper";
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
import { usePlatformOS } from "hooks/use-platform-os";
// icons
// helpers
// types
@ -61,8 +62,10 @@ const BorderButton = (props: ButtonProps) => {
none: "hover:bg-custom-background-80 border-custom-border-300",
};
const { isMobile } = usePlatformOS();
return (
<Tooltip tooltipHeading="Priority" tooltipContent={priorityDetails?.title ?? "None"} disabled={!showTooltip}>
<Tooltip tooltipHeading="Priority" tooltipContent={priorityDetails?.title ?? "None"} disabled={!showTooltip} isMobile={isMobile}>
<div
className={cn(
"h-full flex items-center gap-1.5 border-[0.5px] rounded text-xs px-2 py-0.5",
@ -130,8 +133,10 @@ const BackgroundButton = (props: ButtonProps) => {
none: "bg-custom-background-80",
};
const { isMobile } = usePlatformOS();
return (
<Tooltip tooltipHeading="Priority" tooltipContent={priorityDetails?.title ?? "None"} disabled={!showTooltip}>
<Tooltip tooltipHeading="Priority" tooltipContent={priorityDetails?.title ?? "None"} disabled={!showTooltip} isMobile={isMobile}>
<div
className={cn(
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5",
@ -200,8 +205,10 @@ const TransparentButton = (props: ButtonProps) => {
none: "hover:text-custom-text-300",
};
const { isMobile } = usePlatformOS();
return (
<Tooltip tooltipHeading="Priority" tooltipContent={priorityDetails?.title ?? "None"} disabled={!showTooltip}>
<Tooltip tooltipHeading="Priority" tooltipContent={priorityDetails?.title ?? "None"} disabled={!showTooltip} isMobile={isMobile}>
<div
className={cn(
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",

View File

@ -9,6 +9,8 @@ import { renderFormattedDate, renderFormattedPayloadDate } from "helpers/date-ti
// types
import { useGanttChart } from "../hooks/use-gantt-chart";
import { IBlockUpdateData, IGanttBlock } from "../types";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
type Props = {
block: IGanttBlock;
@ -23,6 +25,8 @@ export const ChartAddBlock: React.FC<Props> = observer((props) => {
const [buttonStartDate, setButtonStartDate] = useState<Date | null>(null);
// refs
const containerRef = useRef<HTMLDivElement>(null);
// hooks
const { isMobile } = usePlatformOS();
// chart hook
const { currentViewData } = useGanttChart();
@ -73,7 +77,7 @@ export const ChartAddBlock: React.FC<Props> = observer((props) => {
>
<div ref={containerRef} className="h-full w-full" />
{isButtonVisible && (
<Tooltip tooltipContent={buttonStartDate && renderFormattedDate(buttonStartDate)}>
<Tooltip tooltipContent={buttonStartDate && renderFormattedDate(buttonStartDate)} isMobile={isMobile}>
<button
type="button"
className="absolute top-1/2 -translate-x-1/2 -translate-y-1/2 h-8 w-8 bg-custom-background-80 p-1.5 rounded border border-custom-border-300 grid place-items-center text-custom-text-200 hover:text-custom-text-100"

View File

@ -3,6 +3,8 @@ import { observer } from "mobx-react-lite";
import Link from "next/link";
import { useRouter } from "next/router";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// components
import { ArrowRight, Plus, PanelRight } from "lucide-react";
import { Breadcrumbs, Button, ContrastIcon, CustomMenu, Tooltip } from "@plane/ui";
import { ProjectAnalyticsModal } from "components/analytics";
@ -26,7 +28,6 @@ import {
useIssues,
} from "hooks/store";
import useLocalStorage from "hooks/use-local-storage";
// components
// ui
// icons
// helpers
@ -43,6 +44,7 @@ const CycleDropdownOption: React.FC<{ cycleId: string }> = ({ cycleId }) => {
const { getCycleById } = useCycle();
// derived values
const cycle = getCycleById(cycleId);
//
if (!cycle) return null;
@ -84,6 +86,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
const {
project: { projectMemberIds },
} = useMember();
const { isMobile } = usePlatformOS()
const activeLayout = issueFilters?.displayFilters?.layout;
@ -207,6 +210,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
<p className="truncate">{cycleDetails?.name && cycleDetails.name}</p>
{issueCount && issueCount > 0 ? (
<Tooltip
isMobile={isMobile}
tooltipContent={`There are ${issueCount} ${
issueCount > 1 ? "issues" : "issue"
} in this cycle`}

View File

@ -3,6 +3,7 @@ import { observer } from "mobx-react-lite";
import Link from "next/link";
import { useRouter } from "next/router";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
import { List, PlusIcon, Sheet } from "lucide-react";
import { Breadcrumbs, Button, LayersIcon, PhotoFilterIcon, Tooltip } from "@plane/ui";
import { BreadcrumbLink } from "components/common";
@ -46,6 +47,7 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
const {
workspace: { workspaceMemberIds },
} = useMember();
const { isMobile } = usePlatformOS();
const issueFilters = globalViewId ? filters[globalViewId.toString()] : undefined;
@ -133,7 +135,7 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
{GLOBAL_VIEW_LAYOUTS.map((layout) => (
<Link key={layout.key} href={`/${workspaceSlug}/${layout.link}`}>
<span>
<Tooltip tooltipContent={layout.title}>
<Tooltip tooltipContent={layout.title} isMobile={isMobile}>
<div
className={`group grid h-[22px] w-7 place-items-center overflow-hidden rounded transition-all hover:bg-custom-background-100 ${
activeLayout === layout.key ? "bg-custom-background-100 shadow-custom-shadow-2xs" : ""

View File

@ -3,6 +3,7 @@ import { observer } from "mobx-react-lite";
import Link from "next/link";
import { useRouter } from "next/router";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
import { ArrowRight, PanelRight, Plus } from "lucide-react";
import { Breadcrumbs, Button, CustomMenu, DiceIcon, Tooltip } from "@plane/ui";
import { ProjectAnalyticsModal } from "components/analytics";
@ -66,6 +67,8 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId, moduleId } = router.query;
// hooks
const { isMobile } = usePlatformOS();
// store hooks
const {
issuesFilter: { issueFilters },
@ -208,6 +211,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
<p className="truncate">{moduleDetails?.name && moduleDetails.name}</p>
{issueCount && issueCount > 0 ? (
<Tooltip
isMobile={isMobile}
tooltipContent={`There are ${issueCount} ${
issueCount > 1 ? "issues" : "issue"
} in this module`}

View File

@ -9,6 +9,11 @@ import useOutsideClickDetector from "hooks/use-outside-click-detector";
import { BreadcrumbLink } from "components/common";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
import { ProjectLogo } from "components/project";
// constants
import { MODULE_VIEW_LAYOUTS } from "constants/module";
import { EUserProjectRoles } from "constants/project";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
import { ModuleFiltersSelection, ModuleOrderByDropdown } from "components/modules";
import { FiltersDropdown } from "components/issues";
// ui
@ -17,9 +22,6 @@ import { Breadcrumbs, Button, Tooltip, DiceIcon, CustomMenu } from "@plane/ui";
import { cn } from "helpers/common.helper";
// types
import { TModuleFilters } from "@plane/types";
// constants
import { MODULE_VIEW_LAYOUTS } from "constants/module";
import { EUserProjectRoles } from "constants/project";
export const ModulesListHeader: React.FC = observer(() => {
// states
@ -36,6 +38,7 @@ export const ModulesListHeader: React.FC = observer(() => {
membership: { currentProjectRole },
} = useUser();
const { currentProjectDetails } = useProject();
const { isMobile } = usePlatformOS();
const {
workspace: { workspaceMemberIds },
} = useMember();
@ -162,7 +165,7 @@ export const ModulesListHeader: React.FC = observer(() => {
</div>
<div className="hidden md:flex items-center gap-1 rounded bg-custom-background-80 p-1">
{MODULE_VIEW_LAYOUTS.map((layout) => (
<Tooltip key={layout.key} tooltipContent={layout.title}>
<Tooltip key={layout.key} tooltipContent={layout.title} isMobile={isMobile}>
<button
type="button"
className={cn(

View File

@ -3,6 +3,7 @@ import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import { ArrowLeft } from "lucide-react";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// constants
// ui
import { Breadcrumbs, LayersIcon, Tooltip } from "@plane/ui";
@ -31,10 +32,10 @@ export const ProjectArchivedIssuesHeader: FC = observer(() => {
const {
project: { projectMemberIds },
} = useMember();
// for archived issues list layout is the only option
const activeLayout = "list";
// hooks
const { isMobile } = usePlatformOS();
const handleFiltersUpdate = (key: keyof IIssueFilterOptions, value: string | string[]) => {
if (!workspaceSlug || !projectId) return;
@ -119,6 +120,7 @@ export const ProjectArchivedIssuesHeader: FC = observer(() => {
</Breadcrumbs>
{issueCount && issueCount > 0 ? (
<Tooltip
isMobile={isMobile}
tooltipContent={`There are ${issueCount} ${issueCount > 1 ? "issues" : "issue"} in project's archived`}
position="bottom"
>

View File

@ -2,6 +2,7 @@ import { FC, useCallback } from "react";
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// components
import { Breadcrumbs, LayersIcon, Tooltip } from "@plane/ui";
import { BreadcrumbLink } from "components/common";
@ -28,7 +29,7 @@ export const ProjectDraftIssueHeader: FC = observer(() => {
const {
project: { projectMemberIds },
} = useMember();
const { isMobile } = usePlatformOS();
const activeLayout = issueFilters?.displayFilters?.layout;
const handleFiltersUpdate = useCallback(
@ -112,6 +113,7 @@ export const ProjectDraftIssueHeader: FC = observer(() => {
</Breadcrumbs>
{issueCount && issueCount > 0 ? (
<Tooltip
isMobile={isMobile}
tooltipContent={`There are ${issueCount} ${issueCount > 1 ? "issues" : "issue"} in project's draft`}
position="bottom"
>

View File

@ -3,6 +3,7 @@ import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import { Briefcase, Circle, ExternalLink, Plus } from "lucide-react";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
import { Breadcrumbs, Button, LayersIcon, Tooltip } from "@plane/ui";
import { ProjectAnalyticsModal } from "components/analytics";
import { BreadcrumbLink } from "components/common";
@ -52,7 +53,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
const { currentProjectDetails } = useProject();
const { projectStates } = useProjectState();
const { projectLabels } = useLabel();
const { isMobile } = usePlatformOS();
const activeLayout = issueFilters?.displayFilters?.layout;
const handleFiltersUpdate = useCallback(
@ -153,6 +154,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
</Breadcrumbs>
{issueCount && issueCount > 0 ? (
<Tooltip
isMobile={isMobile}
tooltipContent={`There are ${issueCount} ${issueCount > 1 ? "issues" : "issue"} in this project`}
position="bottom"
>

View File

@ -5,6 +5,7 @@ import { useRouter } from "next/router";
// icons
import { CalendarDays } from "lucide-react";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// ui
import { Tooltip, PriorityIcon } from "@plane/ui";
// helpers
@ -33,7 +34,7 @@ export const InboxIssueListItem: FC<TInboxIssueListItem> = observer((props) => {
const {
issue: { getIssueById },
} = useIssueDetail();
const { isMobile } = usePlatformOS();
const inboxIssueDetail = getInboxIssueByIssueId(inboxId, issueId);
const issue = getIssueById(issueId);
@ -83,10 +84,10 @@ export const InboxIssueListItem: FC<TInboxIssueListItem> = observer((props) => {
</div>
<div className="flex flex-wrap items-center gap-2">
<Tooltip tooltipHeading="Priority" tooltipContent={`${issue.priority ?? "None"}`}>
<Tooltip tooltipHeading="Priority" tooltipContent={`${issue.priority ?? "None"}`} isMobile={isMobile}>
<PriorityIcon priority={issue.priority ?? null} className="h-3.5 w-3.5" />
</Tooltip>
<Tooltip tooltipHeading="Created on" tooltipContent={`${renderFormattedDate(issue.created_at ?? "")}`}>
<Tooltip tooltipHeading="Created on" tooltipContent={`${renderFormattedDate(issue.created_at ?? "")}`} isMobile={isMobile}>
<div className="flex items-center gap-1 rounded border border-custom-border-200 px-2 py-[0.19rem] text-xs text-custom-text-200 shadow-sm">
<CalendarDays size={12} strokeWidth={1.5} />
<span>{renderFormattedDate(issue.created_at ?? "")}</span>

View File

@ -9,6 +9,7 @@ import { Menu, Transition } from "@headlessui/react";
// icons
import { LogIn, LogOut, Settings, UserCog2 } from "lucide-react";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
import { Avatar, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
import { useApplication, useUser } from "hooks/store";
// ui
@ -34,7 +35,7 @@ export const InstanceSidebarDropdown = observer(() => {
const { signOut, currentUser, currentUserSettings } = useUser();
// hooks
const { setTheme } = useTheme();
const { isMobile } = usePlatformOS();
// redirect url for normal mode
const redirectWorkspaceSlug =
workspaceSlug ||
@ -73,7 +74,7 @@ export const InstanceSidebarDropdown = observer(() => {
{!sidebarCollapsed && (
<div className="flex w-full gap-2">
<h4 className="grow truncate text-base font-medium text-custom-text-200">Instance admin</h4>
<Tooltip position="bottom-left" tooltipContent="Exit God Mode">
<Tooltip position="bottom-left" tooltipContent="Exit God Mode" isMobile={isMobile}>
<div className="flex-shrink-0">
<Link href={`/${redirectWorkspaceSlug}`}>
<span>

View File

@ -2,6 +2,7 @@ import Link from "next/link";
import { useRouter } from "next/router";
import { Image, BrainCog, Cog, Lock, Mail } from "lucide-react";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
import { Tooltip } from "@plane/ui";
import { useApplication } from "hooks/store";
// ui
@ -46,6 +47,7 @@ export const InstanceAdminSidebarMenu = () => {
} = useApplication();
// router
const router = useRouter();
const { isMobile } = usePlatformOS();
return (
<div className="flex h-full w-full flex-col gap-2.5 overflow-y-auto px-4 py-6">
@ -55,7 +57,7 @@ export const InstanceAdminSidebarMenu = () => {
return (
<Link key={index} href={item.href}>
<div>
<Tooltip tooltipContent={item.name} position="right" className="ml-2" disabled={!sidebarCollapsed}>
<Tooltip tooltipContent={item.name} position="right" className="ml-2" disabled={!sidebarCollapsed} isMobile={isMobile}>
<div
className={`group flex w-full items-center gap-3 rounded-md px-3 py-2 outline-none ${
isActive

View File

@ -11,6 +11,7 @@ import { WORKSPACE_INTEGRATIONS } from "constants/fetch-keys";
// hooks
import { useApplication, useUser } from "hooks/store";
import useIntegrationPopup from "hooks/use-integration-popup";
import { usePlatformOS } from "hooks/use-platform-os";
// services
import { IntegrationService } from "services/integrations";
// icons
@ -55,7 +56,7 @@ export const SingleIntegrationCard: React.FC<Props> = observer(({ integration })
} = useUser();
const isUserAdmin = currentWorkspaceRole === 20;
const { isMobile } = usePlatformOS();
const { startAuth, isConnecting: isInstalling } = useIntegrationPopup({
provider: integration.provider,
github_app_name: envConfig?.github_app_name || "",
@ -129,6 +130,7 @@ export const SingleIntegrationCard: React.FC<Props> = observer(({ integration })
{workspaceIntegrations ? (
isInstalled ? (
<Tooltip
isMobile={isMobile}
disabled={isUserAdmin}
tooltipContent={!isUserAdmin ? "You don't have permission to perform this" : null}
>
@ -147,6 +149,7 @@ export const SingleIntegrationCard: React.FC<Props> = observer(({ integration })
</Tooltip>
) : (
<Tooltip
isMobile={isMobile}
disabled={isUserAdmin}
tooltipContent={!isUserAdmin ? "You don't have permission to perform this" : null}
>

View File

@ -2,6 +2,7 @@ import { FC, useState } from "react";
import Link from "next/link";
import { AlertCircle, X } from "lucide-react";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// ui
import { Tooltip } from "@plane/ui";
// components
@ -34,7 +35,7 @@ export const IssueAttachmentsDetail: FC<TIssueAttachmentsDetail> = (props) => {
} = useIssueDetail();
// states
const [attachmentDeleteModal, setAttachmentDeleteModal] = useState<boolean>(false);
const { isMobile } = usePlatformOS();
const attachment = attachmentId && getAttachmentById(attachmentId);
if (!attachment) return <></>;
@ -56,10 +57,11 @@ export const IssueAttachmentsDetail: FC<TIssueAttachmentsDetail> = (props) => {
<div className="h-7 w-7">{getFileIcon(getFileExtension(attachment.asset))}</div>
<div className="flex flex-col gap-1">
<div className="flex items-center gap-2">
<Tooltip tooltipContent={getFileName(attachment.attributes.name)}>
<Tooltip tooltipContent={getFileName(attachment.attributes.name)} isMobile={isMobile}>
<span className="text-sm">{truncateText(`${getFileName(attachment.attributes.name)}`, 10)}</span>
</Tooltip>
<Tooltip
isMobile={isMobile}
tooltipContent={`${
getUserDetails(attachment.updated_by)?.display_name ?? ""
} uploaded on ${renderFormattedDate(attachment.updated_at)}`}

View File

@ -4,6 +4,7 @@ import { Network } from "lucide-react";
import { Tooltip } from "@plane/ui";
import { renderFormattedTime, renderFormattedDate, calculateTimeAgo } from "helpers/date-time.helper";
import { useIssueDetail } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// ui
// components
import { IssueUser } from "../";
@ -25,7 +26,7 @@ export const IssueActivityBlockComponent: FC<TIssueActivityBlockComponent> = (pr
} = useIssueDetail();
const activity = getActivityById(activityId);
const { isMobile } = usePlatformOS();
if (!activity) return <></>;
return (
<div
@ -42,6 +43,7 @@ export const IssueActivityBlockComponent: FC<TIssueActivityBlockComponent> = (pr
<span> {children} </span>
<span>
<Tooltip
isMobile={isMobile}
tooltipContent={`${renderFormattedDate(activity.created_at)}, ${renderFormattedTime(activity.created_at)}`}
>
<span className="whitespace-nowrap"> {calculateTimeAgo(activity.created_at)}</span>

View File

@ -2,6 +2,7 @@ import { FC } from "react";
// hooks
import { Tooltip } from "@plane/ui";
import { useIssueDetail } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// ui
type TIssueLink = {
@ -14,12 +15,12 @@ export const IssueLink: FC<TIssueLink> = (props) => {
const {
activity: { getActivityById },
} = useIssueDetail();
const { isMobile } = usePlatformOS();
const activity = getActivityById(activityId);
if (!activity) return <></>;
return (
<Tooltip tooltipContent={activity.issue_detail ? activity.issue_detail.name : "This issue has been deleted"}>
<Tooltip tooltipContent={activity.issue_detail ? activity.issue_detail.name : "This issue has been deleted"} isMobile={isMobile}>
<a
aria-disabled={activity.issue === null}
href={`${

View File

@ -9,6 +9,7 @@ import { ExternalLinkIcon, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
import { calculateTimeAgo } from "helpers/date-time.helper";
import { copyTextToClipboard } from "helpers/string.helper";
import { useIssueDetail, useMember } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
import { IssueLinkCreateUpdateModal, TLinkOperationsModal } from "./create-update-link-modal";
export type TIssueLinkDetail = {
@ -33,7 +34,7 @@ export const IssueLinkDetail: FC<TIssueLinkDetail> = (props) => {
toggleIssueLinkModalStore(modalToggle);
setIsIssueLinkModalOpen(modalToggle);
};
const { isMobile } = usePlatformOS();
const linkDetail = getLinkById(linkId);
if (!linkDetail) return <></>;
@ -64,7 +65,7 @@ export const IssueLinkDetail: FC<TIssueLinkDetail> = (props) => {
<span className="py-1">
<LinkIcon className="h-3 w-3 flex-shrink-0" />
</span>
<Tooltip tooltipContent={linkDetail.title && linkDetail.title !== "" ? linkDetail.title : linkDetail.url}>
<Tooltip tooltipContent={linkDetail.title && linkDetail.title !== "" ? linkDetail.title : linkDetail.url} isMobile={isMobile}>
<span className="truncate text-xs">
{linkDetail.title && linkDetail.title !== "" ? linkDetail.title : linkDetail.url}
</span>

View File

@ -3,6 +3,7 @@ import { observer } from "mobx-react-lite";
import Link from "next/link";
import { Pencil, X } from "lucide-react";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// components
import { Tooltip } from "@plane/ui";
import { ParentIssuesListModal } from "components/issues";
@ -35,7 +36,7 @@ export const IssueParentSelect: React.FC<TIssueParentSelect> = observer((props)
const parentIssue = issue?.parent_id ? getIssueById(issue.parent_id) : undefined;
const parentIssueProjectDetails =
parentIssue && parentIssue.project_id ? getProjectById(parentIssue.project_id) : undefined;
const { isMobile } = usePlatformOS();
const handleParentIssue = async (_issueId: string | null = null) => {
try {
await issueOperations.update(workspaceSlug, projectId, issueId, { parent_id: _issueId });
@ -73,7 +74,7 @@ export const IssueParentSelect: React.FC<TIssueParentSelect> = observer((props)
>
{issue.parent_id && parentIssue ? (
<div className="flex items-center gap-1 bg-green-500/20 text-green-700 rounded px-1.5 py-1">
<Tooltip tooltipHeading="Title" tooltipContent={parentIssue.name}>
<Tooltip tooltipHeading="Title" tooltipContent={parentIssue.name} isMobile={isMobile}>
<Link
href={`/${workspaceSlug}/projects/${projectId}/issues/${parentIssue?.id}`}
target="_blank"
@ -86,7 +87,7 @@ export const IssueParentSelect: React.FC<TIssueParentSelect> = observer((props)
</Tooltip>
{!disabled && (
<Tooltip tooltipContent="Remove" position="bottom">
<Tooltip tooltipContent="Remove" position="bottom" isMobile={isMobile}>
<span
onClick={(e) => {
e.preventDefault();

View File

@ -7,6 +7,7 @@ import { RelatedIcon, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
import { ExistingIssuesListModal } from "components/core";
import { cn } from "helpers/common.helper";
import { useIssueDetail, useIssues, useProject } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// components
// ui
// helpers
@ -59,7 +60,7 @@ export const IssueRelationSelect: React.FC<TIssueRelationSelect> = observer((pro
toggleRelationModal,
} = useIssueDetail();
const { issueMap } = useIssues();
const { isMobile } = usePlatformOS();
const relationIssueIds = getRelationByIssueIdRelationType(issueId, relationKey);
const onSubmit = async (data: ISearchIssueResponse[]) => {
@ -124,7 +125,7 @@ export const IssueRelationSelect: React.FC<TIssueRelationSelect> = observer((pro
key={relationIssueId}
className={`group flex items-center gap-1 rounded px-1.5 pb-1 pt-1 leading-3 hover:bg-custom-background-90 ${issueRelationObject[relationKey].className}`}
>
<Tooltip tooltipHeading="Title" tooltipContent={currentIssue.name}>
<Tooltip tooltipHeading="Title" tooltipContent={currentIssue.name} isMobile={isMobile}>
<Link
href={`/${workspaceSlug}/projects/${projectDetails?.id}/issues/${currentIssue.id}`}
target="_blank"
@ -136,7 +137,7 @@ export const IssueRelationSelect: React.FC<TIssueRelationSelect> = observer((pro
</Link>
</Tooltip>
{!disabled && (
<Tooltip tooltipContent="Remove" position="bottom">
<Tooltip tooltipContent="Remove" position="bottom" isMobile={isMobile}>
<span
onClick={(e) => {
e.preventDefault();

View File

@ -15,6 +15,7 @@ import {
CalendarCheck2,
} from "lucide-react";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// components
import {
ArchiveIcon,
@ -78,7 +79,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
issue: { getIssueById },
} = useIssueDetail();
const { getStateById } = useProjectState();
const { isMobile } = usePlatformOS();
const issue = getIssueById(issueId);
if (!issue) return <></>;
@ -138,7 +139,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
<IssueSubscription workspaceSlug={workspaceSlug} projectId={projectId} issueId={issueId} />
)}
<div className="flex flex-wrap items-center gap-2.5 text-custom-text-300">
<Tooltip tooltipContent="Copy link">
<Tooltip tooltipContent="Copy link" isMobile={isMobile}>
<button
type="button"
className="grid h-5 w-5 place-items-center rounded hover:text-custom-text-200 focus:outline-none focus:ring-2 focus:ring-custom-primary"
@ -149,6 +150,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
</Tooltip>
{isArchivingAllowed && (
<Tooltip
isMobile={isMobile}
tooltipContent={isInArchivableGroup ? "Archive" : "Only completed or canceled issues can be archived"}
>
<button
@ -170,7 +172,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
</Tooltip>
)}
{is_editable && (
<Tooltip tooltipContent="Delete">
<Tooltip tooltipContent="Delete" isMobile={isMobile}>
<button
type="button"
className="grid h-5 w-5 place-items-center rounded hover:text-custom-text-200 focus:outline-none focus:ring-2 focus:ring-custom-primary"

View File

@ -8,6 +8,7 @@ import { Tooltip, ControlLink } from "@plane/ui";
import { cn } from "helpers/common.helper";
import { useApplication, useIssueDetail, useProject, useProjectState } from "hooks/store";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
import { usePlatformOS } from "hooks/use-platform-os";
// helpers
// types
import { TIssue, TIssueMap } from "@plane/types";
@ -29,6 +30,7 @@ export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
const { getProjectIdentifierById } = useProject();
const { getProjectStates } = useProjectState();
const { peekIssue, setPeekIssue } = useIssueDetail();
const { isMobile } = usePlatformOS();
// states
const [isMenuActive, setIsMenuActive] = useState(false);
@ -110,7 +112,7 @@ export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
<div className="flex-shrink-0 text-xs text-custom-text-300">
{getProjectIdentifierById(issue?.project_id)}-{issue.sequence_id}
</div>
<Tooltip tooltipContent={issue.name}>
<Tooltip tooltipContent={issue.name} isMobile={isMobile}>
<div className="truncate text-xs">{issue.name}</div>
</Tooltip>
</div>

View File

@ -5,7 +5,8 @@ import { Tooltip } from "@plane/ui";
// types
import { ISSUE_LAYOUTS } from "constants/issue";
import { TIssueLayouts } from "@plane/types";
// constants
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
type Props = {
layouts: TIssueLayouts[];
@ -15,11 +16,12 @@ type Props = {
export const LayoutSelection: React.FC<Props> = (props) => {
const { layouts, onChange, selectedLayout } = props;
const { isMobile } = usePlatformOS();
return (
<div className="flex items-center gap-1 rounded bg-custom-background-80 p-1">
{ISSUE_LAYOUTS.filter((l) => layouts.includes(l.key)).map((layout) => (
<Tooltip key={layout.key} tooltipContent={layout.title}>
<Tooltip key={layout.key} tooltipContent={layout.title} isMobile={isMobile}>
<button
type="button"
className={`group grid h-[22px] w-7 place-items-center overflow-hidden rounded transition-all hover:bg-custom-background-100 ${

View File

@ -1,5 +1,6 @@
import { observer } from "mobx-react";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// ui
import { Tooltip, StateGroupIcon, ControlLink } from "@plane/ui";
// helpers
@ -31,6 +32,7 @@ export const IssueGanttBlock: React.FC<Props> = observer((props) => {
issueDetails &&
!issueDetails.tempId &&
setPeekIssue({ workspaceSlug, projectId: issueDetails.project_id, issueId: issueDetails.id });
const { isMobile } = usePlatformOS();
return (
<div
@ -42,6 +44,7 @@ export const IssueGanttBlock: React.FC<Props> = observer((props) => {
>
<div className="absolute left-0 top-0 h-full w-full bg-custom-background-100/50" />
<Tooltip
isMobile={isMobile}
tooltipContent={
<div className="space-y-1">
<h5>{issueDetails?.name}</h5>
@ -83,6 +86,7 @@ export const IssueGanttSidebarBlock: React.FC<Props> = observer((props) => {
workspaceSlug &&
issueDetails &&
setPeekIssue({ workspaceSlug, projectId: issueDetails.project_id, issueId: issueDetails.id });
const { isMobile } = usePlatformOS();
return (
<ControlLink
@ -97,7 +101,7 @@ export const IssueGanttSidebarBlock: React.FC<Props> = observer((props) => {
<div className="flex-shrink-0 text-xs text-custom-text-300">
{projectIdentifier} {issueDetails?.sequence_id}
</div>
<Tooltip tooltipContent={issueDetails?.name}>
<Tooltip tooltipContent={issueDetails?.name} isMobile={isMobile}>
<span className="flex-grow truncate text-sm font-medium">{issueDetails?.name}</span>
</Tooltip>
</div>

View File

@ -6,6 +6,7 @@ import { Tooltip, ControlLink } from "@plane/ui";
import RenderIfVisible from "components/core/render-if-visible-HOC";
import { cn } from "helpers/common.helper";
import { useApplication, useIssueDetail, useProject } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// components
import { TIssue, IIssueDisplayProperties, IIssueMap } from "@plane/types";
import { IssueProperties } from "../properties/all-properties";
@ -41,6 +42,7 @@ interface IssueDetailsBlockProps {
const KanbanIssueDetailsBlock: React.FC<IssueDetailsBlockProps> = observer((props: IssueDetailsBlockProps) => {
const { issue, updateIssue, quickActions, isReadOnly, displayProperties } = props;
// hooks
const { isMobile } = usePlatformOS();
const { getProjectIdentifierById } = useProject();
const {
router: { workspaceSlug },
@ -66,7 +68,7 @@ const KanbanIssueDetailsBlock: React.FC<IssueDetailsBlockProps> = observer((prop
</WithDisplayPropertiesHOC>
{issue?.is_draft ? (
<Tooltip tooltipContent={issue.name}>
<Tooltip tooltipContent={issue.name} isMobile={isMobile}>
<span>{issue.name}</span>
</Tooltip>
) : (
@ -79,7 +81,7 @@ const KanbanIssueDetailsBlock: React.FC<IssueDetailsBlockProps> = observer((prop
className="w-full line-clamp-1 cursor-pointer text-sm text-custom-text-100"
disabled={!!issue?.tempId}
>
<Tooltip tooltipContent={issue.name}>
<Tooltip tooltipContent={issue.name} isMobile={isMobile}>
<span>{issue.name}</span>
</Tooltip>
</ControlLink>

View File

@ -1,11 +1,12 @@
import { observer } from "mobx-react-lite";
// components
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
import { useApplication, useIssueDetail, useProject } from "hooks/store";
// ui
import { Spinner, Tooltip, ControlLink } from "@plane/ui";
// helper
import { cn } from "helpers/common.helper";
import { useApplication, useIssueDetail, useProject } from "hooks/store";
// types
import { TIssue, IIssueDisplayProperties, TIssueMap } from "@plane/types";
import { IssueProperties } from "../properties/all-properties";
@ -36,7 +37,7 @@ export const IssueBlock: React.FC<IssueBlockProps> = observer((props: IssueBlock
setPeekIssue({ workspaceSlug, projectId: issue.project_id, issueId: issue.id });
const issue = issuesMap[issueId];
const { isMobile } = usePlatformOS();
if (!issue) return null;
const canEditIssueProperties = canEditProperties(issue.project_id);
@ -65,7 +66,7 @@ export const IssueBlock: React.FC<IssueBlockProps> = observer((props: IssueBlock
)}
{issue?.is_draft ? (
<Tooltip tooltipContent={issue.name}>
<Tooltip tooltipContent={issue.name} isMobile={isMobile}>
<span>{issue.name}</span>
</Tooltip>
) : (
@ -78,7 +79,7 @@ export const IssueBlock: React.FC<IssueBlockProps> = observer((props: IssueBlock
className="w-full line-clamp-1 cursor-pointer text-sm text-custom-text-100"
disabled={!!issue?.tempId}
>
<Tooltip tooltipContent={issue.name}>
<Tooltip tooltipContent={issue.name} isMobile={isMobile}>
<span>{issue.name}</span>
</Tooltip>
</ControlLink>

View File

@ -20,6 +20,7 @@ import { cn } from "helpers/common.helper";
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
import { shouldHighlightIssueDueDate } from "helpers/issue.helper";
import { useEventTracker, useEstimate, useLabel, useIssues, useProjectState } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// components
import { TIssue, IIssueDisplayProperties, TIssuePriorities } from "@plane/types";
import { IssuePropertyLabels } from "../properties/labels";
@ -50,6 +51,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
} = useIssues(EIssuesStoreType.CYCLE);
const { areEstimatesEnabledForCurrentProject } = useEstimate();
const { getStateById } = useProjectState();
const { isMobile } = usePlatformOS();
// router
const router = useRouter();
const { workspaceSlug } = router.query;
@ -391,7 +393,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
displayPropertyKey="sub_issue_count"
shouldRenderProperty={(properties) => !!properties.sub_issue_count && !!issue.sub_issues_count}
>
<Tooltip tooltipHeading="Sub-issues" tooltipContent={`${issue.sub_issues_count}`}>
<Tooltip tooltipHeading="Sub-issues" tooltipContent={`${issue.sub_issues_count}`} isMobile={isMobile}>
<div
onClick={issue.sub_issues_count ? redirectToIssueDetail : () => {}}
className={cn(
@ -413,7 +415,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
displayPropertyKey="attachment_count"
shouldRenderProperty={(properties) => !!properties.attachment_count && !!issue.attachment_count}
>
<Tooltip tooltipHeading="Attachments" tooltipContent={`${issue.attachment_count}`}>
<Tooltip tooltipHeading="Attachments" tooltipContent={`${issue.attachment_count}`} isMobile={isMobile}>
<div className="flex h-5 flex-shrink-0 items-center justify-center gap-2 overflow-hidden rounded border-[0.5px] border-custom-border-300 px-2.5 py-1">
<Paperclip className="h-3 w-3 flex-shrink-0" strokeWidth={2} />
<div className="text-xs">{issue.attachment_count}</div>
@ -427,7 +429,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
displayPropertyKey="link"
shouldRenderProperty={(properties) => !!properties.link && !!issue.link_count}
>
<Tooltip tooltipHeading="Links" tooltipContent={`${issue.link_count}`}>
<Tooltip tooltipHeading="Links" tooltipContent={`${issue.link_count}`} isMobile={isMobile}>
<div className="flex h-5 flex-shrink-0 items-center justify-center gap-2 overflow-hidden rounded border-[0.5px] border-custom-border-300 px-2.5 py-1">
<Link className="h-3 w-3 flex-shrink-0" strokeWidth={2} />
<div className="text-xs">{issue.link_count}</div>

View File

@ -9,6 +9,7 @@ import { Tooltip } from "@plane/ui";
import { useApplication, useLabel } from "hooks/store";
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
import { usePlatformOS } from "hooks/use-platform-os";
// components
// types
import { IIssueLabel } from "@plane/types";
@ -62,7 +63,7 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
router: { workspaceSlug },
} = useApplication();
const { fetchProjectLabels, getProjectLabels } = useLabel();
const { isMobile } = usePlatformOS();
const storeLabels = getProjectLabels(projectId);
const onOpen = () => {
@ -149,7 +150,13 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
{projectLabels
?.filter((l) => value.includes(l?.id))
.map((label) => (
<Tooltip key={label.id} position="top" tooltipHeading="Labels" tooltipContent={label?.name ?? ""}>
<Tooltip
key={label.id}
position="top"
tooltipHeading="Labels"
tooltipContent={label?.name ?? ""}
isMobile={isMobile}
>
<div
key={label?.id}
className={`flex overflow-hidden hover:bg-custom-background-80 ${
@ -176,6 +183,7 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
}`}
>
<Tooltip
isMobile={isMobile}
position="top"
tooltipHeading="Labels"
tooltipContent={projectLabels
@ -191,7 +199,7 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
</div>
)
) : (
<Tooltip position="top" tooltipHeading="Labels" tooltipContent="None">
<Tooltip position="top" tooltipHeading="Labels" tooltipContent="None" isMobile={isMobile}>
<div
className={`flex h-full items-center justify-center gap-2 rounded px-2.5 py-1 text-xs hover:bg-custom-background-80 ${
noLabelBorder ? "" : "border-[0.5px] border-custom-border-300"
@ -224,8 +232,8 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
disabled
? "cursor-not-allowed text-custom-text-200"
: value.length <= maxRender
? "cursor-pointer"
: "cursor-pointer hover:bg-custom-background-80"
? "cursor-pointer"
: "cursor-pointer hover:bg-custom-background-80"
} ${buttonClassName}`}
onClick={handleOnClick}
>

View File

@ -14,6 +14,7 @@ import { cn } from "helpers/common.helper";
// hooks
import { useIssueDetail, useProject } from "hooks/store";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
import { usePlatformOS } from "hooks/use-platform-os";
// types
import { IIssueDisplayProperties, TIssue } from "@plane/types";
// local components
@ -144,6 +145,7 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
//hooks
const { getProjectIdentifierById } = useProject();
const { peekIssue, setPeekIssue } = useIssueDetail();
const { isMobile } = usePlatformOS();
// states
const [isMenuActive, setIsMenuActive] = useState(false);
const menuActionRef = useRef<HTMLDivElement | null>(null);
@ -241,7 +243,7 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
disabled={!!issueDetail?.tempId}
>
<div className="w-full overflow-hidden">
<Tooltip tooltipContent={issueDetail.name}>
<Tooltip tooltipContent={issueDetail.name} isMobile={isMobile}>
<div
className="h-full w-full cursor-pointer truncate px-4 text-left text-[0.825rem] text-custom-text-100 focus:outline-none"
tabIndex={-1}

View File

@ -1,14 +1,15 @@
import React from "react";
// components
import { Tooltip } from "@plane/ui";
import { usePlatformOS } from "hooks/use-platform-os";
type Props = {
labelDetails: any[];
maxRender?: number;
};
export const ViewIssueLabel: React.FC<Props> = ({ labelDetails, maxRender = 1 }) => (
<>
export const ViewIssueLabel: React.FC<Props> = ({ labelDetails, maxRender = 1 }) => {
const { isMobile } = usePlatformOS();
return (<>
{labelDetails?.length > 0 ? (
labelDetails.length <= maxRender ? (
<>
@ -17,7 +18,7 @@ export const ViewIssueLabel: React.FC<Props> = ({ labelDetails, maxRender = 1 })
key={label.id}
className="flex flex-shrink-0 cursor-default items-center rounded-md border border-custom-border-300 px-2.5 py-1 text-xs shadow-sm"
>
<Tooltip position="top" tooltipHeading="Label" tooltipContent={label.name}>
<Tooltip position="top" tooltipHeading="Label" tooltipContent={label.name} isMobile={isMobile}>
<div className="flex items-center gap-1.5 text-custom-text-200">
<span
className="h-2 w-2 flex-shrink-0 rounded-full"
@ -33,7 +34,7 @@ export const ViewIssueLabel: React.FC<Props> = ({ labelDetails, maxRender = 1 })
</>
) : (
<div className="flex flex-shrink-0 cursor-default items-center rounded-md border border-custom-border-300 px-2.5 py-1 text-xs shadow-sm">
<Tooltip position="top" tooltipHeading="Labels" tooltipContent={labelDetails.map((l) => l.name).join(", ")}>
<Tooltip position="top" tooltipHeading="Labels" tooltipContent={labelDetails.map((l) => l.name).join(", ")} isMobile={isMobile}>
<div className="flex items-center gap-1.5 text-custom-text-200">
<span className="h-2 w-2 flex-shrink-0 rounded-full bg-custom-primary" />
{`${labelDetails.length} Labels`}
@ -44,5 +45,5 @@ export const ViewIssueLabel: React.FC<Props> = ({ labelDetails, maxRender = 1 })
) : (
""
)}
</>
);
</>)
};

View File

@ -8,6 +8,7 @@ import { LayersIcon, Loader, ToggleSwitch, Tooltip } from "@plane/ui";
import useDebounce from "hooks/use-debounce";
import { ProjectService } from "services/project";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// ui
// icons
// types
@ -37,7 +38,7 @@ export const ParentIssuesListModal: React.FC<Props> = ({
const [issues, setIssues] = useState<ISearchIssueResponse[]>([]);
const [isSearching, setIsSearching] = useState(false);
const [isWorkspaceLevel, setIsWorkspaceLevel] = useState(false);
const { isMobile } = usePlatformOS();
const debouncedSearchTerm: string = useDebounce(searchTerm, 500);
const router = useRouter();
@ -113,7 +114,7 @@ export const ParentIssuesListModal: React.FC<Props> = ({
/>
</div>
<div className="flex p-2 sm:justify-end">
<Tooltip tooltipContent="Toggle workspace level search">
<Tooltip tooltipContent="Toggle workspace level search" isMobile={isMobile}>
<div
className={`flex flex-shrink-0 cursor-pointer items-center gap-1 text-xs ${
isWorkspaceLevel ? "text-custom-text-100" : "text-custom-text-200"

View File

@ -21,9 +21,8 @@ import { cn } from "helpers/common.helper";
import { copyUrlToClipboard } from "helpers/string.helper";
// store hooks
import { useIssueDetail, useProjectState, useUser } from "hooks/store";
// helpers
// components
// helpers
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
export type TPeekModes = "side-peek" | "modal" | "full-screen";
@ -83,6 +82,7 @@ export const IssuePeekOverviewHeader: FC<PeekOverviewHeaderProps> = observer((pr
issue: { getIssueById },
} = useIssueDetail();
const { getStateById } = useProjectState();
const { isMobile } = usePlatformOS();
// derived values
const issueDetails = getIssueById(issueId);
const stateDetails = issueDetails ? getStateById(issueDetails?.state_id) : undefined;
@ -160,13 +160,14 @@ export const IssuePeekOverviewHeader: FC<PeekOverviewHeaderProps> = observer((pr
{currentUser && !isArchived && (
<IssueSubscription workspaceSlug={workspaceSlug} projectId={projectId} issueId={issueId} />
)}
<Tooltip tooltipContent="Copy link">
<Tooltip tooltipContent="Copy link" isMobile={isMobile}>
<button type="button" onClick={handleCopyText}>
<Link2 className="h-4 w-4 -rotate-45 text-custom-text-300 hover:text-custom-text-200" />
</button>
</Tooltip>
{isArchivingAllowed && (
<Tooltip
isMobile={isMobile}
tooltipContent={isInArchivableGroup ? "Archive" : "Only completed or canceled issues can be archived"}
>
<button
@ -185,14 +186,14 @@ export const IssuePeekOverviewHeader: FC<PeekOverviewHeaderProps> = observer((pr
</Tooltip>
)}
{isRestoringAllowed && (
<Tooltip tooltipContent="Restore">
<Tooltip tooltipContent="Restore" isMobile={isMobile}>
<button type="button" onClick={handleRestoreIssue}>
<RotateCcw className="h-4 w-4 text-custom-text-300 hover:text-custom-text-200" />
</button>
</Tooltip>
)}
{!disabled && (
<Tooltip tooltipContent="Delete">
<Tooltip tooltipContent="Delete" isMobile={isMobile}>
<button type="button" onClick={() => toggleDeleteIssueModal(true)}>
<Trash2 className="h-4 w-4 text-custom-text-300 hover:text-custom-text-200" />
</button>

View File

@ -4,6 +4,7 @@ import { ChevronDown, ChevronRight, X, Pencil, Trash, Link as LinkIcon, Loader }
// components
import { ControlLink, CustomMenu, Tooltip } from "@plane/ui";
import { useIssueDetail, useProject, useProjectState } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
import { TIssue } from "@plane/types";
import { IssueList } from "./issues-list";
import { IssueProperty } from "./properties";
@ -46,7 +47,7 @@ export const IssueListItem: React.FC<ISubIssues> = observer((props) => {
} = useIssueDetail();
const project = useProject();
const { getProjectStates } = useProjectState();
const { isMobile } = usePlatformOS();
const issue = getIssueById(issueId);
const projectDetail = (issue && issue.project_id && project.getProjectById(issue.project_id)) || undefined;
const currentIssueStateDetail =
@ -117,7 +118,7 @@ export const IssueListItem: React.FC<ISubIssues> = observer((props) => {
onClick={() => handleIssuePeekOverview(issue)}
className="w-full line-clamp-1 cursor-pointer text-sm text-custom-text-100"
>
<Tooltip tooltipContent={issue.name}>
<Tooltip tooltipContent={issue.name} isMobile={isMobile}>
<span>{issue.name}</span>
</Tooltip>
</ControlLink>

View File

@ -2,6 +2,7 @@ import Link from "next/link";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// ui
import { Tooltip, ModuleStatusIcon } from "@plane/ui";
// helpers
@ -25,6 +26,8 @@ export const ModuleGanttBlock: React.FC<Props> = observer((props) => {
const { getModuleById } = useModule();
// derived values
const moduleDetails = getModuleById(moduleId);
// hooks
const { isMobile } = usePlatformOS();
return (
<div
@ -36,6 +39,7 @@ export const ModuleGanttBlock: React.FC<Props> = observer((props) => {
>
<div className="absolute left-0 top-0 h-full w-full bg-custom-background-100/50" />
<Tooltip
isMobile={isMobile}
tooltipContent={
<div className="space-y-1">
<h5>{moduleDetails?.name}</h5>

View File

@ -12,6 +12,7 @@ import { EUserProjectRoles } from "constants/project";
import { renderFormattedDate } from "helpers/date-time.helper";
import { copyUrlToClipboard } from "helpers/string.helper";
import { useEventTracker, useMember, useModule, useUser } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// components
// ui
// helpers
@ -39,7 +40,7 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
// derived values
const moduleDetails = getModuleById(moduleId);
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const { isMobile } = usePlatformOS();
const handleAddToFavorites = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
e.preventDefault();
@ -179,7 +180,7 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
<div className="flex h-44 w-full flex-col justify-between rounded border border-custom-border-100 bg-custom-background-100 p-4 text-sm hover:shadow-md">
<div>
<div className="flex items-center justify-between gap-2">
<Tooltip tooltipContent={moduleDetails.name} position="top">
<Tooltip tooltipContent={moduleDetails.name} position="top" isMobile={isMobile}>
<span className="truncate text-base font-medium">{moduleDetails.name}</span>
</Tooltip>
<div className="flex items-center gap-2">
@ -208,7 +209,7 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
<span className="text-xs text-custom-text-300">{issueCount ?? "0 Issue"}</span>
</div>
{moduleDetails.member_ids?.length > 0 && (
<Tooltip tooltipContent={`${moduleDetails.member_ids.length} Members`}>
<Tooltip tooltipContent={`${moduleDetails.member_ids.length} Members`} isMobile={isMobile}>
<div className="flex cursor-default items-center gap-1">
<AvatarGroup showTooltip={false}>
{moduleDetails.member_ids.map((member_id) => {
@ -222,6 +223,7 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
</div>
<Tooltip
isMobile={isMobile}
tooltipContent={isNaN(completionPercentage) ? "0" : `${completionPercentage.toFixed(0)}%`}
position="top-left"
>

View File

@ -21,6 +21,7 @@ import { EUserProjectRoles } from "constants/project";
import { renderFormattedDate } from "helpers/date-time.helper";
import { copyUrlToClipboard } from "helpers/string.helper";
import { useModule, useUser, useEventTracker, useMember } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// components
// ui
// helpers
@ -48,7 +49,7 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
// derived values
const moduleDetails = getModuleById(moduleId);
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
const { isMobile } = usePlatformOS();
const handleAddToFavorites = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
e.preventDefault();
@ -194,7 +195,7 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
)}
</CircularProgressIndicator>
</span>
<Tooltip tooltipContent={moduleDetails.name} position="top">
<Tooltip tooltipContent={moduleDetails.name} position="top" isMobile={isMobile}>
<span className="truncate text-base font-medium">{moduleDetails.name}</span>
</Tooltip>
</div>
@ -227,7 +228,7 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
</div>
<div className="relative flex flex-shrink-0 items-center gap-3">
<Tooltip tooltipContent={`${moduleDetails?.member_ids?.length || 0} Members`}>
<Tooltip tooltipContent={`${moduleDetails?.member_ids?.length || 0} Members`} isMobile={isMobile}>
<div className="flex w-10 cursor-default items-center justify-center gap-1">
{moduleDetails.member_ids.length > 0 ? (
<AvatarGroup showTooltip={false}>

View File

@ -15,6 +15,7 @@ import { calculateTimeAgo, renderFormattedTime, renderFormattedDate } from "help
import { replaceUnderscoreIfSnakeCase, truncateText, stripAndTruncateHTML } from "helpers/string.helper";
// hooks
import { useEventTracker } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// type
import type { IUserNotification, NotificationType } from "@plane/types";
@ -44,7 +45,7 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
} = props;
// store hooks
const { captureEvent } = useEventTracker();
const { isMobile } = usePlatformOS();
const router = useRouter();
const { workspaceSlug } = router.query;
// states
@ -358,7 +359,7 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
},
},
].map((item) => (
<Tooltip tooltipContent={item.name} key={item.id}>
<Tooltip tooltipContent={item.name} key={item.id} isMobile={isMobile}>
<button
type="button"
onClick={(e) => {
@ -373,7 +374,7 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
</button>
</Tooltip>
))}
<Tooltip tooltipContent="Snooze">
<Tooltip tooltipContent="Snooze" isMobile={isMobile}>
<CustomMenu
className="flex items-center"
customButton={

View File

@ -13,6 +13,7 @@ import {
} from "constants/event-tracker";
import { getNumberCount } from "helpers/string.helper";
import { useEventTracker } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// helpers
// type
import type { NotificationType, NotificationCount } from "@plane/types";
@ -52,6 +53,8 @@ export const NotificationHeader: React.FC<NotificationHeaderProps> = (props) =>
} = props;
// store hooks
const { captureEvent } = useEventTracker();
// hooks
const { isMobile } = usePlatformOS();
const notificationTabs: Array<{
label: string;
@ -84,7 +87,7 @@ export const NotificationHeader: React.FC<NotificationHeaderProps> = (props) =>
</div>
<div className="flex items-center justify-center gap-x-4 text-custom-text-200">
<Tooltip tooltipContent="Refresh">
<Tooltip tooltipContent="Refresh" isMobile={isMobile}>
<button
type="button"
onClick={() => {
@ -94,7 +97,7 @@ export const NotificationHeader: React.FC<NotificationHeaderProps> = (props) =>
<RefreshCw className={`h-3.5 w-3.5 ${isRefreshing ? "animate-spin" : ""}`} />
</button>
</Tooltip>
<Tooltip tooltipContent="Unread notifications">
<Tooltip tooltipContent="Unread notifications" isMobile={isMobile}>
<button
type="button"
onClick={() => {
@ -154,7 +157,7 @@ export const NotificationHeader: React.FC<NotificationHeaderProps> = (props) =>
</CustomMenu.MenuItem>
</CustomMenu>
<div className="hidden md:block">
<Tooltip tooltipContent="Close">
<Tooltip tooltipContent="Close" isMobile={isMobile}>
<button type="button" onClick={() => closePopover()}>
<X className="h-3.5 w-3.5" />
</button>

View File

@ -11,6 +11,7 @@ import { getNumberCount } from "helpers/string.helper";
import { useApplication } from "hooks/store";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
import useUserNotification from "hooks/use-user-notifications";
import { usePlatformOS } from "hooks/use-platform-os";
// components
// images
import emptyNotification from "public/empty-state/notification.svg";
@ -23,6 +24,8 @@ export const NotificationPopover = observer(() => {
const { theme: themeStore } = useApplication();
// refs
const notificationPopoverRef = React.useRef<HTMLDivElement | null>(null);
// hooks
const { isMobile } = usePlatformOS();
const {
notifications,
@ -67,7 +70,7 @@ export const NotificationPopover = observer(() => {
/>
<Popover ref={notificationPopoverRef} className="md:relative w-full">
<>
<Tooltip tooltipContent="Notifications" position="right" className="ml-2" disabled={!isSidebarCollapsed}>
<Tooltip tooltipContent="Notifications" position="right" className="ml-2" disabled={!isSidebarCollapsed} isMobile={isMobile}>
<button
className={`group relative flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium outline-none ${
isActive

View File

@ -6,6 +6,7 @@ import { Button, Input, Tooltip } from "@plane/ui";
import { PAGE_ACCESS_SPECIFIERS } from "constants/page";
import { IPageStore } from "store/page.store";
import { IPage } from "@plane/types";
import { usePlatformOS } from "hooks/use-platform-os";
type Props = {
handleFormSubmit: (values: IPage) => Promise<void>;
@ -31,7 +32,7 @@ export const PageForm: React.FC<Props> = (props) => {
? { name: pageStore.name, description: pageStore.description, access: pageStore.access }
: defaultValues,
});
const { isMobile } = usePlatformOS();
const handleCreateUpdatePage = (formData: IPage) => handleFormSubmit(formData);
return (
@ -75,7 +76,7 @@ export const PageForm: React.FC<Props> = (props) => {
<div className="flex items-center gap-2">
<div className="flex flex-shrink-0 items-stretch gap-0.5 rounded border-[0.5px] border-custom-border-200 p-1">
{PAGE_ACCESS_SPECIFIERS.map((access, index) => (
<Tooltip key={access.key} tooltipContent={access.label}>
<Tooltip key={access.key} tooltipContent={access.label} isMobile={isMobile}>
<button
type="button"
onClick={() => onChange(access.key)}

View File

@ -22,8 +22,10 @@ import { CreateUpdatePageModal, DeletePageModal } from "components/pages";
import { EUserProjectRoles } from "constants/project";
import { renderFormattedTime, renderFormattedDate } from "helpers/date-time.helper";
import { copyUrlToClipboard } from "helpers/string.helper";
// hooks
import { useMember, usePage, useUser } from "hooks/store";
import { useProjectPages } from "hooks/store/use-project-specific-pages";
import { usePlatformOS } from "hooks/use-platform-os";
import { IIssueLabel } from "@plane/types";
export interface IPagesListItem {
@ -44,7 +46,7 @@ export const PagesListItem: FC<IPagesListItem> = observer(({ pageId, projectId }
const [createUpdatePageModal, setCreateUpdatePageModal] = useState(false);
const [deletePageModal, setDeletePageModal] = useState(false);
const { isMobile } = usePlatformOS();
const {
currentUser,
membership: { currentProjectRole },
@ -182,6 +184,7 @@ export const PagesListItem: FC<IPagesListItem> = observer(({ pageId, projectId }
<div className="flex items-center gap-2.5">
{archived_at ? (
<Tooltip
isMobile={isMobile}
tooltipContent={`Archived at ${renderFormattedTime(archived_at)} on ${renderFormattedDate(
archived_at
)}`}
@ -190,6 +193,7 @@ export const PagesListItem: FC<IPagesListItem> = observer(({ pageId, projectId }
</Tooltip>
) : (
<Tooltip
isMobile={isMobile}
tooltipContent={`Last updated at ${renderFormattedTime(updated_at)} on ${renderFormattedDate(
updated_at
)}`}
@ -198,7 +202,10 @@ export const PagesListItem: FC<IPagesListItem> = observer(({ pageId, projectId }
</Tooltip>
)}
{isEditingAllowed && (
<Tooltip tooltipContent={`${is_favorite ? "Remove from favorites" : "Mark as favorite"}`}>
<Tooltip
tooltipContent={`${is_favorite ? "Remove from favorites" : "Mark as favorite"}`}
isMobile={isMobile}
>
{is_favorite ? (
<button type="button" onClick={handleRemoveFromFavorites}>
<Star className="h-3.5 w-3.5 fill-orange-400 text-orange-400" />
@ -212,6 +219,7 @@ export const PagesListItem: FC<IPagesListItem> = observer(({ pageId, projectId }
)}
{userCanChangeAccess && (
<Tooltip
isMobile={isMobile}
tooltipContent={`${
access ? "This page is only visible to you" : "This page can be viewed by anyone in the project"
}`}
@ -228,6 +236,7 @@ export const PagesListItem: FC<IPagesListItem> = observer(({ pageId, projectId }
</Tooltip>
)}
<Tooltip
isMobile={isMobile}
position="top-right"
tooltipContent={`Created by ${ownerDetails?.member?.display_name} on ${renderFormattedDate(
created_at

View File

@ -16,6 +16,7 @@ import { renderFormattedDate } from "helpers/date-time.helper";
// hooks
import { useApplication, useProject, useUser } from "hooks/store";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
import { usePlatformOS } from "hooks/use-platform-os";
// services
import { UserService } from "services/user.service";
// components
@ -35,7 +36,7 @@ export const ProfileSidebar = observer(() => {
const { currentUser } = useUser();
const { theme: themeStore } = useApplication();
const { getProjectById } = useProject();
const { isMobile } = usePlatformOS();
const { data: userProjectsData } = useSWR(
workspaceSlug && userId ? USER_PROFILE_PROJECT_SEGREGATION(workspaceSlug.toString(), userId.toString()) : null,
workspaceSlug && userId
@ -158,7 +159,7 @@ export const ProfileSidebar = observer(() => {
</div>
<div className="flex flex-shrink-0 items-center gap-2">
{project.assigned_issues > 0 && (
<Tooltip tooltipContent="Completion percentage" position="left">
<Tooltip tooltipContent="Completion percentage" position="left" isMobile={isMobile}>
<div
className={`rounded px-1 py-0.5 text-xs font-medium ${
completedIssuePercentage <= 35

View File

@ -14,6 +14,8 @@ import { renderFormattedDate } from "helpers/date-time.helper";
import { useProject } from "hooks/store";
// types
import type { IProject } from "@plane/types";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// constants
import { EUserProjectRoles } from "constants/project";
@ -31,6 +33,9 @@ export const ProjectCard: React.FC<Props> = observer((props) => {
const { workspaceSlug } = router.query;
// store hooks
const { addProjectToFavorites, removeProjectFromFavorites } = useProject();
// hooks
const { isMobile } = usePlatformOS();
project.member_role;
// derived values
const projectMembersIds = project.members?.map((member) => member.member_id);
// auth
@ -171,6 +176,7 @@ export const ProjectCard: React.FC<Props> = observer((props) => {
</p>
<div className="item-center flex justify-between">
<Tooltip
isMobile={isMobile}
tooltipHeading="Members"
tooltipContent={
project.members && project.members.length > 0 ? `${project.members.length} Members` : "No Member"

View File

@ -27,6 +27,7 @@ import { cn } from "helpers/common.helper";
import { projectIdentifierSanitizer } from "helpers/project.helper";
// hooks
import { useEventTracker, useProject } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// types
import { IProject } from "@plane/types";
@ -71,7 +72,7 @@ export const CreateProjectForm: FC<Props> = observer((props) => {
defaultValues,
reValidateMode: "onChange",
});
const { isMobile } = usePlatformOS();
const handleAddToFavorites = (projectId: string) => {
if (!workspaceSlug) return;
@ -283,6 +284,7 @@ export const CreateProjectForm: FC<Props> = observer((props) => {
)}
/>
<Tooltip
isMobile={isMobile}
tooltipContent="Helps you identify issues in the project uniquely, (e.g. APP-123). Max 5 characters."
className="text-sm"
position="right-top"

View File

@ -14,6 +14,7 @@ import { EUserProjectRoles } from "constants/project";
import { ROLE } from "constants/workspace";
// hooks
import { useEventTracker, useMember, useProject, useUser } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
type Props = {
userId: string;
@ -36,7 +37,7 @@ export const ProjectMemberListItem: React.FC<Props> = observer((props) => {
project: { removeMemberFromProject, getProjectMemberDetails, updateMember },
} = useMember();
const { captureEvent } = useEventTracker();
const { isMobile } = usePlatformOS();
// derived values
const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
const userDetails = getProjectMemberDetails(userId);
@ -171,7 +172,7 @@ export const ProjectMemberListItem: React.FC<Props> = observer((props) => {
})}
</CustomSelect>
{(isAdmin || userDetails.member?.id === currentUser?.id) && (
<Tooltip tooltipContent={userDetails.member?.id === currentUser?.id ? "Leave project" : "Remove member"}>
<Tooltip tooltipContent={userDetails.member?.id === currentUser?.id ? "Leave project" : "Remove member"} isMobile={isMobile}>
<button
type="button"
onClick={() => setRemoveMemberModal(true)}

View File

@ -36,6 +36,7 @@ import { getNumberCount } from "helpers/string.helper";
// hooks
import { useApplication, useEventTracker, useInbox, useProject } from "hooks/store";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
import { usePlatformOS } from "hooks/use-platform-os";
// helpers
// components
@ -95,6 +96,7 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
const { setTrackElement } = useEventTracker();
const { addProjectToFavorites, removeProjectFromFavorites, getProjectById } = useProject();
const { getInboxesByProjectId, getInboxById } = useInbox();
const { isMobile } = usePlatformOS();
// states
const [leaveProjectModalOpen, setLeaveProjectModal] = useState(false);
const [publishModalOpen, setPublishModal] = useState(false);
@ -185,6 +187,7 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
>
{provided && !disableDrag && (
<Tooltip
isMobile={isMobile}
tooltipContent={project.sort_order === null ? "Join the project to rearrange" : "Drag to rearrange"}
position="top-right"
>
@ -205,7 +208,13 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
</button>
</Tooltip>
)}
<Tooltip tooltipContent={`${project.name}`} position="right" className="ml-2" disabled={!isCollapsed}>
<Tooltip
tooltipContent={`${project.name}`}
position="right"
className="ml-2"
disabled={!isCollapsed}
isMobile={isMobile}
>
<Disclosure.Button
as="div"
className={cn(
@ -353,6 +362,7 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
<Link key={item.name} href={item.href} onClick={handleProjectClick}>
<span className="block w-full">
<Tooltip
isMobile={isMobile}
tooltipContent={`${project?.name}: ${item.name}`}
position="right"
className="ml-2"

View File

@ -11,6 +11,7 @@ import { STATE_CREATED, STATE_UPDATED } from "constants/event-tracker";
import { GROUP_CHOICES } from "constants/project";
// hooks
import { useEventTracker, useProjectState } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// types
import type { IState } from "@plane/types";
@ -38,6 +39,7 @@ export const CreateUpdateStateInline: React.FC<Props> = observer((props) => {
// store hooks
const { captureProjectStateEvent, setTrackElement } = useEventTracker();
const { createState, updateState } = useProjectState();
const { isMobile } = usePlatformOS();
// form info
const {
handleSubmit,
@ -239,7 +241,7 @@ export const CreateUpdateStateInline: React.FC<Props> = observer((props) => {
name="group"
control={control}
render={({ field: { value, onChange } }) => (
<Tooltip tooltipContent={groupLength === 1 ? "Cannot have an empty group." : "Choose State"}>
<Tooltip tooltipContent={groupLength === 1 ? "Cannot have an empty group." : "Choose State"} isMobile={isMobile}>
<div>
<CustomSelect
disabled={groupLength === 1}

View File

@ -2,6 +2,7 @@ import { useState } from "react";
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
// ui
import { Pencil, X, ArrowDown, ArrowUp } from "lucide-react";
import { Tooltip, StateGroupIcon } from "@plane/ui";
@ -30,6 +31,7 @@ export const StatesListItem: React.FC<Props> = observer((props) => {
// store hooks
const { setTrackElement } = useEventTracker();
const { markStateAsDefault, moveStatePosition } = useProjectState();
const { isMobile } = usePlatformOS();
// derived values
const groupStates = statesList.filter((s) => s.group === state.group);
const groupLength = groupStates.length;
@ -109,11 +111,11 @@ export const StatesListItem: React.FC<Props> = observer((props) => {
disabled={state.default || groupLength === 1}
>
{state.default ? (
<Tooltip tooltipContent="Cannot delete the default state.">
<Tooltip tooltipContent="Cannot delete the default state." isMobile={isMobile}>
<X className={`h-4 w-4 ${groupLength < 1 ? "text-custom-sidebar-text-400" : "text-red-500"}`} />
</Tooltip>
) : groupLength === 1 ? (
<Tooltip tooltipContent="Cannot have an empty group.">
<Tooltip tooltipContent="Cannot have an empty group." isMobile={isMobile}>
<X className={`h-4 w-4 ${groupLength < 1 ? "text-custom-sidebar-text-400" : "text-red-500"}`} />
</Tooltip>
) : (

View File

@ -3,6 +3,8 @@ import { FC } from "react";
import { Tooltip } from "@plane/ui";
// types
import { IIssueLabel } from "@plane/types";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
type IssueLabelsListProps = {
labels?: (IIssueLabel | undefined)[];
@ -12,11 +14,12 @@ type IssueLabelsListProps = {
export const IssueLabelsList: FC<IssueLabelsListProps> = (props) => {
const { labels } = props;
const { isMobile } = usePlatformOS();
return (
<>
{labels && (
<>
<Tooltip position="top" tooltipHeading="Labels" tooltipContent={labels.map((l) => l?.name).join(", ")}>
<Tooltip position="top" tooltipHeading="Labels" tooltipContent={labels.map((l) => l?.name).join(", ")} isMobile={isMobile}>
<div className="flex items-center gap-1 rounded border-[0.5px] border-custom-border-300 px-2 py-1 text-xs text-custom-text-200">
<span className="h-2 w-2 flex-shrink-0 rounded-full bg-custom-primary" />
{`${labels.length} Labels`}

View File

@ -14,6 +14,8 @@ import { useWebhook, useWorkspace } from "hooks/store";
import { IWebhook } from "@plane/types";
// utils
import { getCurrentHookAsCSV } from "../utils";
// hooks
import { usePlatformOS } from "hooks/use-platform-os";
type Props = {
data: Partial<IWebhook>;
@ -30,7 +32,7 @@ export const WebhookSecretKey: FC<Props> = observer((props) => {
// store hooks
const { currentWorkspace } = useWorkspace();
const { currentWebhook, regenerateSecretKey, webhookSecretKey } = useWebhook();
const { isMobile } = usePlatformOS();
const handleCopySecretKey = () => {
if (!webhookSecretKey) return;
@ -108,7 +110,7 @@ export const WebhookSecretKey: FC<Props> = observer((props) => {
{webhookSecretKey && (
<div className="flex items-center gap-2">
{SECRET_KEY_OPTIONS.map((option) => (
<Tooltip key={option.key} tooltipContent={option.label}>
<Tooltip key={option.key} tooltipContent={option.label} isMobile={isMobile}>
<button type="button" className="grid flex-shrink-0 place-items-center" onClick={option.onClick}>
<option.Icon className="h-3 w-3 text-custom-text-400" />
</button>

View File

@ -10,6 +10,7 @@ import { DiscordIcon, GithubIcon, Tooltip } from "@plane/ui";
// hooks
import { useApplication } from "hooks/store";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
import { usePlatformOS } from "hooks/use-platform-os";
// assets
import packageJson from "package.json";
@ -41,6 +42,7 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
theme: { sidebarCollapsed, toggleSidebar },
commandPalette: { toggleShortcutModal },
} = useApplication();
const { isMobile } = usePlatformOS();
// states
const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false);
// refs
@ -69,7 +71,7 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
</div>
)}
<div className={`flex items-center gap-1 ${isCollapsed ? "flex-col justify-center" : "w-1/2 justify-evenly"}`}>
<Tooltip tooltipContent="Shortcuts">
<Tooltip tooltipContent="Shortcuts" isMobile={isMobile}>
<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 ${
@ -80,7 +82,7 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
<Zap className="h-3.5 w-3.5" />
</button>
</Tooltip>
<Tooltip tooltipContent="Help">
<Tooltip tooltipContent="Help" isMobile={isMobile}>
<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 ${
@ -100,7 +102,7 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
<MoveLeft className="h-3.5 w-3.5" />
</button>
<Tooltip tooltipContent={`${isCollapsed ? "Expand" : "Hide"}`}>
<Tooltip tooltipContent={`${isCollapsed ? "Expand" : "Hide"}`} isMobile={isMobile}>
<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 ${

View File

@ -10,6 +10,7 @@ import { ConfirmWorkspaceMemberRemove } from "components/workspace";
import { EUserWorkspaceRoles, ROLE } from "constants/workspace";
// hooks
import { useMember, useUser } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
type Props = {
invitationId: string;
@ -29,6 +30,7 @@ export const WorkspaceInvitationsListItem: FC<Props> = observer((props) => {
const {
workspace: { updateMemberInvitation, deleteMemberInvitation, getWorkspaceInvitationDetails },
} = useMember();
const { isMobile } = usePlatformOS();
// derived values
const invitationDetails = getWorkspaceInvitationDetails(invitationId);
@ -134,7 +136,7 @@ export const WorkspaceInvitationsListItem: FC<Props> = observer((props) => {
);
})}
</CustomSelect>
<Tooltip tooltipContent="Remove member" disabled={!isAdmin}>
<Tooltip tooltipContent="Remove member" disabled={!isAdmin} isMobile={isMobile}>
<button
type="button"
onClick={() => setRemoveMemberModal(true)}

View File

@ -13,6 +13,7 @@ import { WORKSPACE_MEMBER_lEAVE } from "constants/event-tracker";
import { EUserWorkspaceRoles, ROLE } from "constants/workspace";
// hooks
import { useEventTracker, useMember, useUser } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
type Props = {
memberId: string;
@ -35,6 +36,7 @@ export const WorkspaceMembersListItem: FC<Props> = observer((props) => {
workspace: { updateMember, removeMemberFromWorkspace, getWorkspaceMemberDetails },
} = useMember();
const { captureEvent } = useEventTracker();
const { isMobile } = usePlatformOS();
// derived values
const memberDetails = getWorkspaceMemberDetails(memberId);
@ -185,6 +187,7 @@ export const WorkspaceMembersListItem: FC<Props> = observer((props) => {
})}
</CustomSelect>
<Tooltip
isMobile={isMobile}
tooltipContent={isCurrentUser ? "Leave workspace" : "Remove member"}
disabled={!isAdmin && !isCurrentUser}
>

View File

@ -15,11 +15,13 @@ import { EUserWorkspaceRoles } from "constants/workspace";
import { cn } from "helpers/common.helper";
// hooks
import { useApplication, useEventTracker, useUser } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
export const WorkspaceSidebarMenu = observer(() => {
// store hooks
const { theme: themeStore } = useApplication();
const { captureEvent } = useEventTracker();
const { isMobile } = usePlatformOS();
const {
membership: { currentWorkspaceRole },
} = useUser();
@ -50,13 +52,13 @@ export const WorkspaceSidebarMenu = observer(() => {
position="right"
className="ml-2"
disabled={!themeStore?.sidebarCollapsed}
isMobile={isMobile}
>
<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" : ""}`}
} ${themeStore?.sidebarCollapsed ? "justify-center" : ""}`}
>
{
<link.Icon

View File

@ -0,0 +1,12 @@
import { useEffect, useState } from "react";
export const usePlatformOS = () => {
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
const userAgent = window.navigator.userAgent;
const isMobile = /iPhone|iPad|iPod|Android/i.test(userAgent);
if (isMobile) setIsMobile(isMobile);
}, []);
return {isMobile};
}

View File

@ -7,6 +7,7 @@ import { mutate } from "swr";
import { ChevronLeft, LogOut, MoveLeft, Plus, UserPlus } from "lucide-react";
// hooks
import { useApplication, useUser, useWorkspace } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// ui
import { Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
// constants
@ -41,7 +42,7 @@ export const ProfileLayoutSidebar = observer(() => {
} = useApplication();
const { currentUser, currentUserSettings, signOut } = useUser();
const { workspaces } = useWorkspace();
const { isMobile } = usePlatformOS();
const workspacesList = Object.values(workspaces ?? {});
// redirect url for normal mode
@ -132,7 +133,7 @@ export const ProfileLayoutSidebar = observer(() => {
return (
<Link key={link.key} href={link.href} className="block w-full" onClick={handleItemClick}>
<Tooltip tooltipContent={link.label} position="right" className="ml-2" disabled={!sidebarCollapsed}>
<Tooltip tooltipContent={link.label} position="right" className="ml-2" disabled={!sidebarCollapsed} isMobile={isMobile}>
<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.pathname)
@ -195,7 +196,7 @@ export const ProfileLayoutSidebar = observer(() => {
<div className="mt-1.5">
{WORKSPACE_ACTION_LINKS.map((link) => (
<Link className="block w-full" key={link.key} href={link.href} onClick={handleItemClick}>
<Tooltip tooltipContent={link.label} position="right" className="ml-2" disabled={!sidebarCollapsed}>
<Tooltip tooltipContent={link.label} position="right" className="ml-2" disabled={!sidebarCollapsed} isMobile={isMobile}>
<div
className={`group flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium text-custom-sidebar-text-200 outline-none hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80 ${
sidebarCollapsed ? "justify-center" : ""