vuetifyjs / vuetify

🐉 Vue Component Framework
https://vuetifyjs.com
MIT License
39.89k stars 6.97k forks source link

[Feature Request] Add tooltip as directive #9610

Closed archeg closed 7 months ago

archeg commented 5 years ago

Problem to solve

Tooltips are needed very often, and every time they are needed, we need to write quite a lot of code for one (according to documentation):

<v-tooltip right>
    <template v-slot:activator="{on}">
        <v-btn v-on="on">Button</v-btn>
    </template
    <span>I'm a tooltip!</span>
</v-tooltip>

Most of this stuff is needed only for advanced cases

Proposed solution

It would be awesome if they were available as a directive as well, for example:

<v-btn v-tooltip:right="I'm a tooltip!">Button</v-btn>
KaelWD commented 5 years ago

Duplicate of #2961

We have some changes coming that might make this possible

cn1001wang commented 4 years ago

I cant find "v-tooltip" directive in v2.3.6. is this feature available in v2.3.0 or v3.0?

marcocaimi commented 4 years ago

Hi, any news about this feature request? Is it present in v.2.3.10?

DRoet commented 4 years ago

no this is not available in 2.x, but might happen in the 3.x rework

sk-pub commented 3 years ago

@johnleider does the last change mean that it won't happen in Vuetify 3?

keystorm commented 3 years ago

@unicrus They just moved it to a different v3 board. They enabled GitHub Organizations for better cross repo project management, I'd assume, and the board had to be migrated.

mewtlu commented 2 years ago

For anyone else still wishing this was easily available in v2, I've published the plugin I've been using to wrap VTooltip with a directive: vue-tooltip-directive

rafaellehmkuhl commented 2 years ago

For anyone else still wishing this was easily available in v2, I've published the plugin I've been using to wrap VTooltip with a directive: vue-tooltip-directive

Your library is awesome, and is exactly what I expect on a future revision for Vuetify.

econic commented 1 year ago

For anyone else still wishing this was easily available in v2, I've published the plugin I've been using to wrap VTooltip with a directive: vue-tooltip-directive

I cannot agree more, among hundreds of usages in our app there's less than a handful where this wouldn't work. Much appreciated and really hope to see this in vuetify itself, exactly as provided

resu511 commented 1 year ago

Hello,

This thread may be old but for anyone stumbling upon it, I've written such a directive in TS for my use case. This was written using vue2 and vuetify2. I included some custom logic that is commented within the file, feel free to tweak for your own usage :-)

import Vue, {Directive} from "vue";
import VTooltip from "vuetify/lib/components/VTooltip";

/**
 * this directive binds a tooltip to an element using the VTooltip component
 * ```vue
 * <my-element
 *    v-tooltip="'The content of my tooltip'"
 * />
 * ```
 * by default the tooltip will be positioned at the top of the element\
 * position (e.g. `right`) can be handled using directive modifiers :
 * ```vue
 * <my-element
 *    v-tooltip.right="'The content of my tooltip on the right'"
 * />
 * ```
 * the `disabled` state is handled through the binding arg :
 * ```vue
 * <my-element
 *    v-tooltip:[myBoolean]="'The content of my tooltip'"
 * />
 * ```
 * ```js
 * data: () => ({
 *   myBoolean: true // will disable the tooltip
 * })
 * ```
 */
const tooltip = (): Directive => {
  return {
    inserted: (el: HTMLElement, binding) => {
      const {value, modifiers, arg} = binding;
      const {
        top = false,
        right = false,
        bottom = false,
        left = false,
        ...otherModifiers
      } = modifiers;

      /**
       * applies `cursor: help` on the hovered element if no cursor logic is applied
       */
      if (!el.className.match(/cursor-/) && !el.style.cursor)
        el.style.cursor = "help";

      const tooltipComponent = new Vue({
        data: () => ({isActive: false}),
        render: (h) =>
          h(
            VTooltip,
            {
              props: {
                value: tooltipComponent.isActive,
                activator: el,
                disabled: !!arg,
                /**
                 * defaults the position of the tooltip to `top`
                 */
                top: top || !(right || bottom || left),
                ...otherModifiers,
              },
              on: {
                input: (value: boolean) => (tooltipComponent.isActive = value),
              },
            },
            [value],
          ),
      });
      tooltipComponent.$mount();
      el.parentNode.insertBefore(tooltipComponent.$el, el);
    },
  };
};

export default tooltip;

I use it as a module, so to make it work you should set the following in your main file :

import tooltip from '../directives/tooltip.ts';

// if you don't want to use it as I do, just past the content of the above return instead of `tooltip`
Vue.directive('tooltip', tooltip)

Hope this helps !

tjhiggins commented 1 year ago

@resu511 Thanks for sharing! Made it vue3/vuetify3 compatible.

import { createVNode, render } from 'vue';
import { VTooltip } from 'vuetify/lib/components/index.mjs';

export default defineNuxtPlugin(({ vueApp }) => {
  let tooltips: { el: any }[] = [];

  vueApp.directive('tooltip', {
    beforeUnmount: (el, binding) => {
      const tooltipIndex = tooltips.findIndex((tooltip) => tooltip.el === el);
      const tooltip = tooltips.splice(tooltipIndex, 1);
      if (tooltip.length > 0) {
        render(null, el);
      }
    },
    mounted: (el, binding) => {
      const { value, modifiers } = binding;
      const { start = false, bottom = false, end = false } = modifiers;

      let location = 'top';
      if (start) location = 'left';
      else if (end) location = 'right';
      else if (bottom) location = 'bottom';

      /**
       * applies `cursor: help` on the hovered element if no cursor logic is applied
       */
      if (!el.className.match(/cursor-/) && !el.style.cursor) el.style.cursor = 'help';

      let vNode = createVNode(
        VTooltip,
        {
          activator: el,
          location,
        },
        () => [value],
      );

      vNode.appContext = vueApp._context;
      render(vNode, el);

      tooltips.push({ el });
    },
  });
});
johnleider commented 1 year ago

Keep an eye on this P.R. https://github.com/vuetifyjs/vuetify/pull/17395

Thomas-1985 commented 1 year ago

This doesn't work for me, what am i doing wrong?

Vue: 2.7.10 Vuetify: 2.5.4

<v-icon v-tooltip="'The content of my tooltip on the right'"> fa-play </v-icon>

However, no tooltip is shown (it also doesn't work with v-tooltip.right="'...'"

johnleider commented 7 months ago

closed by 2e1e74378b47e2f77721e1d3e5810cf6e25774f9