Exploring the method of implementing a "template" with Vue 3 HeadlessUI TransitionRoot

I'm currently working on setting up a slot machine-style animation using Vue 3, TailwindCSS, and HeadlessUI. At the moment, I have a simple green square that slides in from the top and out from the bottom based on cycles within a for-loop triggered by clicking the "click to transition" button. The resetIsShowing() function is responsible for randomizing a sequential array (1-10). My objective is to display one of these 10 random numbers on the green square during each cycle. To achieve this, I modified the main div displaying the square to pass a random number during each cycle:

<div v-for="number in numbers" :key="number.id" class="h-full w-full rounded-md bg-green-500 shadow-lg">
 {{ number }}
</div>

However, when I add the list property to the above div, I encounter the following error:

The current component <TransitionChild /> is rendering a "template".
However we need to passthrough the following props:
  - ref

If I change "template" to "ref" in the TransitionRoot, I lose the desired slide down effect. How can I configure this setup so that numbers appear on the square with each cycle?

Below is the complete code:

<template>
    <div class="flex flex-col items-center py-16">
      <div class="h-72 w-72">
        <div class="flex justify-center items-center w-full h-full p-4 text-9xl rounded-md shadow-lg border-solid border-2 border-sky-500">
            <TransitionRoot
              appear
              :show="isShowing"
              as="template"
              enter="transition ease-in-out duration-300 transform"
              enter-from="-translate-y-full opacity-0"
              enter-to="translate-y-0 opacity-100"
              leave="transition ease-in-out duration-300 transform"
              leave-from="translate-y-0 opacity-100"
              leave-to="translate-y-full opacity-0"
            >

              <div v-for="number in numbers" :key="number.id" class="h-full w-full rounded-md bg-green-500 shadow-lg">
                {{ number }}
              </div>
    
            </TransitionRoot>
        </div>
      </div>
      <button
        @click="resetIsShowing"
        class="mt-8 flex transform items-center rounded-full bg-black bg-opacity-20 px-3 py-2 text-sm font-medium text-white transition hover:scale-105 hover:bg-opacity-30 focus:outline-none active:bg-opacity-40"
      >
        <svg viewBox="0 0 20 20" fill="none" class="h-5 w-5 opacity-70">
          <path
            d="M14.9497 14.9498C12.2161 17.6835 7.78392 17.6835 5.05025 14.9498C2.31658 12.2162 2.31658 7.784 5.05025 5.05033C7.78392 2.31666 12.2161 2.31666 14.9497 5.05033C15.5333 5.63385 15.9922 6.29475 16.3266 7M16.9497 2L17 7H16.3266M12 7L16.3266 7"
            stroke="currentColor"
            stroke-width="1.5"
          />
        </svg>
  
        <span class="ml-3">Click to transition</span>
      </button>
    </div>
  </template>
  
  <script setup>
  import { ref } from 'vue'
  import { TransitionRoot } from '@headlessui/vue'
  
  const isShowing = ref(true)
  const numbers = ref([])
  const numberArray = ref(Array.from({length: 10}, (e, i)=> i + 1))

  const sleep = (milliseconds) => {
    return new Promise(resolve => setTimeout(resolve, milliseconds))
  }
  
  async function resetIsShowing() {
    for (let i = 0; i < numberArray.value.length; i++) {
        const index = Math.floor(Math.random() * numberArray.value.length)
        await sleep(800)

        isShowing.value = false
  
        setTimeout(() => {
            isShowing.value = true
        }, 500)

        numbers.value = numberArray.value.filter(r => r === (index + 1))
    }
  }
  </script>

Answer №1

SOLVED

<template>
    <div class="flex flex-col items-center py-16">
      <div class="h-72 w-72">
        <div class="flex justify-center items-center w-full h-full p-4 rounded-md shadow-lg border-solid border-2 border-sky-500">
            <TransitionRoot
              appear
              :show="isShowing"
              as="template"
              enter="transition ease-in-out duration-[400ms]"
              enter-from="-translate-y-full opacity-0"
              enter-to="translate-y-0 opacity-100"
              leave="transition ease-in-out duration-[400ms]"
              leave-from="translate-y-0 opacity-100"
              leave-to="translate-y-full opacity-0"
            >

              <div class="h-full w-full rounded-md pt-16">
                <span v-if="numbers > 0" class="text-9xl">
                    {{ numbers }}
                </span>
              </div>
    
            </TransitionRoot>
        </div>
      </div>
      <button
        @click="resetIsShowing"
        class="mt-8 flex transform items-center rounded-full bg-black bg-opacity-20 px-3 py-2 text-sm font-medium text-white transition hover:scale-105 hover:bg-opacity-30 focus:outline-none active:bg-opacity-40"
      >
        <svg viewBox="0 0 20 20" fill="none" class="h-5 w-5 opacity-70">
          <path
            d="M14.9497 14.9498C12.2161 17.6835 7.78392 17.6835 5.05025 14.9498C2.31658 12.2162 2.31658 7.784 5.05025 5.05033C7.78392 2.31666 12.2161 2.31666 14.9497 5.05033C15.5333 5.63385 15.9922 6.29475 16.3266 7M16.9497 2L17 7H16.3266M12 7L16.3266 7"
            stroke="currentColor"
            stroke-width="1.5"
          />
        </svg>
  
        <span class="ml-3">Click to change</span>
      </button>
    </div>
  </template>
  
  <script setup>
  import { ref, watch } from 'vue'
  import { TransitionRoot } from '@headlessui/vue'
  
  const isShowing = ref(true)
  const numbers = ref([])
  const numberArray = ref(Array.from({length: 10}, (e, i)=> i + 1))

  const sleep = (milliseconds) => {
    return new Promise(resolve => setTimeout(resolve, milliseconds))
  }
  
  async function resetIsShowing() {
    for (let i = 0; i < numberArray.value.length; i++) {

        await sleep(1200)
        
        const index = Math.floor(Math.random() * numberArray.value.length)
        // const index = numberArray.value[i]
        
        numbers.value = numberArray.value.filter(r => r === (index + 1))[0]
        // numbers.value = numberArray.value.filter(r => r === (index))[0]
        
        console.log(numbers.value)
        
        isShowing.value = false
        
        setTimeout(() => {
            isShowing.value = true
        }, 500)
    }
  }
  </script>
  

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Show an expanded row in a Vuetify data table without any visible columns

My goal is to create a data table with expanded rows that occupy the full width of the parent row. However, I am facing an issue where the expanded row is automatically divided into columns, causing it to display under the first item of the parent row when ...

Exploring a Ring with Three.js OrbitControls Rotation

I am having an issue with my OrbitControls camera setup. Currently, the camera rotates around a fixed point at player.position.x, y, and z coordinates. While it works fine, I need the camera to rotate around a ring instead. In the examples provided, the fi ...

Utilize SWR to retrieve data that corresponds to the chosen value from the dropdown menu

Can SWR fetch data based on the selected value in a dropdown? Initially, it works, but when I select a previously selected value, it doesn't fetch the correct data. Using the Fetch API const { data: entities } = useSWR( currentEntity?.enti ...

jQuery is in a constant state of indecision when it comes to determining the best way to manage buttons

A straightforward scenario. When a checkbox is checked, it activates a disabled button. Unchecking the box disables the button again. Sample Code: jQuery -> $('#subscribe_button').attr('disabled','disabled') $("[name= ...

What could be the reason behind the index not getting properly set for the array that was cloned afterward?

I need assistance with a code snippet that clones an array, resets the index (0, 1, 2 ...), and stores it in a variable named buildingsPayload: console.log('1:', this.buildings) const buildingsPayload = this.buildings.map((building, index) => ...

Using Nested ng-repeat for Values and Keys in Angular

Struggling with implementing nested ng-repeats in my code. I have a JSON object with multiple layers and attempting to iterate through them to display the data. Here is the structure of the JSON: { "status": "success", "data": { "Mat": { "tota ...

Implementing Jquery tabs into the code causes the vertical auto-scroll to smoothly glide beyond anchor points

I recently implemented a smooth autoscroll feature on my webpage using the CSS-Tricks code found here: http://css-tricks.com/snippets/jquery/smooth-scrolling/ Everything was working perfectly until I added jQuery tabs to display some of the content. Now, ...

Implementing Cross-Origin Resource Sharing (CORS) in play-framework version 2.5.x: A Step-by-Step Guide

My current challenge involves retrieving JSON data by sending a request to a Restful URL from localhost within an AngularJS-1 application. The error that I encounter is as follows: http://localhost:9000/mlm/user/all Failed to load resource: the server r ...

How can I take photos in bulk when I open the camera on Ionic 3?

Is there a way to capture multiple images at once using the camera? Currently, I am only able to capture one image when the user clicks. However, I would like to capture four images when the user clicks the success button. let options: CaptureImageOption ...

What is the best method for extracting span text using selenium?

<p id="line1" class=""><span class="bot">Do you have a short-term memory?</span><span id="snipTextIcon" class="yellow" style="opacity: 1;"></span></p> I want to extract this text: Do you have a short-term memory? This ...

Error encountered when attempting to trigger a Bootstrap dropdown within a designated div

When using React JS, I encountered an issue when trying to trigger a dropdown that was nested inside a div with the class name "row". Initially, I placed the data-toggle and data-target attributes inside the div, like so: <div className="row"> < ...

Attempting to enhance the modularity and readability of my code

Looking for assistance to enhance the modularity and readability of this lengthy code. Any tips on how to simplify it and improve clarity would be greatly appreciated! I'm currently working on a street fighter game, and here's what I have so far ...

Module fails to load in the proper sequence

As a .NET developer who is relatively new to modern client-side web applications, I am currently working on developing an Angular2 charting application using Chart.js. The modules are being loaded with SystemJS. Below is the content of my systemjs.config. ...

Is there a way to download a file using an ajax request?

We are faced with a particular scenario in our application where: Client sends a request Server processes the request and generates a file Server sends the file back as a response Client's browser prompts a dialog for downloading the file Our appli ...

The setting of the custom user agent in the Chrome Extension Manifest Version 3 is not functioning correctly

We currently have an extension that consists of only two files: manifest.json and background.js Despite the browser (Chrome version 112) not reporting any errors, we are facing an issue where the user agent is not being set to 'my-custom-user-agent&a ...

Why is my Angular 2 service not showing up in my application?

Trying to access a JSON file using an Angular service has been unsuccessful. While I can easily read and bind the JSON data without the service, attempting to do so with the service results in an error message: Failed to load resource: the server responde ...

Issue with Colorbox plugin preventing ASP.NET button from triggering postback

Currently utilizing the colorbox modal plugin (http://colorpowered.com/colorbox/) I'm facing an issue with a simple form placed in a master page - the submit button is unresponsive and doesn't trigger any action. It seems like several users are ...

Can Vuex mapActions be utilized within a module that is exported?

Is it possible to utilize Vuex mapActions from an external module imported into a component? I am working on standardizing a set of functions in a vue.js web application. My goal is to import these functions into each component and pass necessary values f ...

Troubleshooting: Why isn't setMetadata working in NestJS from authGuards

When I call my decorators, I want to set metadata for logging purposes. Within my controller, the following decorators are used: @Post("somePath") @Permission("somePermission") @UseGuards(JwtAuthGuard) @HttpCode(200) @Grafana( ...

JavaScript file encountering a problem with its global variables

What is causing the alert("2") to pop up first instead of it being second? Why am I encountering difficulty creating global variables c and ctx? Is there a way for me to successfully create these two global variables in order to utilize ...