Form

<form x-data="appointmentModal" method="get" action="" class="relative inline-flex flex-col gap-2 md:max-w-[662px] w-full">
    <div x-ref="modalButton" class="inline-flex items-center justify-between rounded-full bg-light-white shadow-lg">
        <button type="button" class="text-neutral-800 text-left px-6 md:px-8 py-2 md:py-4" @click="showModal">
            <p class="hidden md:block">Sujet</p>
            <p :class="modalSelectedOption ? 'text-neutral-800 font-semibold' : 'text-neutral-500'" x-text="modalSelectedOption ? modalSelectedOption : 'Quel est le motif du rendez-vous ?'" class="hidden md:block text-nowrap truncate max-w-[330px]">Quel est le motif du rendez-vous ?</p>
            <p class="text-neutral-800 block md:hidden">Prendre rendez-vous</p>
        </button>
        <div class="md:px-3.5 p-2 md:py-0">
            <button :class="modalSwitched ? 'btn-audio' : 'btn-dark'" class="btn md:btn-icons btn-size-md btn-leading-icon max-md:btn-only-icon">
                <div x-show="!modalSwitched"><svg class=" shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path fill-rule="evenodd" clip-rule="evenodd" d="M8 1.25C8.41421 1.25 8.75 1.58579 8.75 2V3.25H15.25V2C15.25 1.58579 15.5858 1.25 16 1.25C16.4142 1.25 16.75 1.58579 16.75 2V3.25H20C21.5188 3.25 22.75 4.48122 22.75 6V20C22.75 21.5188 21.5188 22.75 20 22.75H4C2.48122 22.75 1.25 21.5188 1.25 20V6C1.25 4.48122 2.48122 3.25 4 3.25H7.25V2C7.25 1.58579 7.58579 1.25 8 1.25ZM7.25 4.75H4C3.30964 4.75 2.75 5.30964 2.75 6V8.25H21.25V6C21.25 5.30964 20.6904 4.75 20 4.75H16.75V6C16.75 6.41421 16.4142 6.75 16 6.75C15.5858 6.75 15.25 6.41421 15.25 6V4.75H8.75V6C8.75 6.41421 8.41421 6.75 8 6.75C7.58579 6.75 7.25 6.41421 7.25 6V4.75ZM21.25 9.75H2.75V20C2.75 20.6904 3.30964 21.25 4 21.25H20C20.6904 21.25 21.25 20.6904 21.25 20V9.75ZM12 14.5C12.5523 14.5 13 14.0523 13 13.5C13 12.9477 12.5523 12.5 12 12.5C11.4477 12.5 11 12.9477 11 13.5C11 14.0523 11.4477 14.5 12 14.5ZM8 17.5C8 18.0523 7.55228 18.5 7 18.5C6.44772 18.5 6 18.0523 6 17.5C6 16.9477 6.44772 16.5 7 16.5C7.55228 16.5 8 16.9477 8 17.5ZM12 18.5C12.5523 18.5 13 18.0523 13 17.5C13 16.9477 12.5523 16.5 12 16.5C11.4477 16.5 11 16.9477 11 17.5C11 18.0523 11.4477 18.5 12 18.5ZM17 14.5C17.5523 14.5 18 14.0523 18 13.5C18 12.9477 17.5523 12.5 17 12.5C16.4477 12.5 16 12.9477 16 13.5C16 14.0523 16.4477 14.5 17 14.5ZM17 18.5C17.5523 18.5 18 18.0523 18 17.5C18 16.9477 17.5523 16.5 17 16.5C16.4477 16.5 16 16.9477 16 17.5C16 18.0523 16.4477 18.5 17 18.5Z" fill="currentColor" />
                    </svg>
                </div>
                <div x-show="modalSwitched"><svg class=" shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path fill-rule="evenodd" clip-rule="evenodd" d="M8 1.25C8.41421 1.25 8.75 1.58579 8.75 2V3.25H15.25V2C15.25 1.58579 15.5858 1.25 16 1.25C16.4142 1.25 16.75 1.58579 16.75 2V3.25H20C21.5188 3.25 22.75 4.48122 22.75 6V20C22.75 21.5188 21.5188 22.75 20 22.75H4C2.48122 22.75 1.25 21.5188 1.25 20V6C1.25 4.48122 2.48122 3.25 4 3.25H7.25V2C7.25 1.58579 7.58579 1.25 8 1.25ZM7.25 4.75H4C3.30964 4.75 2.75 5.30964 2.75 6V8.25H21.25V6C21.25 5.30964 20.6904 4.75 20 4.75H16.75V6C16.75 6.41421 16.4142 6.75 16 6.75C15.5858 6.75 15.25 6.41421 15.25 6V4.75H8.75V6C8.75 6.41421 8.41421 6.75 8 6.75C7.58579 6.75 7.25 6.41421 7.25 6V4.75ZM21.25 9.75H2.75V20C2.75 20.6904 3.30964 21.25 4 21.25H20C20.6904 21.25 21.25 20.6904 21.25 20V9.75ZM12 14.5C12.5523 14.5 13 14.0523 13 13.5C13 12.9477 12.5523 12.5 12 12.5C11.4477 12.5 11 12.9477 11 13.5C11 14.0523 11.4477 14.5 12 14.5ZM8 17.5C8 18.0523 7.55228 18.5 7 18.5C6.44772 18.5 6 18.0523 6 17.5C6 16.9477 6.44772 16.5 7 16.5C7.55228 16.5 8 16.9477 8 17.5ZM12 18.5C12.5523 18.5 13 18.0523 13 17.5C13 16.9477 12.5523 16.5 12 16.5C11.4477 16.5 11 16.9477 11 17.5C11 18.0523 11.4477 18.5 12 18.5ZM17 14.5C17.5523 14.5 18 14.0523 18 13.5C18 12.9477 17.5523 12.5 17 12.5C16.4477 12.5 16 12.9477 16 13.5C16 14.0523 16.4477 14.5 17 14.5ZM17 18.5C17.5523 18.5 18 18.0523 18 17.5C18 16.9477 17.5523 16.5 17 16.5C16.4477 16.5 16 16.9477 16 17.5C16 18.0523 16.4477 18.5 17 18.5Z" fill="currentColor" />
                    </svg>
                </div>
                <span class="hidden md:block" x-text="modalSwitched ? 'Prendre rendez-vous' : 'Prendre rendez-vous'">Prendre rendez-vous</span>
            </button>
        </div>
    </div>
    <div x-show="modalOpened" @click.outside="modalOpened = false" x-cloak x-transition class="absolute z-20 left-0 right-0 top-[calc(100%+8px)] bg-light-white p-10 flex flex-col gap-10 text-neutral-800 rounded-3xl shadow-lg">
        <div x-ref="switch" :class="modalSwitched ? 'before:translate-x-[calc(100%+2px)]' : ''" class="grid grid-cols-2 bg-neutral-150 p-2 gap-1 rounded-full relative before:transition-transform
         before:rounded-full before:mx-px before:my-2 before:absolute before:left-2 before:top-0 before:bottom-0 before:right-1/2 before:bg-light-white">
            <button @click="modalSwitched = false" type="button" :class="modalSwitched ? 'text-neutral-500' : 'text-neutral-800'" class="btn relative z-10 bg-transparent backdrop-blur-none justify-center text-xl py-2">Optique</button>
            <button @click="modalSwitched = true" type="button" :class="modalSwitched ? 'text-audio-600' : 'text-neutral-500'" class="btn relative z-10 bg-transparent backdrop-blur-none justify-center text-xl py-2 transition-colors">Audition</button>
        </div>
        <div class="flex flex-col gap-2" x-ref="selectors">
            <div>Quel est le motif du rendez-vous ?</div>
            <div x-show="!modalSwitched" x-cloak="">
                <div x-data="appointmentSelect" class="relative">
                    <button type="button" @click="openSelect" class="text-neutral-500 flex items-center text-neutral-800 justify-between w-full px-3.5 py-2.5 text-left border border-neutral-300 rounded-md shadow-sm text-sm">
                        <span :class="selected ? 'font-medium' : 'text-neutral-500'" class="truncate" x-text="selected ? selected.name : 'Choisir un motif'">Choisir un motif</span>
                        <svg class=" shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path fill-rule="evenodd" clip-rule="evenodd" d="M12.5303 14.5303C12.2374 14.8232 11.7626 14.8232 11.4697 14.5303L7.46967 10.5303C7.17678 10.2374 7.17678 9.76256 7.46967 9.46967C7.76256 9.17678 8.23744 9.17678 8.53033 9.46967L12 12.9393L15.4697 9.46967C15.7626 9.17678 16.2374 9.17678 16.5303 9.46967C16.8232 9.76256 16.8232 10.2374 16.5303 10.5303L12.5303 14.5303Z" fill="currentColor" />
                        </svg>
                    </button>
                    <div class="dropdown-content relative mt-2 shadow-none " x-show="show" x-transition x-cloak @click.outside="show = false">
                        <template x-for="option in options">
                            <button type="button" @click="select(option.id)" class="dropdown-item px-4 border-l border-r first-of-type:border-t first-of-type:rounded-t-md" :class="option.checked ? 'dropdown-item-checked' : ''">
                                <span class="max-w-full truncate" x-text="option.name"></span>
                                <svg class="dropdown-item-checkmark shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path fill-rule="evenodd" clip-rule="evenodd" d="M18.5303 7.46967C18.8232 7.76256 18.8232 8.23744 18.5303 8.53033L10.5303 16.5303C10.2374 16.8232 9.76256 16.8232 9.46967 16.5303L5.46967 12.5303C5.17678 12.2374 5.17678 11.7626 5.46967 11.4697C5.76256 11.1768 6.23744 11.1768 6.53033 11.4697L10 14.9393L17.4697 7.46967C17.7626 7.17678 18.2374 7.17678 18.5303 7.46967Z" fill="currentColor" />
                                </svg>
                            </button>
                        </template>
                    </div>
                    <select class="hidden" x-ref="select" name="subject">
                        <option value="" selected disabled hidden></option>
                        <option value="option-1">Vérifier ma vue (avec ordonnance)</option>
                        <option value="option-2">Vérifier ma vue (avec ordonnance) et être conseillé dans le choix de mes lunettes</option>
                        <option value="option-3">Être conseillé dans le choix de mes lunettes</option>
                        <option value="option-4">Être conseillé dans le choix de mes lentilles de contact</option>
                        <option value="option-5">Effectuer une réparation, un ajustement, un réglage de mes lunettes</option>
                        <option value="option-6">Réceptionner ma commande</option>
                    </select>
                </div>

            </div>
            <div x-show="modalSwitched" x-cloak="">
                <div x-data="appointmentSelect" class="relative">
                    <button type="button" @click="openSelect" class="text-neutral-500 flex items-center text-neutral-800 justify-between w-full px-3.5 py-2.5 text-left border border-neutral-300 rounded-md shadow-sm text-sm">
                        <span :class="selected ? 'font-medium' : 'text-neutral-500'" class="truncate" x-text="selected ? selected.name : 'Choisir un motif'">Choisir un motif</span>
                        <svg class=" shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path fill-rule="evenodd" clip-rule="evenodd" d="M12.5303 14.5303C12.2374 14.8232 11.7626 14.8232 11.4697 14.5303L7.46967 10.5303C7.17678 10.2374 7.17678 9.76256 7.46967 9.46967C7.76256 9.17678 8.23744 9.17678 8.53033 9.46967L12 12.9393L15.4697 9.46967C15.7626 9.17678 16.2374 9.17678 16.5303 9.46967C16.8232 9.76256 16.8232 10.2374 16.5303 10.5303L12.5303 14.5303Z" fill="currentColor" />
                        </svg>
                    </button>
                    <div class="dropdown-content relative mt-2 shadow-none " x-show="show" x-transition x-cloak @click.outside="show = false">
                        <template x-for="option in options">
                            <button type="button" @click="select(option.id)" class="dropdown-item px-4 border-l border-r first-of-type:border-t first-of-type:rounded-t-md" :class="option.checked ? 'dropdown-item-checked' : ''">
                                <span class="max-w-full truncate" x-text="option.name"></span>
                                <svg class="dropdown-item-checkmark shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path fill-rule="evenodd" clip-rule="evenodd" d="M18.5303 7.46967C18.8232 7.76256 18.8232 8.23744 18.5303 8.53033L10.5303 16.5303C10.2374 16.8232 9.76256 16.8232 9.46967 16.5303L5.46967 12.5303C5.17678 12.2374 5.17678 11.7626 5.46967 11.4697C5.76256 11.1768 6.23744 11.1768 6.53033 11.4697L10 14.9393L17.4697 7.46967C17.7626 7.17678 18.2374 7.17678 18.5303 7.46967Z" fill="currentColor" />
                                </svg>
                            </button>
                        </template>
                    </div>
                    <select class="hidden" x-ref="select" name="subject">
                        <option value="" selected disabled hidden></option>
                        <option value="option-1">Vérifier mon audition (sans ordonnance)</option>
                        <option value="option-2">Premier rendez-vous (avec ordonnance)</option>
                        <option value="option-3">Livraison des aides auditives</option>
                        <option value="option-4">Réglage des aides auditives - Début période d’essai</option>
                        <option value="option-5">Restitution des aides auditives - Fin période d’essai</option>
                        <option value="option-6">Rendez-vous de suivi (3 mois, 6 mois, 1 an, …)</option>
                        <option value="option-7">Réglage et/ou contrôle des aides auditives</option>
                        <option value="option-8">Service après vente - Nettoyage des aides auditives</option>
                        <option value="option-9">Renouvellement des aides aides auditives</option>
                        <option value="option-10">Fabrication de protections d’oreilles sur mesure</option>
                    </select>
                </div>

            </div>
        </div>

    </div>
</form>
<script>
    function appointmentModal() {
        return {
            modalSwitched: false,
            modalOpened: false,
            modalSelectedOption: null,
            showModal() {
                // desktop only
                if (window.innerWidth > 768) {
                    this.modalOpened = !this.modalOpened;
                    if (this.modalOpened) {
                        this.scrollToTrigger();
                    }
                }
            },
            scrollToTrigger() {
                const modalButtonBounding = this.$refs.modalButton.getBoundingClientRect();
                const offset = (window.innerHeight / 2) - (modalButtonBounding.height * 2);
                window.scrollTo({
                    behavior: 'smooth',
                    top: modalButtonBounding.top -
                        document.body.getBoundingClientRect().top -
                        offset,
                })
            }
        }
    }

    function appointmentSelect() {
        return {
            options: [],
            show: false,
            selected: null,
            init() {
                Array.from(this.$refs.select.options).forEach(option => {
                    if (!option.disabled)
                        this.options.push({
                            id: option.value,
                            name: option.text,
                            checked: option.selected
                        })
                });
            },
            openSelect() {
                this.show = !this.show;
            },
            select(id) {
                this.options = this.options.map(option => {
                    if (option.id === id) {
                        option.checked = true;
                        this.selected = option;
                    } else {
                        option.checked = false;
                    }
                    return option;
                });
                this.modalSelectedOption = this.selected.name;
                this.$refs.select.value = this.selected.id;
                this.scrollToTrigger()
                this.show = false;
                this.modalOpened = false;
            }
        }
    }
</script>
<form x-data="appointmentModal" method="get" action="" class="relative inline-flex flex-col gap-2 md:max-w-[662px] w-full">
    <div x-ref="modalButton" class="inline-flex items-center justify-between rounded-full bg-light-white shadow-lg">
        <button type="button" class="text-neutral-800 text-left px-6 md:px-8 py-2 md:py-4" @click="showModal">
            <p class="hidden md:block">Sujet</p>
            <p :class="modalSelectedOption ? 'text-neutral-800 font-semibold' : 'text-neutral-500'" x-text="modalSelectedOption ? modalSelectedOption : 'Quel est le motif du rendez-vous ?'" class="hidden md:block text-nowrap truncate max-w-[330px]">Quel est le motif du rendez-vous ?</p>
            <p class="text-neutral-800 block md:hidden">Prendre rendez-vous</p>
        </button>
        <div class="md:px-3.5 p-2 md:py-0">
            <button :class="modalSwitched ? 'btn-audio' : 'btn-dark'" class="btn md:btn-icons btn-size-md btn-leading-icon max-md:btn-only-icon">
                <div x-show="!modalSwitched">{% render "@icons-library--calendar" %}</div>
                <div x-show="modalSwitched">{% render "@icons-library--calendar" %}</div>
                <span class="hidden md:block" x-text="modalSwitched ? 'Prendre rendez-vous' : 'Prendre rendez-vous'" >Prendre rendez-vous</span>
            </button>
        </div>
    </div>
    <div x-show="modalOpened" @click.outside="modalOpened = false" x-cloak x-transition class="absolute z-20 left-0 right-0 top-[calc(100%+8px)] bg-light-white p-10 flex flex-col gap-10 text-neutral-800 rounded-3xl shadow-lg">
        <div x-ref="switch" :class="modalSwitched ? 'before:translate-x-[calc(100%+2px)]' : ''" class="grid grid-cols-2 bg-neutral-150 p-2 gap-1 rounded-full relative before:transition-transform
         before:rounded-full before:mx-px before:my-2 before:absolute before:left-2 before:top-0 before:bottom-0 before:right-1/2 before:bg-light-white">
            <button @click="modalSwitched = false" type="button" :class="modalSwitched ? 'text-neutral-500' : 'text-neutral-800'" class="btn relative z-10 bg-transparent backdrop-blur-none justify-center text-xl py-2">Optique</button>
            <button @click="modalSwitched = true" type="button" :class="modalSwitched ? 'text-audio-600' : 'text-neutral-500'" class="btn relative z-10 bg-transparent backdrop-blur-none justify-center text-xl py-2 transition-colors">Audition</button>
        </div>
        <div class="flex flex-col gap-2" x-ref="selectors">
            <div>Quel est le motif du rendez-vous ?</div>
            <div x-show="!modalSwitched" x-cloak="">
                {% render "@template-select" with optic_select %}
            </div>
            <div x-show="modalSwitched" x-cloak="">
                {% render "@template-select" with audio_select %}
            </div>
        </div>

    </div>
</form>
<script>

    function appointmentModal() {
        return {
            modalSwitched: false,
            modalOpened: false,
            modalSelectedOption: null,
            showModal() {
                // desktop only
                if (window.innerWidth > 768) {
                    this.modalOpened = !this.modalOpened;
                    if (this.modalOpened) {
                        this.scrollToTrigger();
                    }
                }
            },
            scrollToTrigger() {
                const modalButtonBounding = this.$refs.modalButton.getBoundingClientRect();
                const offset = (window.innerHeight/2)-(modalButtonBounding.height*2);
                window.scrollTo({
                    behavior: 'smooth',
                    top:
                        modalButtonBounding.top -
                        document.body.getBoundingClientRect().top -
                        offset,
                })
            }
        }
    }

    function appointmentSelect() {
        return {
            options: [],
            show: false,
            selected: null,
            init() {
                Array.from(this.$refs.select.options).forEach(option => {
                    if (!option.disabled)
                        this.options.push({
                            id: option.value,
                            name: option.text,
                            checked: option.selected
                        })
                });
            },
            openSelect() {
                this.show = !this.show;
            },
            select(id) {
                this.options = this.options.map(option => {
                    if (option.id === id) {
                        option.checked = true;
                        this.selected = option;
                    } else {
                        option.checked = false;
                    }
                    return option;
                });
                this.modalSelectedOption = this.selected.name;
                this.$refs.select.value = this.selected.id;
                this.scrollToTrigger()
                this.show = false;
                this.modalOpened = false;
            }
        }
    }

</script>
{
  "optic_select": {
    "x_data": "appointmentSelect",
    "placeholder": "Choisir un motif",
    "options": [
      {
        "value": "option-1",
        "text": "Vérifier ma vue (avec ordonnance)"
      },
      {
        "value": "option-2",
        "text": "Vérifier ma vue (avec ordonnance) et être conseillé dans le choix de mes lunettes"
      },
      {
        "value": "option-3",
        "text": "Être conseillé dans le choix de mes lunettes"
      },
      {
        "value": "option-4",
        "text": "Être conseillé dans le choix de mes lentilles de contact"
      },
      {
        "value": "option-5",
        "text": "Effectuer une réparation, un ajustement, un réglage de mes lunettes"
      },
      {
        "value": "option-6",
        "text": "Réceptionner ma commande"
      }
    ]
  },
  "audio_select": {
    "x_data": "appointmentSelect",
    "placeholder": "Choisir un motif",
    "options": [
      {
        "value": "option-1",
        "text": "Vérifier mon audition (sans ordonnance)"
      },
      {
        "value": "option-2",
        "text": "Premier rendez-vous (avec ordonnance)"
      },
      {
        "value": "option-3",
        "text": "Livraison des aides auditives"
      },
      {
        "value": "option-4",
        "text": "Réglage des aides auditives - Début période d’essai"
      },
      {
        "value": "option-5",
        "text": "Restitution des aides auditives - Fin période d’essai"
      },
      {
        "value": "option-6",
        "text": "Rendez-vous de suivi (3 mois, 6 mois, 1 an, …)"
      },
      {
        "value": "option-7",
        "text": "Réglage et/ou contrôle des aides auditives"
      },
      {
        "value": "option-8",
        "text": "Service après vente - Nettoyage des aides auditives"
      },
      {
        "value": "option-9",
        "text": "Renouvellement des aides aides auditives"
      },
      {
        "value": "option-10",
        "text": "Fabrication de protections d’oreilles sur mesure"
      }
    ]
  }
}

No notes defined.