Frontend

React JS

React JS Example

We provide a Frontend React JS library that integrates nicely with HeadlessUI by Tailwind.

Installation

To get started, install Headless UI and Sigmie React via npm:

npm install -D @headlessui/react @sigmie/react @heroicons/vue

Example

Here is the above example to get you started:

import { Fragment, useEffect, useRef, useState } from 'react'
import { Combobox, Dialog, Transition } from '@headlessui/react'
import { SigmieSearch } from '@sigmie/react'

export default function Search() {
  let [isOpen, setIsOpen] = useState(true)
  let [query, setQuery] = useState('')
  const searchInput = useRef();

  let visit = (value) => {
    console.log(value);
  }

  function handleKeyDown(e) {
    // On Esc
    if (e.keyCode === 27) {
      searchInput.current?.blur();
    }

    // On CMD + K
    if (e.keyCode === 75 && e.metaKey) {
      setIsOpen(true)
      searchInput.current?.focus();
      searchInput.current?.click();
    }
  }

  function closeModal() {
    setIsOpen(false)
  }

  function openModal() {
    setIsOpen(true)
  }

  let addKeydownListener = function () {
    document.addEventListener("keydown", handleKeyDown);

  };

  let removeKeydownListener = function () {
    document.removeEventListener('keydown', handleKeyDown);
  };

  useEffect(() => {
    addKeydownListener();
    return () => {
      removeKeydownListener()
    }
  });

  return (
    <>
      <div className='bg-white min-h-screen'>
        <div className={`relative max-w-xl mx-auto w-full cursor-default text-left shadow-md focus:outline-none focus-visible:ring-0 focus-visible:ring-red-500 focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-teal-300 sm:text-sm  rounded-t-md rounded-lg`}>
          <button
            onClick={openModal}
            className="w-full shadow-lg items-center rounded-lg px-4 absolute bg-zinc-800 top-10 z-10 cursor-pointer text-left focus:outline-none ring-0  py-3 pl-4 text-sm leading-5 text-zinc-300 outline-none flex flex-row justify-between"
          >
            <div>
              Search...
            </div>

            <div className="flex flex-row items-center space-x-2">
              <div
                className="bg-black px-2 py-1 rounded-md text-zinc-300 font-semibold text-xs"
              >
                CMD/CTR
              </div>
              <div className="">+</div>
              <div
                className="bg-black px-2 py-1 rounded-md text-zinc-300 font-semibold text-xs"
              >
                K
              </div>
            </div>

          </button>
        </div>

        <Transition appear show={isOpen} as={Fragment}>
          <Dialog as="div" className="relative z-10" onClose={closeModal}>
            <Transition.Child
              as={Fragment}
              enter="ease-out duration-300"
              enterFrom="opacity-0"
              enterTo="opacity-100"
              leave="ease-in duration-200"
              leaveFrom="opacity-100"
              leaveTo="opacity-0"
            >
              <div className="fixed inset-0 bg-black bg-opacity-75" />
            </Transition.Child>
            <div className="fixed inset-0 overflow-y-auto">
              <div className="flex min-h-full items-center justify-center p-4 text-center">
                <Transition.Child
                  as={Fragment}
                  enter="ease-out duration-300"
                  enterFrom="opacity-0 scale-95"
                  enterTo="opacity-100 scale-100"
                  leave="ease-in duration-200"
                  leaveFrom="opacity-100 scale-100"
                  leaveTo="opacity-0 scale-95"
                >
                  <Dialog.Panel className="transition-all w-full absolute top-20">
                    <SigmieSearch
                      apiKey="Dw4cThA9iGZwPw0r8VFMEiZwWGzroKFg6C0nb39D"
                      query={query}
                      perPage={5}
                      filter=""
                      search="testing"
                      applicationId="svvhug7c38lsrznsn"
                      debounceMs={150}
                    >
                      {({ hits, total, loading }) =>
                        <div>
                          <main className={`max-w-xl mx-auto w-full flex flex-col space-y-4 shadow-xl`}>
                            <Combobox value={query} onChange={visit}>
                              {({ open }) => (
                                <div className="relative">
                                  <div className={`relative bg-zinc-800 w-full cursor-default text-left shadow-md focus:outline-none focus-visible:ring-0 focus-visible:ring-red-500 focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-teal-300 sm:text-sm  rounded-t-md ${open ? 'rounded-t-lg' : 'rounded-lg'}`}>
                                    <Combobox.Button as='div'>
                                      <Combobox.Input
                                        ref={searchInput}
                                        className={`w-full focus:outline-none ring-0 bg-transparent  py-3 pl-4 text-sm leading-5 text-zinc-300 outline-none`}
                                        onChange={(event) => setQuery(event.target.value)}
                                      />
                                    </Combobox.Button>
                                    <Combobox.Button className="absolute inset-y-0 right-0 flex items-center pr-4 text-zinc-400 text-sm">
                                      <div className="flex flex-row items-center space-x-2">
                                        <div
                                          className="bg-black px-2 py-1 rounded-md text-zinc-300 font-semibold text-xs"
                                        >
                                          ESC
                                        </div>
                                      </div>
                                    </Combobox.Button>
                                  </div>
                                  <Transition
                                    as={Fragment}
                                    leave=""
                                    leaveFrom="opacity-100"
                                    leaveTo="opacity-0"
                                    afterLeave={() => setQuery('')}
                                  >
                                    <div className="h-auto pb-12">
                                      <Combobox.Options className="relative bg-zinc-800 max-h-[800px] w-full overflow-auto text-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
                                        {total === 0 && query !== '' ? (
                                          <div className="relative cursor-default select-none py-2 px-4 text-zinc-400 h-40 flex flex-row items-center text-lg">
                                            <div className="mx-auto">
                                              <svg width="40" height="40" viewBox="0 0 20 20" fill="none" fillRule="evenodd" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round">
                                                <path d="M15.5 4.8c2 3 1.7 7-1 9.7h0l4.3 4.3-4.3-4.3a7.8 7.8 0 01-9.8 1m-2.2-2.2A7.8 7.8 0 0113.2 2.4M2 18L18 2"></path>
                                              </svg>
                                            </div>

                                            <div className="mx-auto">
                                              <div className="w-56 text-center">
                                                No results for "<span className="text-zinc-100 font-medium">{
                                                  query
                                                }</span
                                                >"
                                              </div>
                                            </div>
                                          </div>
                                        ) : (
                                          Object.values(hits).map((hit) => (
                                            <Combobox.Option
                                              key={hit._id}
                                              className={({ active }) =>
                                                `relative cursor-default select-none py-2  ${active ? ' text-white' : 'text-zinc-400'
                                                }`
                                              }
                                              value={hit}
                                            >
                                              {({ selected, active }) => (
                                                <div className={`relative cursor-default select-none pt-2 pb-4 px-4 flex flex-col items-center border-t border-zinc-800 ${active ? 'bg-black text-white' : 'text-zinc-400'}`}>
                                                  <div className="block p-3 overflow-hidden max-w-lg border-zinc-700 rounded-md border">
                                                    {JSON.stringify(hit) }
                                                  </div>
                                                </div>
                                              )}
                                            </Combobox.Option>
                                          ))
                                        )}
                                      </Combobox.Options>
                                      <div
                                        className="absolute rounded-b-lg bottom-0 h-12 text-zinc-500 bg-zinc-800 w-full px-4 py-2 flex flex-row justify-between items-center border-t border-zinc-700"
                                      >
                                        <div
                                          className="flex flex-row items-center space-x-2"
                                        >
                                          <div className='bg-black px-2 py-1 rounded-md text-zinc-300 text-xs'>
                                            <svg width="15" height="15"><g fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1.8"><path d="M7.5 3.5v8M10.5 8.5l-3 3-3-3"></path></g></svg>
                                          </div>
                                          <div className='bg-black px-2 py-1 rounded-md text-zinc-300 text-xs'>
                                            <svg width="15" height="15"><g fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1.8"><path d="M7.5 11.5v-8M10.5 6.5l-3-3-3 3"></path></g></svg>
                                          </div>
                                          <div className="text-zinc-300 text-sm">to navigate</div>
                                        </div>

                                        <div
                                          className="flex flex-row items-center space-x-2"
                                        >
                                          <div className='bg-black px-2 py-1 rounded-md text-zinc-300 font-semibold text-xs'>
                                            ESC
                                          </div>
                                          <div className="text-zinc-300 text-sm">to close</div>
                                        </div>

                                        <div className="flex flex-row items-center space-x-2">
                                          <div
                                            className="bg-black px-2 py-1 rounded-md text-zinc-300 font-semibold text-xs"
                                          >
                                            ENTER
                                          </div>
                                          <div className="text-zinc-300 text-sm">to visit</div>
                                        </div>
                                      </div>
                                    </div>
                                  </Transition>
                                </div>
                              )
                              }
                            </Combobox >
                          </main >
                        </div >}
                    </SigmieSearch >
                  </Dialog.Panel>
                </Transition.Child>
              </div>
            </div>
          </Dialog>
        </Transition>
      </div>
    </>
  )
}
Previous
Codepen