The issue you're encountering is because the x-data variable selectedOptionId is separate from Livewire’s $selectedOption property, meaning they are not connected. When you click an option, Alpine's selectedOptionId is being set, but it’s not reflected in Livewire's $selectedOption.
Try the following instead:
<form wire:submit.prevent="nextQuestion"
x-data="{ enableSaveButton: false }">
<div class="grid sm:grid-cols-2 gap-4">
<template x-for="(option, index) in @js($options)" :key="option.id">
<div @click="enableSaveButton = true">
<input
type="radio"
name="option"
:id="'option_' + option.id"
:value="option.id"
class="sr-only peer"
wire:model.defer="selectedOption"
/>
<label :for="'option_' + option.id" class="">
<span class="text-sm xl:text-base font-bold text-primary">
<span x-text="option.option"></span>
</span>
</label>
</div>
</template>
</div>
<div class="mt-8 xl:mt-10 flex gap-2 justify-between">
<div class="flex gap-1">
<button type="submit"
:class="{'opacity-50 cursor-not-allowed': !enableSaveButton}"
class="btn-secondary bg-state-success text-secondary text-sm font-bold flex-none">
Save & Next
</button>
</div>
</div>
<button class="btn-secondary bg-transparent border border-border text-dark font-bold w-full text-sm md:hidden">
Clear Response
</button>
</form>