So I’m working with technologies such as Next.js 14 React Server Components for our new website, and I’m trying to stick as much as possible with server components – at least until I absolutely have to move some functionality to a client component.
Meaning I want to stick in "CSS" land and opt out of JavaScript for trivial things where JS is not really needed but often used because it’s easier or we’re used to it.
The thing at give me problems however is Tailwind which we’re also using. I was able to solve my problem quite fast using plain css the following way:
.times {
display: none;
}
.timeslots:has(.timeslot-1 > input:checked)~.timeslot-1-times {
display: block;
}
.timeslots:has(.timeslot-2 > input:checked)~.timeslot-2-times {
display: block;
}
.timeslots {
display: flex;
gap: 1rem;
}
<form>
<div>
<div class="timeslots">
<div class="timeslot-1">
<input type="radio" name="date" id="2024-04-28" />
<label for="2024-04-28">2024-04-28</label>
</div>
<div class="timeslot-2">
<input type="radio" name="date" id="2024-04-29" />
<label for="2024-04-29">2024-04-29</label>
</div>
</div>
<div class="times timeslot-1-times">
<div>
<input type="radio" name="time" id="12" />
<label for="12">12</label>
</div>
<div>
<input type="radio" name="time" id="13" />
<label for="13">13</label>
</div>
</div>
<div class="times timeslot-2-times">
<div>
<input type="radio" name="time" id="15" />
<label for="15">15</label>
</div>
</div>
</div>
</form>
Had the "times" been nested under each date this would be trivial to solve with tailwinds peer and peer-checked or even with checked pseudo selector. I do however need to render the dates in a horizontal list and show each date’s times in full width below, like in a typical tabs component as I tried to show in the above snippet.
Generally I’d like to avoid having to use plain css when using tailwind as the creator have stated that he’d remove "@apply" if he could go back in time. So what is the best practice Tailwind-way to achieve something similar to the code snippet above? Is there an easy built-in way I’m missing or do I need to add my own custom variations?
>Solution :
You can emulate your vanilla CSS with peer-has-* modifiers to conditionally apply the display: block:
<script src="https://cdn.tailwindcss.com/3.4.3"></script>
<form>
<div>
<div class="flex gap-4 peer">
<div class="timeslot-1">
<input type="radio" name="date" id="2024-04-28" />
<label for="2024-04-28">2024-04-28</label>
</div>
<div class="timeslot-2">
<input type="radio" name="date" id="2024-04-29" />
<label for="2024-04-29">2024-04-29</label>
</div>
</div>
<div class="hidden peer-has-[.timeslot-1>input:checked]:block">
<div>
<input type="radio" name="time" id="12" />
<label for="12">12</label>
</div>
<div>
<input type="radio" name="time" id="13" />
<label for="13">13</label>
</div>
</div>
<div class="hidden peer-has-[.timeslot-2>input:checked]:block">
<div>
<input type="radio" name="time" id="15" />
<label for="15">15</label>
</div>
</div>
</div>
</form>