Code Monkey home page Code Monkey logo

svelte-headlessui's Introduction

svelte-headlessui

This is an unofficial, complete Svelte port of the Headless UI component library (https://headlessui.dev/). It contains fully accessible, feature-rich, unstyled UI components.

Documentation for this library is available at https://svelte-headlessui.goss.io

Who is this for?

This library is for you if you fall into one of two categories:

  • You want unstyled yet sophisticated customizable UI components that fully follow the WAI-ARIA specs. You want a component library to handle all the messy details (keyboard navigation, focus management, aria-* attributes, and many many more), but you want to style your components yourself and not be constrained by existing design systems like Material UI.
    • Alternatively, you want to implement an existing design system in Svelte, and want a powerful set of primitives to build your components on, letting you focus on styling.
  • You want to use the commercial Tailwind UI component library (https://tailwindui.com/) in your Svelte project, and want a drop-in replacement for the React/Vue components which power Tailwind UI.

This project is intended to keep an API as close as possible to the React API for the base Headless UI project, with only a few small differences. While one of the primary goals is to enable using Tailwind UI in a Svelte project with as little effort as possible, neither Tailwind UI nor Tailwind CSS is required to use these components.

This project is an unofficial port. I have no affiliation with Tailwind Labs and cannot offer commercial support for this project. With that said, I intend to keep it as up to date as possible with the upstream Headless UI project, including porting new components when they are released.

Installation

npm install -D @rgossiaux/svelte-headlessui

Usage

See https://svelte-headlessui.goss.io for full documentation.

Credits

Credit for everything good about this library goes to Tailwind Labs for writing the original React/Vue versions. All bugs should be assumed to be my fault in the port (though as the codebases are so similar, bugs in upstream will likely affect this library too).

Additional thanks to https://github.com/hperrin/svelte-material-ui; this well-engineered Svelte library was the source of the action and event forwarding code, with minor modifications.

License

This library is licensed under the MIT license; see the LICENSE file for more.

svelte-headlessui's People

Contributors

davepar avatar dependabot[bot] avatar rgossiaux avatar safwanolaimat avatar vitroidfpv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

svelte-headlessui's Issues

Forward actions

  • Description
  • Dialog
  • Label
  • Listbox
  • Menu
  • Popover
  • Radio Group
  • Switch
  • Tabs

Popover example transition doesn't work correctly on the buttons

For some reason the buttons are not transitioned even though everything else is-- maybe because they are not children of the Transition. Need to understand the details more here. Not being able to render as a <Fragment> is causing the issue & it seems pretty hard to fix at first glance.

Components with lists of items/options don't handle dynamically inserting items

For example:

<script lang="ts">
  import { RadioGroup, RadioGroupLabel, RadioGroupOption } from "$lib";
  let showFirst = false;
  let active: unknown;
</script>

<button on:click={() => (showFirst = !showFirst)}>Toggle</button>
<RadioGroup value={active} on:change={(e) => (active = e.detail)}>
  <RadioGroupLabel>Pizza Delivery</RadioGroupLabel>
  {#if showFirst}
    <RadioGroupOption value="pickup">Pickup</RadioGroupOption>
  {/if}
  <RadioGroupOption value="home-delivery">Home delivery</RadioGroupOption>
  <RadioGroupOption value="dine-in">Dine in</RadioGroupOption>
</RadioGroup>

Headless UI seems to handle this case for RadioGroup. The Vue implementation can port directly to Svelte: https://github.com/tailwindlabs/headlessui/blob/e9e6aded545c329585d8cf7452ad9fe400a5406b/packages/%40headlessui-vue/src/components/radio-group/radio-group.ts#L120

Interestingly they didn't bother handling this for other components, but I don't see why we shouldn't do the same thing for Listbox, Menu, and Tabs.

Filing this to keep track of it since I'm working on other areas right now. Will fix soon.

MenuItem links do not activate on keypress

Describe the bug
I have a Menu with MenuItem links which can be activated by mouse but not by keyboard.

To Reproduce

  1. Navigate to https://sveltekit-headlessui-starter.vercel.app
  2. Tab to the Avatar icon within the global navigation
  3. Press Enter to expand the Menu
  4. Select one of the MenuItems via keyboard and press Enter
  5. Observe no navigation occurs
  6. Do the same thing with the mouse and observe successful navigation

Here's the source for the above site:
https://github.com/vhscom/sveltekit-headlessui-starter

And a deep link to the MenuItem implementation:
https://github.com/vhscom/sveltekit-headlessui-starter/blob/bd7df2ff5b248bec95e94b126db42193be08a2f4/src/lib/shared/components/navigation/GlobalNav.svelte#L111-L122

Example linked:

<MenuItem let:active>
  <a
    href="/account/profile"
    sveltekit:prefetch
    class={classes(
      active ? 'bg-gray-100' : '',
      'block px-4 py-2 text-sm text-gray-700'
    )}
  >
    Your Profile
  </a>
</MenuItem>

Library version
lib: [email protected]
kit: [email protected]

Make FocusTrap closer to React/Vue implementations

I don't remember any more why this ended up with a different implementation... looking back over it I don't see why it can't be closer to the others. In particular this gets in the way of porting the FocusTrap tests and exposing the component publicly.

This isn't really a user-facing bug, it's just to track internal cleanup.

Docs

Aware that this is already planned by the readme, but I thought that I might open this issue to track it anyways. Might suggest a few things, since documenting svelte components can be made a lot easier than expected.

Few neat things that can help:

Consider forwarding transition and animation directives

We already forward use: (via the use= prop) and on: (via some runtime hacks). We should consider supporting equivalents for the transition/animation directives too: something like in=, out=, transition=, and animate=. Not sure if any other popular component library supports this, but I think it's probably pretty useful.

Text Selection Broken in Dialogs

I noticed I can't select text in Dialogs on all browsers. This doesn't apply to input elements though.

Screen.Recording.2022-01-21.at.11.02.47.mov

License

As far as I'm aware you cannot change ANY existing copyright line in the MIT license. And when you add to an existing license you should stack on top of the existing copyright line (and not below it). As such, nothing in this world is ever set in stone. I'm simply relaying what I've read and researched on opensource.stackexchange.com and on the web. Lastly you may want to update your modifications copyright line to include something like and contributors if you plan to accept pull requests in this repo.

Thanks for picking an MIT license. Even if you did go with Apache 2.0 (which you possibly still could do if you wanted, though that's just a hip shot statement) both the MIT and Apache 2.0 are GPL-compatible licenses.

Buttons inside Popovers are not clickable in Safari

I am unable to click items inside of a popover when using safari. Brave seems to work just fine. I've tried using the below code as well as <PopoverPanel static> manually controlling the open state to no luck.

<script>
  import {
    Popover,
    PopoverButton,
    PopoverPanel,
  } from '@rgossiaux/svelte-headlessui'
</script>

<Popover>
  <PopoverButton>open popover</PopoverButton>
  <PopoverPanel>
    <button on:click={() => console.log('button clicked')}>button</button>
  </PopoverPanel>
</Popover>

Tested in a fresh skeleton sveltekit app. Tabbing through the items and hitting enter does work. Clicking, however, causes the panel to disappear before firing any events.

Doing the same test using a fresh vite + vue app and the official @headlessui/vue popover works as expected (including in safari):

<template>
  <Popover>
    <PopoverButton>open popover</PopoverButton>

    <PopoverPanel>
      <button @click="handleClick">button</button>
    </PopoverPanel>
  </Popover>
</template>

<script setup>
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/vue";

function handleClick() {
  console.log("button clicked");
}
</script>

Carve our own path?

I have been waiting for this for almost a year. At this point there's nothing wrong if we try not to make it 'official'.

  • "Unofficial port of" sounds a bit experimental. it should be called simply "based on". That'll give us more freedom.
  • Merge updates from Headless UI upstream without being restricted to it.
  • Take inspiration from other projects, i.e., renderless-svelte
  • Tailwind is not required so it'll be good to keep docs and code examples agnostic and easy to follow for custom/component css, Chota, Picnic, WindiCSS, etc.

Context store pattern

Is it valuable to extract this function?
I've seen it in almost every component.

// $lib/components/menu/Menu.svelte

  const MENU_CONTEXT_NAME = "headlessui-menu-context";

  export function useMenuContext(
    componentName: string
  ): Readable<StateDefinition> {
    let context: Writable<StateDefinition> | undefined =
      getContext(MENU_CONTEXT_NAME);

    if (context === undefined) {
      throw new Error(
        `<${componentName} /> is missing a parent <Menu /> component.`
      );
    }
    return context;
  }

// ...

  setContext(MENU_CONTEXT_NAME, api);

Possible solution

// $lib/internal/context-store.ts

export function createContextStore<T>(
  id = Symbol("context")
): [() => Readable<T> | undefined, (value: Writable<T>) => void] {
  return [() => getContext(id), (value) => setContext(id, value)];
}
// $lib/components/menu/Menu.svelte

  export const [getMenuContext, setMenuContext] =
    createContextStore<StateDefinition>();

  export function useMenuContext(componentName: string) {
    const context = getMenuContext();
    if (context) return context;
    throw new Error(
      `<${componentName} /> is missing a parent <Menu /> component.`
    );
  }
// ...

  setMenuContext(api);

Slot props not defined in Typescript

Hello!

I've been tinkering with this library today and it's been great! One thing I've run into is that the packaging that's been done so far doesn't generate typings for the various slotProps that are used; i.e., the slotProps for ListBoxOption is {} instead of correctly picking up the active/selected/disabled props.

Root cause here is spreading the slotProps onto the slot, instead of defining them manually. Looks like if you did something like the below, sveltekit package picks up the types correctly

<slot active={slotProps.active} ...etc/>

Use two-way binding

When writing this initially I imitated the React API as closely as I could, to make it easy to adapt the Tailwind UI snippets.

However, a second guiding principle is that I want this to feel like a native Svelte library as much as possible. I believe that Tailwind follows this approach themselves with their React/Vue versions. And I think a native Svelte library should really just use bind here. Most convincing, though, is that the Vue library uses data binding with v-model on several components.

Need to figure out the right way to semver this... I'm still on 1.0.0-beta.x but I think I might have to bump to 2.0 just for this change, not sure yet.

Improve TypeScript support for $$restProps, `class`/`style` as functions

Because these components spread $$restProps all over the place, the TypeScript support for props besides those exported by the component is lacking. Concretely that means:

  • Props which <Render> uses which come via $$restProps: class and style--particularly when using them as functions.
  • Props which are spread all the way down to the underlying HTML elements.

It would be nice if we could do this semi-automatically (sveltejs/language-tools#1363), but we can also use $$Props to type the component manually. Ideally we can get support for some similar $$RestProps type of interface (suggesting this to the language-tools folks) but if not we can still use $$Props--it'll just be a bit more painful since we now have to worry about forgetting to add any props there.

Accessing Listbox value with slot property

Hi there,

as someone who has never used React or Vue, it can be a challenge to crosscheck your documentation with the official headlessui docs. As such, I hope you don't mind a question (even if it seems very basic):

When using Listbox, am I only able to access the value of the Listbox by listening to the component event?
on:change((e) => selectedValue = e.detail) as per your example?

This doesn't seem to work:
<Listbox as="div" let:value> <ListboxButton>{value}</ListboxButton> //returns undefined

If the above doesn't work, how do I access/make use of the component API? What confuses me is that in the official React docs, "value" is listed as a prop. Does this not automatically mean that the prop is exposed? (https://headlessui.dev/react/listbox#component-api)

Additional insert of empty `<div>` tag is throwing off my CSS element sizing.

Hey all, I have a TransitionChild that contains a <div> tag with a class something downs the line of class="relative flex-1 flex flex-col max-w-xs w-full pt-5 pb-4 bg-purple-700". However, when I run this the sizing is all off. I have found that in the inspection there is an additional <div> tag insterted before the body of a TransitionChild with class= " ". This additional div is throwing off my css and the resizing. Is this the expected behaviour and I should work around this? Or is this a bug that needs to get addressed?

null is not an object (evaluating 'node.parentNode.removeChild')

Context

I'm getting a critical error when using the Dialog component with transitions then interacting (hover, click) with a Menu component before the transition ends.

<Dialog {open} on:close={() => (open = false)}>
  <div class="dialog" style={$primaryVars}>
    <div transition:fade={{ duration: 300, easing: cubicOut }}>
      <DialogOverlay class="dialog-overlay" />
      <div
        class="dialog-card"
        in:fly={{ duration: 500, y: 50, easing: cubicOut }}
      >
        <DialogTitle as="h1" class="text-brand w-fit">My application</DialogTitle>
        ...
      </div>
    </div>
  </div>
</Dialog>

Traces

The errors I'm getting are:
TypeError: stop is not a function. (In 'stop()', 'stop' is null)

[Error] TypeError: stop is not a function. (In 'stop()', 'stop' is null)
	(anonymous function) (chunk-JTPRY6KS.js:50)
	(anonymous function) (withError.ts:77)
	forEach
	run_all (chunk-QOGR3KCG.js:25)
	destroy_component (chunk-QOGR3KCG.js:1643)
	destroy (AuthDialog.svelte:352)
	destroy (AuthDialog.svelte:785)
	destroy (Dialog.svelte:118)
	destroy (Render.svelte:241)
	destroy (Div.svelte:118)
	destroy_component (chunk-QOGR3KCG.js:1644)
	destroy (Render.svelte:180)
	(anonymous function) (chunk-QOGR3KCG.js:1011)
	forEach
	run_all (chunk-QOGR3KCG.js:25)
	(anonymous function) (chunk-QOGR3KCG.js:1196)
	(anonymous function) (chunk-QOGR3KCG.js:169)
	forEach
	run_tasks (chunk-QOGR3KCG.js:168)

Unhandled Promise Rejection: TypeError: null is not an object (evaluating 'node.parentNode.removeChild')

[Error] Unhandled Promise Rejection: TypeError: null is not an object (evaluating 'node.parentNode.removeChild')
	detach (chunk-QOGR3KCG.js:321)
	detach_dev (chunk-QOGR3KCG.js:1796)
	destroy (Render.svelte:179)
	(anonymous function) (chunk-QOGR3KCG.js:1011)
	forEach
	run_all (chunk-QOGR3KCG.js:25)
	check_outros (chunk-QOGR3KCG.js:992)
	update (Render.svelte:296)
	update (chunk-QOGR3KCG.js:964)
	flush (chunk-QOGR3KCG.js:935)
	promiseReactionJob

System Info

macOS: 12.0.1 Monterey
MacBook Pro (15-inch, 2017)
Safari: Version 15.1 (17612.2.9.1.20)
Chrome: Version 97.0.4692.99 (Official Build)

Package info

@rgossiaux/svelte-headlessui: v1.0.0-beta.8
svelte: 3.46.2
@sveltejs/kit: 1.0.0-next.245

<TransitionRoot> is not a valid SSR component.

Hi,

New to svelte here. I tried using one of TailwindUI components and got the error below.

TransitionRoot is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules

Better error messages on React-style props

Something I've been thinking about recently--it would be nice if I could add in some error messages if you use React-style prop names (className, onChange, htmlFor, and some SVG attributes come to mind). Ideally I can get these to throw a type error, but even a compile or runtime error will make it a lot friendlier for people porting React code (ie users of Tailwind UI).

Are `as` and `class` working?

I'm using Windi CSS with Svelte Kit.

Most of the things work and are straight forward, but using the components I can't use the as and class props.
So I need to nest a div or other html element. Is this intended?

A port from the headless ui react example

image

<script>
	import {
		RadioGroup,
		RadioGroupDescription,
		RadioGroupLabel,
		RadioGroupOption
	} from '@rgossiaux/svelte-headlessui';

	const plans = [
		{
			name: 'Startup',
			ram: '12GB',
			cpus: '6 CPUs',
			disk: '160 GB SSD disk'
		},
		{
			name: 'Business',
			ram: '16GB',
			cpus: '8 CPUs',
			disk: '512 GB SSD disk'
		},
		{
			name: 'Enterprise',
			ram: '32GB',
			cpus: '12 CPUs',
			disk: '1024 GB SSD disk'
		}
	];

	let value = plans[0];
</script>

<div class="w-full px-4 py-16">
	<div class="w-full max-w-md mx-auto">
		<RadioGroup {value} on:change={(e) => (value = plans.find((p) => p.name === e.detail.name))}>
			<RadioGroupLabel>
				<div class="sr-only">Server size</div>
			</RadioGroupLabel>
			<div class="space-y-2">
				{#each plans as plan (plan.name)}
					<RadioGroupOption key={plan.name} value={plan} let:active let:checked>
						<div
							class={`
                            relative rounded-lg shadow-md px-5 py-4 cursor-pointer flex focus:outline-none 
                            ${checked ? 'bg-sky-900 bg-opacity-75 text-white' : 'bg-white'} ${
								active ? 'ring-2 ring-offset-2 ring-offset-sky-300 ring-white ring-opacity-60' : ''
							} 
                            `}
						>
							<div class="flex items-center justify-between w-full">
								<div class="flex items-center">
									<div class="text-sm">
										<RadioGroupLabel>
											<p class={`font-medium ${checked ? 'text-white' : 'text-gray-900'}`}>
												{plan.name}
											</p>
										</RadioGroupLabel>
										<RadioGroupDescription>
											<span class={`inline ${checked ? 'text-sky-100' : 'text-gray-500'}`}>
												<span>
													{plan.ram}/{plan.cpus}
												</span>
												<span aria-hidden="true">&middot;</span>{' '}
												<span>{plan.disk}</span>
											</span>
										</RadioGroupDescription>
									</div>
								</div>
								{#if checked}
									<div class="flex-shrink-0 text-white">
										<svg class="w-6 h-6" viewBox="0 0 24 24" fill="none">
											<circle cx={12} cy={12} r={12} fill="#fff" opacity="0.2" />
											<path
												d="M7 13l3 3 7-7"
												stroke="#fff"
												stroke-width={1.5}
												stroke-linecap="round"
												stroke-linejoin="round"
											/>
										</svg>
									</div>
								{/if}
							</div>
						</div>
					</RadioGroupOption>
				{/each}
			</div>
		</RadioGroup>
	</div>
</div>

Support `TransitionRoot` alias for `Transition`

I only export the TransitionRoot component under the Transition name (which is the one that's documented), but it looks like some Tailwind UI snippets might use the Transition.Root naming, so I should probably export that as well

Typeahead does not fully follow WAI-ARIA spec

The WAI-ARIA spec for Listbox mentions (emphasis mine):

Type a character: focus moves to the next item with a name that starts with the typed character.

However, as reported by a user on Reddit, Headless UI does not do that; instead, we search for the first item with a name that starts with the typed character. You can see this in action on https://headlessui.dev/react/menu by repeatedly typing the letter d (with pauses in between). This affects Listbox and Menu both.

Unused export properties warnings from vite-plugin-svelte

I am seeing these warning logs at first load.

Forgive my ignorance, am new to front end dev, and also both to Sveltekit and Vite. Is it important for vite-plugin-svelte to care about node_modules or should it ignore everything except what's in my src folder?

yarn run v1.22.15
$ svelte-kit dev --host 0.0.0.0
Pre-bundling dependencies:
  svelte/store
  svelte
  svelte-hero-icons
  svelte/animate
  svelte/easing
  (...and 3 more)
(this will be run only when your dependencies or config have changed)

  SvelteKit v1.0.0-next.202

  local:   http://localhost:3000
  network: http://172.18.0.2:3000

  Note that all files in the following directories will be accessible to anyone on your network: static, src/lib, src/routes, src, .svelte-kit, node_modules


1:30:36 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/components/dialog/Dialog.svelte:2:11 Dialog has unused export property 'DialogStates'. If it is for external reference only, please consider using `export const DialogStates`
1:30:36 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/components/disclosure/Disclosure.svelte:3:11 Disclosure has unused export property 'DisclosureStates'. If it is for external reference only, please consider using `export const DisclosureStates`
1:30:37 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/components/listbox/Listbox.svelte:1:37 Listbox has unused export property 'ListboxStates'. If it is for external reference only, please consider using `export const ListboxStates`
1:30:37 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/components/menu/Menu.svelte:9:11 Menu has unused export property 'MenuStates'. If it is for external reference only, please consider using `export const MenuStates`
1:30:37 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/components/popover/Popover.svelte:1:37 Popover has unused export property 'PopoverStates'. If it is for external reference only, please consider using `export const PopoverStates`
1:30:37 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/components/transitions/TransitionRoot.svelte:1:37 TransitionRoot has unused export property 'TreeStates'. If it is for external reference only, please consider using `export const TreeStates`
1:30:37 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/internal/StackContextProvider.svelte:1:37 StackContextProvider has unused export property 'StackMessage'. If it is for external reference only, please consider using `export const StackMessage`
1:30:37 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/utils/Render.svelte:21:11 Render has unused export property 'RenderStrategy'. If it is for external reference only, please consider using `export const RenderStrategy`
1:30:37 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/utils/Render.svelte:3:11 Render has unused export property 'Features'. If it is for external reference only, please consider using `export const Features`
1:30:39 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/components/dialog/Dialog.svelte:2:11 Dialog has unused export property 'DialogStates'. If it is for external reference only, please consider using `export const DialogStates`
1:30:39 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/components/disclosure/Disclosure.svelte:3:11 Disclosure has unused export property 'DisclosureStates'. If it is for external reference only, please consider using `export const DisclosureStates`
1:30:39 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/components/listbox/Listbox.svelte:1:37 Listbox has unused export property 'ListboxStates'. If it is for external reference only, please consider using `export const ListboxStates`
1:30:40 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/components/popover/Popover.svelte:1:37 Popover has unused export property 'PopoverStates'. If it is for external reference only, please consider using `export const PopoverStates`
1:30:40 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/components/menu/Menu.svelte:9:11 Menu has unused export property 'MenuStates'. If it is for external reference only, please consider using `export const MenuStates`
1:30:41 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/components/transitions/TransitionRoot.svelte:1:37 TransitionRoot has unused export property 'TreeStates'. If it is for external reference only, please consider using `export const TreeStates`
1:30:41 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/internal/StackContextProvider.svelte:1:37 StackContextProvider has unused export property 'StackMessage'. If it is for external reference only, please consider using `export const StackMessage`
1:30:41 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/utils/Render.svelte:21:11 Render has unused export property 'RenderStrategy'. If it is for external reference only, please consider using `export const RenderStrategy`
1:30:41 AM [vite-plugin-svelte] /app/node_modules/@rgossiaux/svelte-headlessui/utils/Render.svelte:3:11 Render has unused export property 'Features'. If it is for external reference only, please consider using `export const Features`

Question - RadioGroupOption slot props

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>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.