# General concepts ## Component styling Out of the box, these components are completely unstyled. This has some big advantages: you're free to make them look however you want, without having to fight against any pre-existing styles that don't fit in with the look and feel of your site. Instead of being constrained by an existing design system like Material Design or Carbon Components, you can fully customize your components' appearance--but letting the library take care of implementing all the keyboard and mouse interactions, accessibility features, and so on. The flipside of unstyled components, however, is that you need to, well, style them. There are a number of ways of doing this. ### Styling children: slot props You can style the descendants of components from this library with the help of slot props: ```svelte (plan = e.detail)}> Plan Startup Business Enterprise ``` ### Styling the components themselves: `class` and `style` Slot props can be used to style any descendent components, but they cannot be used to style the same component that defines them. To work around this, any component that defines slot props will also optionally accept a **function** for its `class` and/or `style` props. These functions will be **called with the slot props as an argument**: ```svelte (plan = e.detail)}> Plan (checked ? "checked" : undefined)} > Startup (checked ? "checked" : undefined)} > Business (checked ? "checked" : undefined)} > Enterprise ``` See the individual component documentation to learn about the slot props for each component. You may also pass a string for `class` or `style`, or omit them entirely, of course. What follows below is some guidance on the different ways to use the `class` and `style` props to style your components. #### Using Svelte's ` ``` This works great for styling HTML elements. However, it (unfortunately) does **not** work for styling _components_. If you try to create the same example without the ``s, it won't work: ```svelte (plan = e.detail)}> Plan (checked ? "checked" : "")} > Startup (checked ? "checked" : "")} > Business (checked ? "checked" : "")} > Enterprise ``` (Note that we also can no longer use the `class:checked` shorthand on a component) Why doesn't this work? When Svelte compiles our component, it adds in a special unique class to the CSS rules and to the HTML elements rendered by this component that are affected. But it does _not_ add this special class to any child _components_. The result is that the `.checked` CSS rule will be generated with a second class that the `` components do not have, and it will not match. Unfortunately there is no way in Svelte right now to pass this special class down to the `` components, and the framework does not have a good solution in general for this. Hopefully one day the Svelte maintainers will add some way of solving this problem. Until then, you can still style your components using one of the approaches below. #### The `:global()` modifier The `:global()` modifier opts your rule out of the default component style scoping. CSS rules inside `:global()` are treated as "normal" CSS, so the following will work: ```svelte (plan = e.detail)}> Plan (checked ? "checked" : "")} > Startup (checked ? "checked" : "")} > Business (checked ? "checked" : "")} > Enterprise ``` However, global CSS has one critical downside: it's global! The `.checked` rule above will now apply to _any_ `.checked` CSS class in your application, even if it's in other components. In a larger application, this can get difficult to maintain. You can scope this more narrowly if you have a wrapper element: ```svelte
(plan = e.detail)}> Plan (checked ? "checked" : "")} > Startup (checked ? "checked" : "")} > Business (checked ? "checked" : "")} > Enterprise
``` In this case, this works perfectly. When using this scoped `* > :global()` approach, keep in mind these principles: - Your Headless UI components must be contained inside some element **that is rendered by your component**, like the wrapper `
` above. You need an element for the Svelte scoped class to be attached to. - Your rule will be scoped to your component **and any descendant**. In the example above this is not a problem, since the component has no ``s. But if your component _does_ have ``s, you will still need to be careful for collisions. - This rule won't work properly inside a portal, which means that it won't work properly for a ``. To style the ``, you will need to either 1) use global styles without the `* >` scoping, 2) put a wrapper element inside the `` and style that instead, or 3) use one of the other styling approaches. #### Inline styles You can style any component using inline styles using the `style=...` prop: ```svelte
(plan = e.detail)}> Plan checked ? "background-color: rgb(191 219 254)" : undefined} > Startup checked ? "background-color: rgb(191 219 254)" : undefined} > Business checked ? "background-color: rgb(191 219 254)" : undefined} > Enterprise
``` As mentioned above, this prop accepts a function whose input will be the component's slot props, allowing you to apply conditional styles. One downside of inline styles is that you cannot use them to style CSS psuedoselectors, like `:focus` and `:hover`. In general this library will provide you with states that make these psuedoselectors unnecessary, however. #### Using a CSS framework You can always use the `class` prop as normal alongside a CSS framework like Bootstrap, Bulma, Tailwind, etc. The original version of this component library was written by the same team that maintains Tailwind CSS. ## Event forwarding This library will forward all events to the underlying elements, so you can add your own event handlers if necessary: ```svelte (enabled = e.detail)} on:click={() => console.log("Clicked!")} > Toggle me! ``` Note that the library already handles all of the keyboard and mouse events you'd need to implement the component functionality. You don't need to add a handler to e.g. open or close a popover when the popover button is clicked. You can also use event modifiers, but they must be separated by ! instead of the normal |, for technical reasons: ```svelte (enabled = e.detail)} on:click!once={() => console.log("Clicked!")} > Toggle me! ``` ## Using Svelte actions You can use [actions](https://svelte.dev/tutorial/actions) with this library as well. The Svelte `use:` directive is not supported for Components, so you need to use the `use` prop instead: ```svelte (enabled = e.detail)} use={[[action1, action1options], [action2], [action3, action3options]]} > Toggle me! ``` The `use` prop must be a list of `[action]` or `[action, options]` items. These actions will be applied to the underlying element that the component eventually renders. ## Customizing the elements rendered Each component in this library renders as some specific HTML element. By default, this element will be something that makes sense for that particular component: a `Label` component renders as `