Component
As we prepare for the upcoming release of Skeleton v4, we will introduce new component APIs for all Skeleton components and supported frameworks. This comes in the form of three primary changes, covered below.
Composed Pattern
The component structure will now be much more explicit and granular. While a bit more verbose, this offers direct access to all children within the component tree. Allowing you to pass pass arbitrary props and attributes directly to the the HTML template within. Including: required
, data-*
, style
, class
, and many others.
<Accordion> <Accordion.Item value="item-1"> <Accordion.ItemHeading> <Accordion.ItemTrigger>Item 1</Accordion.ItemTrigger> </Accordion.ItemHeading> <Accordion.ItemContent>Content for Item 1</Accordion.ItemContent> </Accordion.Item> <Accordion.Item value="item-2"> <Accordion.ItemHeading> <Accordion.ItemTrigger>Item 2</Accordion.ItemTrigger> </Accordion.ItemHeading> <Accordion.ItemContent>Content for Item 2</Accordion.ItemContent> </Accordion.Item> <Accordion.Item value="item-3"> <Accordion.ItemHeading> <Accordion.ItemTrigger>Item 3</Accordion.ItemTrigger> </Accordion.ItemHeading> <Accordion.ItemContent>Content for Item 3</Accordion.ItemContent> </Accordion.Item></Accordion>
Simpler Stying
The most painful part of using Skeleton in the past has been learning the unique conventions required to apply styles to to each component. Previously we relied on reserved prop names, special prefixes, etc. This is no longer the case. You simply provide your styles via a common class
attribute per component.
v3 Styling
<Avatar ... rounded="rounded-2xl" imageClasses="grayscale" />
v4 Styling
<Avatar class="rounded-2xl"> <Avatar.Image src="https://i.pravatar.cc/150?img=48" class="greyscale" /> <Avatar.Fallback>SK</Avatar.Fallback></Avatar>
Rather than opting for additional tooling like Tailwind Merge under the hood, we instead accomplish this using the new custom variant syntax provided in Tailwind 4.
@custom-variant skb { @layer base { @slot; }}
This enables us to assign all internal styles to the @base
layer within your generated CSS bundle. We then inject our Tailwind utility classes to the class
attribute within each component for the default styling, but prefix them with skb
(short for “Skeleton Base”).
{ class: "skb:bg-surface-500 skb:rounded-full"}
Then, when you supply custom classes via the component’s class
attribute, those are appended to the end of the class list and automatically take precedence. By pairing this with the new composed component structure, this means you can alawys target the portion of the component you wish to adjust. Leading to a much more intuative experience overall that is closer to working with native HTML.
Extensible Markup
Finally we’re adding one more tool to your toolkit - the ability to override and modify the component template markup.
React
export default function () { return ( <Accordion> {/* ... */} <Accordion.Item value="item-1"> <Accordion.ItemHeading> <Accordion.ItemTrigger element={(attributes) => <button {...attributes}>My Own Button</button>} /> </Accordion.ItemHeading> <Accordion.ItemContent>Content for Item 1</Accordion.ItemContent> </Accordion.Item> {/* ... */} </Accordion> );}
Svelte
<Accordion> <!-- ... --> <Accordion.Item value="item-1"> <Accordion.ItemHeading> <Accordion.ItemTrigger> {#snippet element(attributes)} <button {...attributes}>My Own Button</button> {/snippet} </Accordion.ItemTrigger> </Accordion.ItemHeading> <Accordion.ItemContent>Content for Item 1</Accordion.ItemContent> </Accordion.Item> <!-- ... --></Accordion>
By exposing the the the internal attributes
, this enables you to take control and modify the template implementation.
Custom Animations
Building on the extensible markup concept, this provides additional control over the template markup. Which in turn means you can implement animations as you see fit. Here’s a quick example:
import { slide } from 'svelte/transition';
<Accordion> <!-- ... --> <Accordion.Item value="item-1"> <Accordion.ItemHeading> <Accordion.ItemTrigger>Item 1</Accordion.ItemTrigger> </Accordion.ItemHeading> <Accordion.ItemContent> {#snippet element(attributes)} {#if !attributes.hidden} <div {...attributes} hidden={false} transition:slide>Content for Item 1</div> {/if} {/snippet} </Accordion.ItemContent> </Accordion.Item> <!-- ... --></Accordion>
This requires the following:
- Implement the
element()
snippet to gain access to theattributes
. - Spread the
attributes
to the custom element, a<div>
in this example. - Override the
hidden
attribute tofalse
to prevent it from showing/hiding the element too soon. - Add the
transition:slide
and configure your preferred options. - Then implement the wrapping
#if
block that triggers transitions whenattribute.hidden
is toggled.
While we showcase this with Svelte Transitons, you could easily substitute with any viable alternative. Including Motion, a framework agnostic animation library. This will be our recommendation for React and all future component frameworks we support.
And while this is very verbose, we don’t expect you to implement this per every component instance. But instead, abstract these changes to a local component in your project. For example, instead of using the stock <Accordion.Content>
that lacks animation, you would implement your own <AccordionContentAnimated>
component with the above logic. Then the developer experience would then be something like this:
import AccordionContentAnimated from 'my/local/lib/AccordionContentAnimated.svelte';
<Accordion> <!-- ... --> <Accordion.Item value="item-1"> <Accordion.ItemHeading> <Accordion.ItemTrigger>Item 1</Accordion.ItemTrigger> <AccordionContentAnimated>Content for Item 1</AccordionContentAnimated> </Accordion.ItemHeading> </Accordion.Item> <!-- ... --></Accordion>
Early Access Preview
If you’re interested in trying our early preview of the new Skeleton v4 components, you can do so immediately by updating to the latest release of each production Skeleton v3 package:
@skeletonlabs/skeleton
- for styling@skeletonlabs/skeleton-react
- for React components@skeletonlabs/skeleton-svelte
for Svelte components
We have currently provided two new components that follow the new patterns. There are available in parallel to their standard v3 variants, which means you can easily swap between at will.
- Avatars: React | Svelte via import path
@skeletonlabs/skeleton-react/composed
- Accordions: React | Svelte via import path
@skeletonlabs/skeleton-svelte/composed
Request for Comment
For the duration of this preview, we ask that you please test the new component structure, styling, and markup features in your projects. Note that these features are considered experimental and subject to breaking changes at any time. However, we encourage you to share feedback in both Discord (via #contributors
) and GitHub. We’ll aim to provide progress updates as frequently as we can.
Contribute
If you wish to contribute to Skeleton Next (v4), please refer to our updated guidelines.