feat: Add Carousel component
Linked Issue
Closes #3035
Description
Implements the Carousel component using @zag-js/carousel for both Svelte and React frameworks.
Changes
- Dependencies: Added
@zag-js/[email protected]to workspace catalog and both framework packages - Svelte Component (
packages/skeleton-svelte/src/components/carousel/): Full anatomy with Root, RootProvider, RootContext, Control, ItemGroup, Item, PrevTrigger, NextTrigger, AutoplayTrigger, IndicatorGroup, Indicator, ProgressText - React Component (
packages/skeleton-react/src/components/carousel/): Matching anatomy structure - CSS Styles (
packages/skeleton-common/src/components/carousel.css): Base styles for all carousel parts - Tests: Component render tests for both frameworks (10 tests each)
- Playgrounds: Added interactive playground pages for both Svelte and React with basic, multiple slides, and autoplay examples
- Documentation: Added full MDX documentation with examples for default, autoplay, loop, and multiple slides per page features
Complete ZagJS Carousel Anatomy Implementation
All components from the ZagJS carousel anatomy are implemented:
- root
- itemGroup
- item
- control
- nextTrigger
- prevTrigger
- indicatorGroup
- indicator
- autoplayTrigger
- progressText
Screenshot
Usage
<Carousel slideCount={3}>
<Carousel.Control>
<Carousel.PrevTrigger>Prev</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.ItemGroup>
<Carousel.Item index={0}>Slide 1</Carousel.Item>
<Carousel.Item index={1}>Slide 2</Carousel.Item>
<Carousel.Item index={2}>Slide 3</Carousel.Item>
</Carousel.ItemGroup>
<Carousel.IndicatorGroup>
<Carousel.Indicator index={0} />
<Carousel.Indicator index={1} />
<Carousel.Indicator index={2} />
</Carousel.IndicatorGroup>
<Carousel.ProgressText />
</Carousel>
AI Disclosure
Use of LLM technology is allowed. We ask for your voluntary disclosure to help inform future Skeleton contribution guidelines.
- [x] I used AI to generate this pull request
Checklist
Please read and apply all contribution requirements.
- [x] Your branch should be prefixed with:
docs/,feature/,task/,bugfix/ - [x] Contributions should target the
mainbranch - [x] Documentation should be updated to describe all relevant changes
- [x] Run
pnpm checkin the root of the monorepo - [x] Run
pnpm formatin the root of the monorepo - [x] Run
pnpm lintin the root of the monorepo - [x] Run
pnpm testin the root of the monorepo - [ ] If you modify
/packageprojects, please supply a Changeset
Changesets
View our documentation to learn more about Changesets. To create a Changeset:
- Navigate to the root of the monorepo in your terminal
- Run
pnpm changesetand follow the prompts - Commit and push the changeset before flagging your PR ready for review.
Original prompt
This section details on the original issue you should resolve
<issue_title>feature:
Carousel</issue_title> <issue_description>### Describe the feature in detail (code, mocks, or screenshots encouraged)Zag: https://zagjs.com/components/carousel WAI: https://www.w3.org/WAI/ARIA/apg/patterns/carousel/
Provide relevant links, wireframes, prototypes, or additional information.
No response</issue_description>
Comments on the Issue (you are @copilot in this section)
- Fixes skeletonlabs/skeleton#4217
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.
🦋 Changeset detected
Latest commit: db1bfc56cbc2f8592cd34826b8156de5a4ec9f80
The changes in this PR will be included in the next version bump.
This PR includes changesets to release 5 packages
| Name | Type |
|---|---|
| @skeletonlabs/skeleton-common | Minor |
| @skeletonlabs/skeleton-svelte | Minor |
| @skeletonlabs/skeleton-react | Minor |
| skeleton | Minor |
| @skeletonlabs/skeleton | Minor |
Not sure what this means? Click here to learn what changesets are.
Click here if you're a maintainer who wants to add another changeset to this PR
The latest updates on your projects. Learn more about Vercel for GitHub.
| Project | Deployment | Review | Updated (UTC) |
|---|---|---|---|
| themes.skeleton.dev | Preview | Dec 22, 2025 4:44pm | |
| www.skeleton.dev | Preview | Dec 22, 2025 4:44pm |
@copilot Add docs and playgrounds, i can't see otherwise what you've built
@copilot Add docs and playgrounds, i can't see otherwise what you've built
Added docs and playgrounds in commit 689eb24.
Playgrounds:
- Svelte:
/playgrounds/skeleton-svelte/src/routes/components/carousel/ - React:
/playgrounds/skeleton-react/src/routes/components/carousel/
Documentation:
- MDX:
/sites/skeleton.dev/src/content/docs/framework-components/carousel.mdx - Examples with default, autoplay, loop, and multiple slides per page
[!WARNING]
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
iojs.org
- Triggering command:
/usr/bin/curl curl --fail --compressed -q -L -s REDACTED -o -(dns block)picsum.photos
- Triggering command:
/home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD v24.11.1/bin/node(dns block)- Triggering command:
/home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD [email protected]/node_modules/@esbuild/linux-x64/bin/esbuild(dns block)telemetry.astro.build
- Triggering command:
/home/REDACTED/.nvm/versions/node/v24.11.1/bin/node node /home/REDACTED/work/skeleton/skeleton/sites/skeleton.dev/node_modules/.bin/../astro/astro.js sync(dns block)If you need me to access, download, or install something from one of these locations, you can either:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to the custom allowlist in this repository's Copilot coding agent settings (admins only)
@copilot declare const anatomy: _zag_js_anatomy.AnatomyInstance<"root" | "itemGroup" | "item" | "control" | "nextTrigger" | "prevTrigger" | "indicatorGroup" | "indicator" | "autoplayTrigger" | "progressText">;
This is the anatomy from ZagJS source, check if you missed any components and implement them.
@copilot declare const anatomy: _zag_js_anatomy.AnatomyInstance<"root" | "itemGroup" | "item" | "control" | "nextTrigger" | "prevTrigger" | "indicatorGroup" | "indicator" | "autoplayTrigger" | "progre...
Added the missing ProgressText component in commit f605581.
All ZagJS carousel anatomy components are now implemented:
- root ✓
- itemGroup ✓
- item ✓
- control ✓
- nextTrigger ✓
- prevTrigger ✓
- indicatorGroup ✓
- indicator ✓
- autoplayTrigger ✓
- progressText ✓ (newly added)
[!WARNING]
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
iojs.org
- Triggering command:
/usr/bin/curl curl --fail --compressed -q -L -s REDACTED -o -(dns block)picsum.photos
- Triggering command:
/home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD /.bin/node(dns block)- Triggering command:
/home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD in/node(dns block)- Triggering command:
/home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD /.bin/node path = substr($sh(dns block)telemetry.astro.build
- Triggering command:
/home/REDACTED/.nvm/versions/node/v24.11.1/bin/node node /home/REDACTED/work/skeleton/skeleton/sites/skeleton.dev/node_modules/.bin/../astro/astro.js sync(dns block)If you need me to access, download, or install something from one of these locations, you can either:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to the custom allowlist in this repository's Copilot coding agent settings (admins only)