Datepicker

Example
x-model:

<div x-data="{ model: '' }" class="px-6">
  <div
    x-data="datepicker"
    x-model="model"
    class="w-[320px] overflow-hidden rounded-md border border-dark-300 bg-white text-center text-text-800 shadow-md dark:border-dark-700 dark:bg-dark-800 dark:text-text-300 mx-auto"
  >
    <div class="my-4 grid grid-flow-col grid-cols-6">
      <button
        x-bind="prevYearButton"
        class="mx-auto flex flex-col justify-center rounded-sm px-2 py-1 leading-none focus:outline-hidden focus:ring-2 focus:ring-primary-200 dark:focus:ring-primary-400"
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="16"
          height="16"
          fill="currentColor"
          viewBox="0 0 16 16"
        >
          <path
            fill-rule="evenodd"
            d="M8.354 1.646a.5.5 0 0 1 0 .708L2.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0"
          />
          <path
            fill-rule="evenodd"
            d="M12.354 1.646a.5.5 0 0 1 0 .708L6.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0"
          />
        </svg>
      </button>
      <button
        x-bind="prevMonthButton"
        class="mx-auto flex flex-col justify-center rounded-sm px-2 py-1 leading-none focus:outline-hidden focus:ring-2 focus:ring-primary-200 dark:focus:ring-primary-400"
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="16"
          height="16"
          fill="currentColor"
          viewBox="0 0 16 16"
        >
          <path
            fill-rule="evenodd"
            d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0"
          />
        </svg>
      </button>
      <div
        x-text="currentDate"
        class="col-span-2 inline-block font-bold"
      ></div>
      <button
        x-bind="nextMonthButton"
        class="mx-auto flex flex-col justify-center rounded-sm px-2 py-1 leading-none focus:outline-hidden focus:ring-2 focus:ring-primary-200 dark:focus:ring-primary-400"
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="16"
          height="16"
          fill="currentColor"
          viewBox="0 0 16 16"
        >
          <path
            fill-rule="evenodd"
            d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708"
          />
        </svg>
      </button>
      <button
        x-bind="nextYearButton"
        class="mx-auto flex flex-col justify-center rounded-sm px-2 py-1 leading-none focus:outline-hidden focus:ring-2 focus:ring-primary-200 dark:focus:ring-primary-400"
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="16"
          height="16"
          fill="currentColor"
          viewBox="0 0 16 16"
        >
          <path
            fill-rule="evenodd"
            d="M3.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L9.293 8 3.646 2.354a.5.5 0 0 1 0-.708"
          />
          <path
            fill-rule="evenodd"
            d="M7.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L13.293 8 7.646 2.354a.5.5 0 0 1 0-.708"
          />
        </svg>
      </button>
    </div>
    <div class="mb-3 grid grid-cols-7 px-2">
      <template x-for="weekday in weekdays">
        <div
          x-text="weekday"
          class="text-sm font-semibold dark:text-text-300"
        ></div>
      </template>
    </div>
    <div class="relative mb-3 grid grid-cols-7 justify-items-center gap-2 px-2">
      <template x-for="d in days" :key="getDayKey()">
        <button
          x-bind="day"
          x-text="d.getDate()"
          class="flex h-9 w-9 cursor-pointer items-center justify-center rounded-full py-1 text-sm font-semibold"
          class-default="hover:bg-secondary-200 dark:hover:bg-dark-700"
          class-today="border border-primary-400 font-bold! text-primary-400 dark:text-primary-400"
          class-adjacent="text-text-800/20 dark:text-text-200/10"
          class-selected="bg-primary-400 text-white hover:bg-primary-600 dark:bg-primary-500 dark:text-text-200 dark:hover:bg-primary-700"
          class-selected-range="bg-primary-400 text-white hover:bg-primary-600 dark:bg-primary-500 dark:text-text-200 dark:hover:bg-primary-700"
          class-partially-selected="bg-secondary-300 text-text-800 dark:bg-dark-700 dark:text-text-300"
          class-disabled="text-text-800/20 dark:text-text-200/10 pointer-events-none"
        ></button>
      </template>
    </div>
    <div
      x-text="todayFormatted"
      class="bg-gray-100 py-1 text-sm font-semibold dark:bg-dark-700 dark:text-text-300"
    ></div>
  </div>
  <div class="font-mono text-lg mx-auto w-max mt-4">
    x-model: <span x-text="JSON.stringify(model)"></span>
  </div>
</div>

Usage

<script defer src="https://cdn.jsdelivr.net/npm/litewind-alpine@0.x.x/components/datepicker/dist/cdn.min.js"></script>

The data for the component is provided by the datepicker function in the x-data directive and the props in the data-* attributes.

Props

data-range
false Boolean

Allows selection of date ranges. Changing this prop resets component.


data-monday-first-weekday
true Boolean

Week starts on Monday


data-adjacent-months
true Boolean

If true, days from the previous and next months are displayed. Classes for these days can be customized using the class-adjacent attribute in the template. Adjacent days are selectable.


data-locale
en-GB String

This prop is only used to set the names of the months and weekdays and to format date in the components footer. It does not modify format of the x-model date which is always YYYY-MM-DD.

x-model

x-model
String Array

The type of the x-model is a string in single mode and an array of two strings in range mode. Strings are always in th YYYY-MM-DD format.

Events

datepicker-selection-complete

Event dispatched after a selection is completed. This can be useful, for example, for closing an expandable datepicker in a dropdown.

Range mode

The datepicker allows selecting date ranges when the data-range prop is enabled. In range mode, instead of a single date string, the component emits an array of two strings.

Example
x-model:

<div x-data="{ model: [] }" class="px-6">
  <div
    x-data="datepicker"
    data-range="true"
    x-model="model"
    class="w-[320px] overflow-hidden rounded-md border border-dark-300 bg-white text-center text-text-800 shadow-md dark:border-dark-700 dark:bg-dark-800 dark:text-text-300 mx-auto"
  >
    <div class="my-4 grid grid-flow-col grid-cols-6">
      <button
        x-bind="prevYearButton"
        class="mx-auto flex flex-col justify-center rounded-sm px-2 py-1 leading-none focus:outline-hidden focus:ring-2 focus:ring-primary-200 dark:focus:ring-primary-400"
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="16"
          height="16"
          fill="currentColor"
          viewBox="0 0 16 16"
        >
          <path
            fill-rule="evenodd"
            d="M8.354 1.646a.5.5 0 0 1 0 .708L2.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0"
          />
          <path
            fill-rule="evenodd"
            d="M12.354 1.646a.5.5 0 0 1 0 .708L6.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0"
          />
        </svg>
      </button>
      <button
        x-bind="prevMonthButton"
        class="mx-auto flex flex-col justify-center rounded-sm px-2 py-1 leading-none focus:outline-hidden focus:ring-2 focus:ring-primary-200 dark:focus:ring-primary-400"
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="16"
          height="16"
          fill="currentColor"
          viewBox="0 0 16 16"
        >
          <path
            fill-rule="evenodd"
            d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0"
          />
        </svg>
      </button>
      <div
        x-text="currentDate"
        class="col-span-2 inline-block font-bold"
      ></div>
      <button
        x-bind="nextMonthButton"
        class="mx-auto flex flex-col justify-center rounded-sm px-2 py-1 leading-none focus:outline-hidden focus:ring-2 focus:ring-primary-200 dark:focus:ring-primary-400"
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="16"
          height="16"
          fill="currentColor"
          viewBox="0 0 16 16"
        >
          <path
            fill-rule="evenodd"
            d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708"
          />
        </svg>
      </button>
      <button
        x-bind="nextYearButton"
        class="mx-auto flex flex-col justify-center rounded-sm px-2 py-1 leading-none focus:outline-hidden focus:ring-2 focus:ring-primary-200 dark:focus:ring-primary-400"
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="16"
          height="16"
          fill="currentColor"
          viewBox="0 0 16 16"
        >
          <path
            fill-rule="evenodd"
            d="M3.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L9.293 8 3.646 2.354a.5.5 0 0 1 0-.708"
          />
          <path
            fill-rule="evenodd"
            d="M7.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L13.293 8 7.646 2.354a.5.5 0 0 1 0-.708"
          />
        </svg>
      </button>
    </div>
    <div class="mb-3 grid grid-cols-7 px-2">
      <template x-for="weekday in weekdays">
        <div
          x-text="weekday"
          class="text-sm font-semibold dark:text-text-300"
        ></div>
      </template>
    </div>
    <div class="relative mb-3 grid grid-cols-7 justify-items-center gap-2 px-2">
      <template x-for="d in days" :key="getDayKey()">
        <button
          x-bind="day"
          x-text="d.getDate()"
          class="flex h-9 w-9 cursor-pointer items-center justify-center rounded-full py-1 text-sm font-semibold"
          class-default="hover:bg-secondary-200 dark:hover:bg-dark-700"
          class-today="border border-primary-400 font-bold! text-primary-400 dark:text-primary-400"
          class-adjacent="text-text-800/20 dark:text-text-200/10"
          class-selected="bg-primary-400 text-white hover:bg-primary-600 dark:bg-primary-500 dark:text-text-200 dark:hover:bg-primary-700"
          class-selected-range="bg-primary-400 text-white hover:bg-primary-600 dark:bg-primary-500 dark:text-text-200 dark:hover:bg-primary-700"
          class-partially-selected="bg-secondary-300 text-text-800 dark:bg-dark-700 dark:text-text-300"
          class-disabled="text-text-800/20 dark:text-text-200/10 pointer-events-none"
        ></button>
      </template>
    </div>
    <div
      x-text="todayFormatted"
      class="bg-gray-100 py-1 text-sm font-semibold dark:bg-dark-700 dark:text-text-300"
    ></div>
  </div>
  <div class="font-mono text-lg mx-auto w-max mt-4">
    x-model: <span x-text="JSON.stringify(model)"></span>
  </div>
</div>

Datepicker in dropdown

By default, datepicker is a standalone component. You can easy turn it into a standard expandable picker for inputs by placing it inside a dropdown component menu. The dropdown should have the data-auto-close prop disabled to prevent menu from closing. To close the menu after selection, use the @datepicker-selection-complete event.

Example

<div x-data="{ date: '' }">
  <div
    x-data="dropdown"
    data-auto-close="false"
    @datepicker-selection-complete="close()"
  >
    <div
      x-data="input"
      data-clearable="true"
      x-model="date"
      x-bind="trigger"
      class="flex flex-1 items-center rounded-sm border px-3 py-2 outline-hidden transition-shadow duration-200 focus-within:ring-3 focus:outline-hidden"
      class-default="border-gray-300 bg-white focus-within:border-gray-400 focus-within:ring-primary-200 dark:border-dark-600 dark:bg-dark-800 dark:text-text-300 dark:focus-within:ring-primary-300"
      class-valid="border-success-300 bg-white text-success-600 focus-within:ring-success-200 dark:border-success-400 dark:bg-dark-800 dark:text-success-600 dark:focus-within:ring-success-300"
      class-invalid="border-danger-300 bg-white text-danger-600 focus-within:ring-danger-200 dark:border-danger-400 dark:bg-dark-800 dark:text-danger-600 dark:focus-within:ring-danger-300"
    >
      <div data-icon class="mr-3 empty:hidden"></div>
      <div data-prepend class="mr-3 empty:hidden"></div>
      <div class="mr-3 flex flex-1 flex-wrap">
        <input
          x-bind="input"
          type="text"
          class="w-full min-w-0 flex-1 border-0 bg-transparent p-0 outline-hidden focus:min-w-[64px] focus:outline-hidden"
        />
      </div>
      <div data-append class="mr-3 empty:hidden"></div>
      <div class="flex items-center gap-x-2">
        <div x-bind="loader">
          <svg
            viewBox="25 25 50 50"
            fill="none"
            class="h-5 w-5 animate-spinner-rotate"
          >
            <circle
              cx="50"
              cy="50"
              r="20"
              stroke="currentColor"
              stroke-width="4"
              stroke-miterlimit="10"
              stroke-linecap="round"
              class="animate-spinner-dash"
            />
          </svg>
        </div>
        <button x-bind="clearButton" @click="clear()" class="flex items-center">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="16"
            height="16"
            fill="currentColor"
            class="h-5 w-5 opacity-70"
            viewBox="0 0 16 16"
          >
            <path
              d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8z"
            />
          </svg>
        </button>
      </div>
    </div>
    <div
      x-bind="menu"
      x-cloak
      x-alt-transition='{
        "enter": ["opacity-0 scale-y-50", "transition ease-out duration-100 origin-top", "opacity-100"],
        "leave": ["opacity-100", "transition ease-in duration-100 origin-top", "opacity-0 scale-y-50"]
      }'
      class="z-50 w-[320px] rounded-md border border-gray-200 bg-white shadow-md dark:border-dark-700 dark:bg-dark-800 dark:text-text-300"
    >
      <div x-data="datepicker" x-model="date" class="w-[320px] text-center">
        <div class="my-4 grid grid-flow-col grid-cols-6">
          <button
            x-bind="prevYearButton"
            class="mx-auto flex flex-col justify-center rounded-sm px-2 py-1 leading-none focus:ring-2 focus:ring-primary-200 focus:outline-hidden dark:focus:ring-primary-400"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="16"
              height="16"
              fill="currentColor"
              viewBox="0 0 16 16"
            >
              <path
                fill-rule="evenodd"
                d="M8.354 1.646a.5.5 0 0 1 0 .708L2.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0"
              />
              <path
                fill-rule="evenodd"
                d="M12.354 1.646a.5.5 0 0 1 0 .708L6.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0"
              />
            </svg>
          </button>
          <button
            x-bind="prevMonthButton"
            class="mx-auto flex flex-col justify-center rounded-sm px-2 py-1 leading-none focus:ring-2 focus:ring-primary-200 focus:outline-hidden dark:focus:ring-primary-400"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="16"
              height="16"
              fill="currentColor"
              viewBox="0 0 16 16"
            >
              <path
                fill-rule="evenodd"
                d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0"
              />
            </svg>
          </button>
          <div
            x-text="currentDate"
            class="col-span-2 inline-block font-bold"
          ></div>
          <button
            x-bind="nextMonthButton"
            class="mx-auto flex flex-col justify-center rounded-sm px-2 py-1 leading-none focus:ring-2 focus:ring-primary-200 focus:outline-hidden dark:focus:ring-primary-400"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="16"
              height="16"
              fill="currentColor"
              viewBox="0 0 16 16"
            >
              <path
                fill-rule="evenodd"
                d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708"
              />
            </svg>
          </button>
          <button
            x-bind="nextYearButton"
            class="mx-auto flex flex-col justify-center rounded-sm px-2 py-1 leading-none focus:ring-2 focus:ring-primary-200 focus:outline-hidden dark:focus:ring-primary-400"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="16"
              height="16"
              fill="currentColor"
              viewBox="0 0 16 16"
            >
              <path
                fill-rule="evenodd"
                d="M3.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L9.293 8 3.646 2.354a.5.5 0 0 1 0-.708"
              />
              <path
                fill-rule="evenodd"
                d="M7.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L13.293 8 7.646 2.354a.5.5 0 0 1 0-.708"
              />
            </svg>
          </button>
        </div>
        <div class="mb-3 grid grid-cols-7 px-2">
          <template x-for="weekday in weekdays">
            <div
              x-text="weekday"
              class="text-sm font-semibold dark:text-text-300"
            ></div>
          </template>
        </div>
        <div
          class="relative mb-3 grid grid-cols-7 justify-items-center gap-2 px-2"
        >
          <template x-for="d in days" :key="getDayKey()">
            <button
              x-bind="day"
              x-text="d.getDate()"
              class="flex h-9 w-9 cursor-pointer items-center justify-center rounded-full py-1 text-sm font-semibold"
              class-default="hover:bg-secondary-200 dark:hover:bg-dark-700"
              class-today="border border-primary-400 font-bold! text-primary-400 dark:text-primary-400"
              class-adjacent="text-text-800/20 dark:text-text-200/10"
              class-selected="bg-primary-400 text-white hover:bg-primary-600 dark:bg-primary-500 dark:text-text-200 dark:hover:bg-primary-700"
              class-selected-range="bg-primary-400 text-white hover:bg-primary-600 dark:bg-primary-500 dark:text-text-200 dark:hover:bg-primary-700"
              class-partially-selected="bg-secondary-300 text-text-800 dark:bg-dark-700 dark:text-text-300"
              class-disabled="text-text-800/20 dark:text-text-200/10 pointer-events-none"
            ></button>
          </template>
        </div>
        <div
          x-text="todayFormatted"
          class="bg-gray-100 py-1 text-sm font-semibold dark:bg-dark-700 dark:text-text-300"
        ></div>
      </div>
    </div>
  </div>
</div>
Litewind-alpine 0.1.0