ui icon indicating copy to clipboard operation
ui copied to clipboard

Tooltip trigger onMobile

Open jozefdrabik opened this issue 2 years ago • 11 comments

I would like to ask how does tooltip work on mobile devices? Because when i tried to use it there it does not work. Is there some solution for this to trigger tooltip when user clicks on trigger?

jozefdrabik avatar Feb 15 '23 13:02 jozefdrabik

Also the tooltip only opens when you hover the border, does not work on the surface: E.g here: https://ui.shadcn.com/docs/primitives/tooltip

jackblackCH avatar Feb 15 '23 16:02 jackblackCH

I would like to ask how does tooltip work on mobile devices? Because when i tried to use it there it does not work. Is there some solution for this to trigger tooltip when user clicks on trigger?

This is a design decision from Radix UI team, see #955 and the answer by Benoît Grélard. He said:

This is by design. Tooltips are problematic on touch devices because there is no hover interaction, so if it was on tap it would fight with the general button action, or require 2 taps. That's also why tooltips should just be used generally for extra information that isn't mandatory do use your interface.

In case you "need a tooltip" use a popover instead, as they do in their documentation.

codingcodax avatar Mar 16 '23 15:03 codingcodax

tooltip Not work on mobile view

chadryja avatar Feb 01 '24 05:02 chadryja

any progress?

0xbid avatar Feb 14 '24 05:02 0xbid

@0xbid the only solution is described above. So i use Tooltip for Desktop and for tablet and mobile i just change it to popover. Or u can make some own logic instead of using libraries(made one as well).

jozefdrabik avatar Feb 20 '24 13:02 jozefdrabik

To summarise, they are three components:

Tooltip and Hover Card are only meant to be used on desktop. Popover is meant to be used on desktop and mobile.

This is a design choice by the Radix people. I think it wouldn't make sense to change it here at Shadcn-UI :thinking: so I reckon this issue can be closed.

If you need a hybrid solution, which mounts a popover on mobile and a tooltip by default, have a look at this suggestion :wink:

Zwyx avatar Mar 12 '24 10:03 Zwyx

Does it continue to make sense to be locked-in to radix for this scenario? I mean the Radix design choices shouldn't limit the capabilities offered by ShadCn. Would it make sense to look at a better alternative for this case? Similar as how it was done for the carousel component. I would say the https://floating-ui.com/ offers a great alternative to build something useful and fully configurable.

oxuk85 avatar Mar 28 '24 15:03 oxuk85

To summarise, they are three components:

Tooltip and Hover Card are only meant to be used on desktop. Popover is meant to be used on desktop and mobile.

This is a design choice by the Radix people. I think it wouldn't make sense to change it here at Shadcn-UI 🤔 so I reckon this issue can be closed.

If you need a hybrid solution, which mounts a popover on mobile and a tooltip by default, have a look at this suggestion 😉

I am surprised, that in 2024, we are still trying to differentiate between "desktop", "touch", "pointer down". When do we realize that everything is hybrid? We will never know if a user is touching only and within the next minute using a pointer device on the same screen? Simple example: I am on an iPad with an iPencil, how should the tooltip behave?

Shouldn't responsive components always work consistently on any "device" with and without "touch"? 🙏

jackblackCH avatar Apr 10 '24 11:04 jackblackCH

To summarise, they are three components:

Tooltip and Hover Card are only meant to be used on desktop. Popover is meant to be used on desktop and mobile. This is a design choice by the Radix people. I think it wouldn't make sense to change it here at Shadcn-UI 🤔 so I reckon this issue can be closed. If you need a hybrid solution, which mounts a popover on mobile and a tooltip by default, have a look at this suggestion 😉

I am surprised, that in 2024, we are still trying to differentiate between "desktop", "touch", "pointer down". When do we realize that everything is hybrid? We will never know if a user is touching only and within the next minute using a pointer device on the same screen? Simple example: I am on an iPad with an iPencil, how should the tooltip behave?

Shouldn't responsive components always work consistently on any "device" with and without "touch"? 🙏

I ended up using @floating-ui/react I found it was used by Radix in a component.

Here is the demo I found and used as the template for my own re-usable component. It works great on touch devices.

https://codesandbox.io/p/sandbox/xenodochial-grass-js3bo9?file=%2Fsrc%2FTooltip.tsx

In case you are curious here is a gist with the component I build: https://gist.github.com/oxuk85/34e6969d6ec3971f4561d69f26571bb4

oxuk85 avatar Apr 10 '24 17:04 oxuk85

'use client'
import { Button } from "@/components/ui/button"
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip"
import { InfoIcon } from "lucide-react"
import { useState } from "react"
export default function InfoTooltip({information}:{information : string}) {
    const [open, setOpen] = useState(false);
    function handleOpenClose(){
        if(open){
            setOpen(false);
        }
        else{
            setOpen(true);
            setTimeout(() => {
                setOpen(false);
            }, 2500);
        }
    }
    return (
        <>
        <TooltipProvider>
            <Tooltip>
                <TooltipTrigger asChild className="collapse lg:visible xl:visible 2xl:visible">
                    <InfoIcon className="opacity-15 dark:opacity-50 hover:opacity-80 ml-2"/>
                </TooltipTrigger>
                <TooltipContent className="max-w-[40vw] p-2">
                    <p>{information}</p>
                </TooltipContent>
            </Tooltip>
        </TooltipProvider>
        {open && <p className="absolute z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2">
            {information}
        </p>}
        <Button onClick={handleOpenClose} className="bg-transparent lg:collapse xl:collapse 2xl:collapse m-2" variant={'ghost'}><InfoIcon className="opacity-15 dark:opacity-50 hover:opacity-80"/></Button>
        </>
    )
}

This is what I have settled for. I know not the most elegant but mostly works.

techlism avatar Apr 12 '24 04:04 techlism

In case you "need a tooltip" use a popover instead, as they do in their documentation.

This is the correct solution, and it works like a charm. But honestly I don't understand the point of having both the <Tooltip> and the <Popover>. It seems the <Tooltip> can be deprecated in favor of the <Popover>.

alberduris avatar May 23 '24 12:05 alberduris

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.

shadcn avatar Jul 10 '24 23:07 shadcn

Here is a tooltip that works on both mobile and desktop. We just handle all interactions ourselves. We get the added benefit of having this work with tabbing i.e. on a form and using the Enter key to toggle open and close

cc: @shadcn

const Tip = ({
  content,
  children,
  className
}: React.PropsWithChildren<{ content: string | React.ReactNode; className?: string }>) => {
  const [open, setOpen] = React.useState(false);

  return (
    <TooltipProvider delayDuration={0}>
      <Tooltip open={open}>
        <TooltipTrigger asChild>
          <button
            type="button"
            className={cn('cursor-pointer', className)}
            onClick={() => setOpen(!open)}
            onMouseEnter={() => setOpen(true)}
            onMouseLeave={() => setOpen(false)}
            onTouchStart={() => setOpen(!open)}
            onKeyDown={(e) => {
              e.preventDefault();
              e.key === 'Enter' && setOpen(!open);
            }}
          >
            {children}
          </button>
        </TooltipTrigger>
        <TooltipContent className={!content ? 'hidden' : ''}>
          <span className="inline-block">{content}</span>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
};

devotox avatar Jul 21 '24 23:07 devotox