MauroBaptista.com

Creating Tooltip with Alpine and Tailwind in Laravel

October 24, 2021

Expected result from code:

expected tooltip result

We are going to create a component that will handle the tooltip. So, we need to create a file named tooltip.blade.php in /view/components. This way we will be able to call our tooltip as <x-tooltip ... />

@props([
    'tooltip'
])

<div
    x-data="{ show: false }"
    x-on:mouseover="show = true"
    x-on:mouseleave="show = false"
    {{ $attributes->class(['relative inline-flex w-auto cursor-pointer']) }}>

    <span x-show="show" x-cloak
          class="bg-gray-800 absolute -mt-5 top-1/2 right-1/2 transform translate-x-1/2 -translate-y-1/2 rotate-45"
          style="width: 10px; height: 10px;"
    ></span>
    <span x-show="show" x-cloak
          class="text-sm overflow-hidden text-white absolute bg-gray-800 rounded-md px-2 py-1 -mt-8 top-1/2 right-1/2 transform translate-x-1/2 -translate-y-1/2"
    >
        {!! str_replace(' ', '&nbsp;', $tooltip) !!}
    </span>

    {{ $slot }}
</div>

Then you can call in your blade files the component as:

<x-tooltip tooltip="Some Tooltip">
  Some Text
</x-tooltip>

Explaining the code

First we explicitly say that we require a tooltip argument.

@props([
 'tooltip'
])

Then we initiate the Alpine data, and also set to change the show value when entering or leaving the component.

Here we also set the required classes allowing to receive any other class from the view that is using the component.

<div
  x-data="{ show: false }"
  x-on:mouseover="show = true"
  x-on:mouseleave="show = false"
  {{ $attributes->class(['relative inline-flex w-auto cursor-pointer']) }}
>

We then create the “arrow” (which is just a rotated square), and only display it when show is true.

We also don’t want to display it when the page is loading, so we add the x-cloak Alpine method on it.

<span x-show="show" x-cloak
      class="bg-gray-800 absolute -mt-5 top-1/2 right-1/2 transform translate-x-1/2 -translate-y-1/2 rotate-45"
      style="width: 10px; height: 10px;"
></span>

And we add our tooltip.

<span x-show="show" x-cloak
      class="text-sm overflow-hidden text-white absolute bg-gray-800 rounded-md px-2 py-1 -mt-8 top-1/2 right-1/2 transform translate-x-1/2 -translate-y-1/2"
>
    {!! str_replace(' ', '&nbsp;', $tooltip) !!}
</span>

The str_replace method is needed to avoid break line on sentences with space.

Using Transitions

This is the approach you can see in the gif at top.

<x-tooltip tooltip="It will answer your question">
    <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-indigo-500" viewBox="0 0 20 20" fill="currentColor">
        <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-3a1 1 0 00-.867.5 1 1 0 11-1.731-1A3 3 0 0113 8a3.001 3.001 0 01-2 2.83V11a1 1 0 11-2 0v-1a1 1 0 011-1 1 1 0 100-2zm0 8a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd" />
    </svg>
</x-tooltip>

If you want to add some transition in your tooltip, you should add it to both span tags.

Sample of the tooltip.blade.php full body with transitions:

@props([
    'tooltip'
])

<div
    x-data="{ show: false }"
    x-on:mouseover="show = true"
    x-on:mouseleave="show = false"
    {{ $attributes->class(['relative inline-flex w-auto cursor-pointer']) }}>

    <span x-show="show" x-cloak
          x-transition:enter="transition ease-out duration-200"
          x-transition:enter-start="opacity-0 transform scale-90"
          x-transition:enter-end="opacity-100 transform scale-100"
          x-transition:leave="transition ease-in duration-50"
          x-transition:leave-start="opacity-100 transform scale-100"
          x-transition:leave-end="opacity-0 transform scale-90"
          class="bg-gray-800 absolute -mt-5 top-1/2 right-1/2 transform translate-x-1/2 -translate-y-1/2 rotate-45"
          style="width: 10px; height: 10px;"
    ></span>
    <span x-show="show" x-cloak
          x-transition:enter="transition ease-out duration-200"
          x-transition:enter-start="opacity-0 transform scale-90"
          x-transition:enter-end="opacity-100 transform scale-100"
          x-transition:leave="transition ease-in duration-200"
          x-transition:leave-start="opacity-100 transform scale-100"
          x-transition:leave-end="opacity-0 transform scale-90"
          class="text-sm overflow-hidden text-white absolute bg-gray-800 rounded-md px-2 py-1 -mt-8 top-1/2 right-1/2 transform translate-x-1/2 -translate-y-1/2"
    >
        {!! str_replace(' ', '&nbsp;', $tooltip) !!}

    </span>

    {{ $slot }}
</div>

Mauro Baptista

Mauro Baptista

Building stuff with code and having fun in the way

© 2021, Built with Gatsby