KABBOUCHI / vue-tippy

VueJS Tooltip powered by Tippy.js
https://vue-tippy.netlify.app
MIT License
722 stars 86 forks source link

WCAG 1.2 issue 3.3.2: Tooltip labelling for icon buttons #282

Closed tommed closed 1 year ago

tommed commented 1 year ago

We picked tippy because of the advertised "Accessible by default, WAI-ARIA compliant"

However after independent testing, the following was raised: warning raised by wcag testers

Is there a way we can re-configure the default behaviour of Tippy so that tooltips are shown on focus via keyboard please?

How is Tippy usually configured to achieve WAI compatibility? Thanks,

KABBOUCHI commented 1 year ago

you can tab to trigger the tooltip on btn, all aria attr are there

image

https://codesandbox.io/p/sandbox/keen-cookies-1631dd?file=%2Fsrc%2FApp.vue&selection=%5B%7B%22endColumn%22%3A25%2C%22endLineNumber%22%3A1%2C%22startColumn%22%3A25%2C%22startLineNumber%22%3A1%7D%5D

tommed commented 1 year ago

Thanks. I can see that if I use v-tippy attribute/mix-in it works as described. However the default behaviour for the element does not do this. How can I configure it to trigger on keyboard focus of the element?

Otherwise, if I have a v-tippy defined within a routerview, it doesn't look like it's every processed and never shows the tooltip. If I need to use this instead, how do I get it to initialise the v-tippy attribute for sub-pages please?

KABBOUCHI commented 1 year ago

plz can u share an example? https://vue.new

tommed commented 1 year ago
// main.js

// tooltips
import { plugin as VueTippy, Tippy } from 'vue-tippy'
import 'tippy.js/dist/tippy.css' // optional for styling

// ...

createApp(App).use(VueTippy).component('Tippy', Tippy)
<!-- App.vue -->
<template>
  <RouterView />
</template>
<!-- SomeView.vue -->
<div class="zone" aria-label="This region can contain an aggregation of your choosing">
            <tippy content="Choose an aggregation for this area">
                <button @click="customise(0, firstKey)" class="heading">Aggregation #1</button>
            </tippy>
</div>

When I tab to the button, no tippy is raised. Whereas:

<li v-if="hasAlerts">
        <AppIcon v-tippy="{content: 'Launch the Reporting Dashboards'}" look-for="dashboards" aria-label="Launch the Reporting Dashboards" :to="{name:'dashboards'}" icon="fa-duotone fa-chart-user" />
</li>

Does on keyboard focus.

KABBOUCHI commented 1 year ago

u can treat tippy as button, should solve ur issue

https://codesandbox.io/p/sandbox/pensive-wildflower-5edc6f?file=%2Fsrc%2FApp.vue

<template>
  <div>
    <tippy
      content="Choose an aggregation for this area"
      tag="button"
      class="heading"
    >
      Aggregation #1
    </tippy>
  </div>
</template>
tommed commented 1 year ago

Thanks :) I guess the reason mine doesn't work in the same way is because the tippy is a parent element and doesn't actually have the focus itself, so cannot respond to it?

tommed commented 1 year ago

How does this work with RouterLink? I have tried tag="RouterLink" and :tag="RouterLink" (and imported the component) - but neither works :(

KABBOUCHI commented 1 year ago

How does this work with RouterLink? I have tried tag="RouterLink" and :tag="RouterLink" (and imported the component) - but neither works :(

can u try vue-tippy^6.1.0-beta.2?

tommed commented 1 year ago
// package.json
"vue-tippy": "6.1.0-beta.2",

This does indeed include the aria-label on the child node, but when I focus the keyboard onto the element, it doesn't solve the original question:

Is there a way we can re-configure the default behaviour of Tippy so that tooltips are shown on focus via keyboard please?

KABBOUCHI commented 1 year ago

@tommed released 6.1.0, now it mounts on the child node when the tag is null

<Tippy content="Choose an aggregation for this area" :tag="null">
    <button class="heading">Aggregation #1</button>
</Tippy>

https://codesandbox.io/p/sandbox/suspicious-borg-ypqggf?file=%2Fsrc%2FApp.vue

tommed commented 1 year ago

Using 6.1.0:

<tippy v-if="hideLink !== true" content="View Android device page" :tag="null">
            <RouterLink :to="{name:'view-device', params: { id }}" aria-label="View device page">
                <font-awesome-icon :icon="['fad', 'eye']"/>
            </RouterLink>
        </tippy>

When I tab using the keyboard to this element, it still does not show the tooltip.

Same for:

<tippy :content="label" :tag="null">
  <a href="javascript:void(0)">test button</a>
</tippy>

For reference:

// package.json
{

// ...

  "vue-tippy": "^6.1.0",

// ...

}

No aria either:

Screenshot 2023-05-03 at 15 41 10

KABBOUCHI commented 1 year ago

Using 6.1.0:

<tippy v-if="hideLink !== true" content="View Android device page" :tag="null">
            <RouterLink :to="{name:'view-device', params: { id }}" aria-label="View device page">
                <font-awesome-icon :icon="['fad', 'eye']"/>
            </RouterLink>
        </tippy>

When I tab using the keyboard to this element, it still does not show the tooltip.

Same for:

<tippy :content="label" :tag="null">
  <a href="javascript:void(0)">test button</a>
</tippy>

For reference:

// package.json
{

// ...

  "vue-tippy": "^6.1.0",

// ...

}

No aria either:

Screenshot 2023-05-03 at 15 41 10

there a span elem in ur screenshot, try to delete package lock file, node_modules and re-install vue-tippy

tommed commented 1 year ago

Thanks. That has fixed it for most of the scenarios, so long as I explicitly set the :tag="null".

However, there is still an example which isn't working:

<div class="android-device">
        <tippy v-if="hideLink !== true" content="View Android device page" :tag="null">
            <RouterLink :to="{name:'view-android-device', params: { imei }}" aria-label="View Android device page">
                <font-awesome-icon :icon="['fad', 'eye']"/>
            </RouterLink>
        </tippy>
</div>

Results in the html:

<span class="android-device">
<a href="/dashboards/android-devices/REDACTED" class="" data-v-tippy=""><svg class="svg-inline--fa fa-eye" aria-hidden="true" focusable="false" data-prefix="fad" data-icon="eye" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">SVG_MARKUP_REDACTED</svg></a>
</div>

UPDATE: I now appear to be getting warnings in the console:

[Vue warn]: Failed to resolve component: span
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement. 
  at <Tippy content="Refresh this dashboard" placement="left" > 

And an error too:

Uncaught (in promise) TypeError: Cannot convert object to primitive value
    at getArrayOfElements (vue-tippy.esm-browser.js:1889:29)
    at tippy (vue-tippy.esm-browser.js:3236:18)
    at mount (vue-tippy.esm-browser.js:4102:30)

It appears to not like the :tag="null" ?

KABBOUCHI commented 1 year ago
 <tippy v-if="hideLink !== true" content="View Android device page" :tag="null">
            <RouterLink :to="{name:'view-android-device', params: { imei }}" aria-label="View Android device page">
                <font-awesome-icon :icon="['fad', 'eye']"/>
            </RouterLink>
        </tippy>

error has been fixed in v6.1.2, and tested here https://github.com/KABBOUCHI/vue-tippy/blob/main/playground/pages/Wga.vue#L1C1-L19

tommed commented 1 year ago

That seems to have done it, thanks for that :)