简体   繁体   中英

Alpine custom tooltip directive darkmode with tippy.js

I'm trying to implement the tippy.js tooltip and change the theme based on the local storage value darkMode as an AlpineJs custom directive .

The code below works more or less fine with the latest bit that if I toggle the dark-mode switch, which changes the local localStorage item value of darkMode , I need a page refresh to get the new value.

How can I get the value ( JSON.parse(localStorage.getItem('darkMode')) ) while I change it?

app.js

document.addEventListener('alpine:init', () => {
    Alpine.directive('tooltip', (el, {expression, modifiers}) => {
        tippy(el, {
            content: expression,
            placement: modifiers[0] ?? 'auto',
            theme: JSON.parse(localStorage.getItem('darkMode')) ?'blue':'light-border'
        })
    })
})

tool-tip button

<button type="button" x-tooltip.left="I'm a tooltip">Hover me</button>

darkmode

<body class="font-sans antialiased h-full"
      x-data="{'darkMode': false}"
      x-init="
        darkMode = JSON.parse(localStorage.getItem('darkMode'));
        $watch('darkMode', value => localStorage.setItem('darkMode', JSON.stringify(value)))"
      x-cloak
>
<!-- some html -->
</body>

toggle button

<input id="toggle" type="checkbox"  :value="darkMode" @change="darkMode = !darkMode"/>

As you see a Tippy.js instance and the localStorage is not reactive. After creating a Tippy.js instance we need to use the _tippy property on each element if we want to change a property. To make it a little bit easier, I modified the tooltip directive to add a custom class tooltips , that we use to loop over each Tippy.js instance.

document.addEventListener('alpine:init', () => {
  Alpine.directive('tooltip', (el, { expression, modifiers }) => {
    tippy(el, {
      content: expression,
      placement: modifiers[0] ?? 'auto',
      theme: JSON.parse(localStorage.getItem('darkMode')) ? 'blue' : 'light-border'
    })
    el.classList.add('tooltips')
  })
})

And in the $watch magic, we use the tooltips class to find all of the Tippy.js instances and set the new theme on them.

<body class="font-sans antialiased h-full"
      x-data="{'darkMode': false}"
      x-init="
        darkMode = JSON.parse(localStorage.getItem('darkMode'));
        $watch('darkMode', value => {
            localStorage.setItem('darkMode', JSON.stringify(value))
            Array.from(document.querySelectorAll('.tooltips')).forEach(
              el => el._tippy.setProps({ theme: value ? 'blue' : 'light-border' }))
        })"
      x-cloak
>
<!-- some html -->
</body>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM