Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ImWaller's avatar

Help with the fucntionality for the theme changer.

Hello everybody, I try to create a method to change the theme color of the elements. But the problem I face is something with the tailwind css classes. I think tailwind can't detect the color classes. I try with 2 ways bad one is the string concatenation as tailwind docs mention don't do that and I try the second which create the color classes with the javascript but not working too. If you try to replace the first (on navbar) classes('bg-600') helper that I create below then the colors work but with some problems. Can you help with this or you can suggest a better or different solution.

suport function: classes() example: classes('bg-600') and return the selected color bg-indigo-600

component code (this code exist on the above code anyway):

            <div class="flex space-x-1 bg-white rounded-full px-2 py-1">
              <button
                class="rounded-full"
                v-for="(themeColor, index) in listTheme"
                :key="index"
                :class="[classes('bg-600'), !themeColor.current ? 'p-3' : 'p-1']"
                @click="color = themeColor.name"
              >
                <CheckIcon v-if="themeColor.current" class="text-white w-4 h-4" />
              </button>
            </div>

Full code:

<template>
  <div class="overflow-auto h-full bg-gray-100">
    <Disclosure as="nav" :class="['sticky top-0 z-10 shadow-md']" v-slot="{ open }">
      <div class="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
        <div class="relative flex h-14 items-center justify-between">
          <div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
            <DisclosureButton class="inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white">
              <Bars3Icon v-if="!open" class="block h-6 w-6" aria-hidden="true" />
              <XMarkIcon v-else class="block h-6 w-6" aria-hidden="true" />
            </DisclosureButton>
          </div>

          <div class="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
            <div class="flex flex-shrink-0 items-center">
              <img class="block h-8 w-auto lg:hidden" src="https://tailwindui.com/img/logos/mark.svg?color=white" alt="Your Company" />
              <img class="hidden h-8 w-auto lg:block" src="https://tailwindui.com/img/logos/mark.svg?color=white" alt="Your Company" />
            </div>

            <div class="hidden sm:ml-6 sm:block">
              <div class="flex space-x-4">
                <a
                  v-for="item in navigation"
                  :key="item.name"
                  :href="item.href"
                  :class="[
                    'px-3 py-5 text-sm font-medium',
                    item.current ?
                      'border-b-2 border-white text-white' :
                      'text-white',
                  ]"
                  :aria-current="item.current ? 'page' : undefined">{{ item.name }}</a>
              </div>
            </div>
          </div>

          <div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
            <div class="flex space-x-1 bg-white rounded-full px-2 py-1">
              <button
                class="rounded-full"
                v-for="(themeColor, index) in listTheme"
                :key="index"
                :class="[classes('bg-600'), !themeColor.current ? 'p-3' : 'p-1']"
                @click="color = themeColor.name"
              >
                <CheckIcon v-if="themeColor.current" class="text-white w-4 h-4" />
              </button>
            </div>
          </div>
        </div>
      </div>

      <DisclosurePanel class="sm:hidden">
        <div class="space-y-1 px-2 pt-2 pb-3">
          <DisclosureButton v-for="item in navigation" :key="item.name" as="a" :href="item.href" :class="[item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white', 'block px-3 py-2 rounded-md text-base font-medium']" :aria-current="item.current ? 'page' : undefined">{{ item.name }}</DisclosureButton>
        </div>
      </DisclosurePanel>
    </Disclosure>

    <main>
      <div class="py-10">
        <div class="relative flex flex-wrap justify-center items-center gap-6 select-none">
          <div
            class="w-full max-w-sm bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700"
            v-for="(n, index) in 20"
            :key="index"
          >
            <a href="#">
              <img class="p-8 rounded-t-lg" src="https://flowbite.com/docs/images/products/apple-watch.png" alt="product image" />
            </a>

            <div class="px-5 pb-5">
              <a href="#">
                <h5 class="text-xl font-medium tracking-tight text-gray-900 dark:text-white">Apple Watch Series 7 GPS, Aluminum Case, Starlight Sport</h5>
              </a>

              <div class="flex items-center mt-2.5 mb-5">
                <svg aria-hidden="true" class="w-5 h-5 text-yellow-300" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
                <svg aria-hidden="true" class="w-5 h-5 text-yellow-300" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
                <svg aria-hidden="true" class="w-5 h-5 text-yellow-300" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
                <svg aria-hidden="true" class="w-5 h-5 text-yellow-300" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
                <svg aria-hidden="true" class="w-5 h-5 text-yellow-300" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
                <span :class="['ml-3 mr-2 px-2.5 py-0.5 text-xs font-semibold rounded', classes('bg-100 text-600')]">5.0</span>
              </div>

              <div class="flex items-center justify-between">
                <span class="text-2xl font-medium text-gray-900 dark:text-white">9</span>
                <a href="#" :class="['text-white font-medium rounded-lg text-sm px-5 py-2.5 text-center focus:outline-none focus:ring-0', classes('bg-600 hover:bg-700')]">Add to cart</a>
              </div>
            </div>
          </div>
        </div>
      </div>
    </main>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { Disclosure, DisclosureButton, DisclosurePanel, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'
import { Bars3Icon, BellIcon, XMarkIcon } from '@heroicons/vue/24/outline'
import { CheckIcon } from '@heroicons/vue/24/solid'

const navigation = [
  { name: 'Dashboard', href: '#', current: true },
  { name: 'Team', href: '#', current: false },
  { name: 'Projects', href: '#', current: false },
  { name: 'Calendar', href: '#', current: false },
]

const listTheme = ref([
  { name: 'indigo', current: true },
  { name: 'emerald', current: false },
  { name: 'blue', current: false },
  { name: 'orange', current: false },
  { name: 'yellow', current: false },
  { name: 'red', current: false },
])
const color = ref(listTheme.value[0].name)

function classes(classes) {
  let arrayClasses = []
  let variableClass = ''

  if (typeof classes === 'string') {
    arrayClasses = classes.split(' ')
  }

  arrayClasses.forEach(c => {
    variableClass += c.replace('-', `-${color.value}-`)

    if (variableClass.length > 1) variableClass += ' '
  })

  return variableClass
}
</script>
0 likes
0 replies

Please or to participate in this conversation.