rgossiaux/svelte-headlessui

Question - RadioGroupOption slot props

Closed this issue · 5 comments

FIrstly, thanks so much for the work that's gone into porting this over for Svelte, it's incredibly valuable!

Secondly, I'm a bit of a novice so this is probably down to my ignorance. I don't know React and I'm beginner with Svelte so reading the official docs isn't a great help to me so far.

Question - at this line, class="{active && checked ? 'ring ring-offset-1' : ''} {!active && checked ? 'ring-2' : ''}, active and checked are both erroring as undefined. No idea what I'm doing wrong. Please could you point me in the right direction?

<RadioGroup value={selectedColour} on:change={(e) => (selectedColour = e.detail)}>
					<RadioGroupLabel class="block text-sm font-medium text-gray-900"
						>Choose a label colour</RadioGroupLabel
					>
					<div class="mt-1 flex items-center space-x-3">
						{#each colours as colour (colour.name)}
							<RadioGroupOption
								let:active
								let:checked
								value={colour}
								class="{active && checked ? 'ring ring-offset-1' : ''}
						  {!active && checked ? 'ring-2' : ''}
				
							  {colour.selectedColour} -m-0.5 relative p-0.5 rounded-full flex items-center justify-center cursor-pointer focus:outline-none"
							>
								<RadioGroupLabel as="p" class="sr-only">
									{colour.name}
								</RadioGroupLabel>
								<span
									aria-hidden="true"
									class="{colour.bgColour} h-8 w-8 border border-black border-opacity-10 rounded-full"
								/>
							</RadioGroupOption>
						{/each}
					</div>
				</RadioGroup>

Hey! Glad you're finding the library useful :) Sorry about the lack of docs, I'm actually working on them right now.

In your code, active and checked are erroring because in Svelte, the slot props (let:active and let:checked) are only defined in the child components. To get around this, the components in this library also accept a function for the class prop. That function will take the slot props as input and should output a class string.

In your case, I think you want something like

class={({active, checked}) => classNames(
  active && checked ? 'ring ring-offset-1' : '',
  !active && checked ? 'ring-2' : '',
  colour.selectedColour,
  '-m-0.5 relative p-0.5 rounded-full flex items-center justify-center cursor-pointer focus:outline-none'
)}

where classNames is a helper function that looks like

  function classNames(...classes) {
    return classes.filter(Boolean).join(" ");
  }

Or alternatively using template literals something like:

class={({active, checked}) => 
  `${active && checked ? 'ring ring-offset-1' : ''} ${!active && checked ? 'ring-2' : ''} ${colour.selectedColour} -m-0.5 relative p-0.5 rounded-full flex items-center justify-center cursor-pointer focus:outline-none`
}

I also noticed that a bit further down in your snippet, I think you meant to use a template literal on this line:
class="{colour.bgColour} h-8 w-8 border border-black border-opacity-10 rounded-full"

Otherwise I think your HTML will end up with "{colour.bgColour}" in it instead of the value.

Hope that helps!

Thanks @rgossiaux that was very helpful. Really looking forward to the docs. Happy to help review them if you want. If I could understand them, then anyone could! 😂

Thanks to the implementation guidance from @rgossiaux I was able to implement the Tailwind UI e-commerce product quickview @sbadisa was trying to create. See it in action here or review the implementation here. (Note I could not figure out how to get the disabled slot prop working and left a FIXME in the code. I also left transitions/animation for a future iteration.)

@rgossiaux Perhaps you could enable Discussions on this repo so we could move items like this to the Q&A section? @sbadisa if you can get disabled working for the size selector please let me know -- I tried to use a Svelte @const in the each block but that didn't do it.

Thanks to the implementation guidance from @rgossiaux I was able to implement the Tailwind UI e-commerce product quickview @sbadisa was trying to create. See it in action here or review the implementation here. (Note I could not figure out how to get the disabled slot prop working and left a FIXME in the code. I also left transitions/animation for a future iteration.)

@rgossiaux Perhaps you could enable Discussions on this repo so we could move items like this to the Q&A section? @sbadisa if you can get disabled working for the size selector please let me know -- I tried to use a Svelte @const in the each block but that didn't do it.

Sure, I enabled discussions for the repo.

As for your code, I took a quick peek. You want to just use the normal disabled prop, the same as the Tailwind code: disabled={!size.inStock}.

I also noticed that you commented out the Transitions in their code. Those should work just fine as well if you just delete the as={Fragment} and rename the Transition.Root to Transition

Thanks so much for creating the Discussion section, @rgossiaux.

As for your code, I took a quick peek. You want to just use the normal disabled prop, the same as the Tailwind code: disabled={!size.inStock}.

I did try that before attempting to use @const as a workaround. Unfortunately Svelte throws a compiler error due to an invalid use of let which I've detailed along with my issue in more detail in the Discussion section here: #48

Looking forward to getting past this issue as it's a blocker for creating a workable ecommerce storefront.