forked from github/plane
[WEB-713] style: remove tooltips in mobile responsiveness (#3948)
Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
parent
b930d98665
commit
cb632408f9
@ -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}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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 ? (
|
||||
|
@ -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}
|
||||
|
@ -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"
|
||||
|
@ -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)}
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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 ${
|
||||
|
@ -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>
|
||||
|
@ -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}>
|
||||
|
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -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`}
|
||||
|
@ -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" : ""
|
||||
|
@ -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`}
|
||||
|
@ -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(
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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}
|
||||
>
|
||||
|
@ -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)}`}
|
||||
|
@ -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>
|
||||
|
@ -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={`${
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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 ${
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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}
|
||||
>
|
||||
|
@ -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}
|
||||
|
@ -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 })
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</>
|
||||
);
|
||||
</>)
|
||||
};
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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}>
|
||||
|
@ -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={
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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)}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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)}
|
||||
|
@ -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"
|
||||
|
@ -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}
|
||||
|
@ -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>
|
||||
) : (
|
||||
|
@ -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`}
|
||||
|
@ -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>
|
||||
|
@ -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 ${
|
||||
|
@ -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)}
|
||||
|
@ -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}
|
||||
>
|
||||
|
@ -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
|
||||
|
12
web/hooks/use-platform-os.tsx
Normal file
12
web/hooks/use-platform-os.tsx
Normal 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};
|
||||
}
|
@ -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" : ""
|
||||
|
Loading…
Reference in New Issue
Block a user