@slidy/react
Simple, configurable & reusable carousel component built with React based on @slidy/core.
Try the demo.
Getting started
The package is available via npm:
npm i @slidy/react
Usage
The most simple way to get started is to use named import of <Slidy />
component:
import { Slidy } from '@slidy/react';
import '@slidy/react/dist/slidy.css';
const slides = [
{
id: 1,
width: 800,
height: 1200,
src: 'static/img/some-image.webp',
},
];
export default () => {
return <Slidy slides={slides} />;
};
All props are optional. The only property to get started is slides
- an array of objects with image related data.
You will also have to import css styles:
import '@slidy/react/dist/slidy.css';
Core Component
Core
is a wrapper component for @slidy/core available via named import. It is best to use to build up the custom component for specific needs or when just the basic functionality is needed.
import { Core } from '@slidy/react';
export default () => {
return <Core />;
};
Core Component API
Property | Default | Type | Description |
---|---|---|---|
animation |
undefined |
AnimationFunc |
Custom slide animation. |
axis |
"x" |
"x" or "y"
|
The scroll direction. |
clamp |
0 |
number |
Clamps sliding index as {clamp} - {index} + {clamp}
|
className |
"" |
string |
Passes the class to the node. |
duration |
450 |
number |
Slide transitions duration value. |
easing |
undefined |
(t: number => number) |
Inertion scroll easing behaviour. |
gravity |
1.2 |
number |
Scroll inertia value. |
indent |
0 |
number |
Custom scroll indent value, calculates as gap * indent . |
index |
0 |
number |
The index of the initial slide. |
setIndex |
undefined |
React.Dispatch<React.SetStateAction<number>> |
Set's index of a current slide. |
plugins |
undefined |
ReturnType<PluginFunc>[] |
Plugins to operate with the slidy instance and its options directly. |
loop |
false |
boolean |
Makes the slideshow continious. |
sensity |
5 |
number |
Defines the sliding sensity as the number of pixels required to drag. |
snap |
undefined |
"start" or "center" or "end" or "deck"
|
Enforces the scroll stop positions. |
tag |
ol |
string |
The HTML tag name to render. |
onResize |
undefined |
(event: CustomEvent<{ ROE: ResizeObserverEntry[] }>) => void |
Listen to the core event resize to fire. |
onMount |
undefined |
(event: CustomEvent<Options>) => void |
Listen to the core event mount to fire. |
onMove |
undefined |
(event: CustomEvent<{ index: number; position: number }>) => void |
Listen to the core event move to fire. |
onIndex |
undefined |
(event: CustomEvent<{ index: number }>) => void |
Listen to the core event index to fire. |
onKeys |
undefined |
(event: CustomEvent<string>) => void |
Listen to the core event keys to fire. |
onUpdate |
undefined |
(event: CustomEvent<Options>) => void |
Listen to the core event update to fire. |
onDestroy |
undefined |
(event: CustomEvent<HTMLElement>) => void |
Listen to the core event destroy to fire. |
For TypeScript users there is the SlidyCoreOptions
interface available via named import.
Slidy Component
<Slidy />
component uses <Core />
internally and provides more features expected from carousel.
Slidy Component API
The <Slidy />
component interface extends the <Core />
. There are a list of additional options available:
Property | Default | Type | Description |
---|---|---|---|
arrows |
true |
boolean or () => JSXElement
|
Renders the arrow button controls for accessible slide navigation. |
arrow |
undefined |
() => JSXElement |
Renders the arrow. |
children |
undefined |
(item: Slide) => JSXElement |
Renders each slide. |
overlay |
undefined |
() => JSXElement |
Renders the overlay. |
background |
false |
boolean |
Sets background-image instead of <img /> elements to display slides. |
classNames |
SlidyStyles |
SlidyStylesDefault |
The class names object used over the component. |
getImgSrc |
item => item.src |
function |
The slide's src attribute getter. |
getThumbSrc |
item => item.src |
function |
The thumbnail's src attribute getter. |
i18n |
i18nDefaults |
I18NDict |
The i18n localization dictionary. |
navigation |
false |
boolean |
Renders the navigation controls for pagination-like slide navigation. |
groups |
0 |
number |
Controls the number of items displayed per viewport. |
progress |
false |
boolean |
Renders the progress bar. |
slides |
[] |
Slides[] |
An array of objects with image metadata. |
thumbnail |
false |
boolean or () => JSXElement
|
Renders the thumbnail navigation panel. |
onResize |
undefined |
(event: CustomEvent<{ ROE: ResizeObserverEntry[] }>) => void |
Listen to the core event resize to fire. |
onMount |
undefined |
(event: CustomEvent<Options>) => void |
Listen to the core event mount to fire. |
onMove |
undefined |
(event: CustomEvent<{ index: number; position: number }>) => void |
Listen to the core event move to fire. |
onIndex |
undefined |
(event: CustomEvent<{ index: number }>) => void |
Listen to the core event index to fire. |
onKeys |
undefined |
(event: CustomEvent<string>) => void |
Listen to the core event keys to fire. |
onUpdate |
undefined |
(event: CustomEvent<Options>) => void |
Listen to the core event update to fire. |
onDestroy |
undefined |
(event: CustomEvent<HTMLElement>) => void |
Listen to the core event destroy to fire. |
plugins |
undefined |
ReturnType<PluginFunc>[] |
Plugins to operate with the slidy instance and its options directly. |
By default component works with images. Image object should contain width
and height
attributes to prevent layout shifts and alt
for accessibility.
Styling
Extending/Overriding classes
To extend default component styles use classNames
property. Default classes are available via object, that can be extended or overridden:
import { Slidy, classNames } from '@slidy/react';
import '@slidy/react/dist/slidy.css';
export default () => {
return (
<Slidy
classNames={{
root: `${classNames.root} custom-class`,
...classNames,
}}
/>
);
};
The classNames
consist of { target: className }
pairs:
Target | Default class | Description |
---|---|---|
arrow | slidy-arrow |
Arrow controls. |
autoplay | slidy-autoplay |
Autoplay control. |
counter | slidy-counter |
Slide progress counter. |
img | slidy-img |
Slide image node. |
nav | slidy-nav |
Slide navigation panel. |
nav-item | slidy-nav-item |
Navigtion panel item. |
overlay | slidy-overlay |
Slides overlay node. |
progress | slidy-progress |
Slide progress bar. |
root | slidy |
Component's root node. |
slide | slidy-slide |
Slide item node. |
slides | slidy-slides |
Slides list node. |
thumbnail | slidy-thumbnail |
Thumbnail item. |
thumbnail | slidy-thumbnails |
Thumbnails bar. |
Custom Properties API
For easier style customization Slidy
provides a set of predefined custom properties to inherit:
List of available public custom properties:
Property | Default | Type | Description |
---|---|---|---|
--slidy-arrow-bg |
#4e4e4ebf | <color> |
The arrow control background color. |
--slidy-arrow-bg-hover |
#4e4e4e54 | <color> |
The arrow control hover background color. |
--slidy-arrow-icon-color |
currentColor | <color> |
The arrow control icon fill color. |
--slidy-arrow-size |
24px | <length> |
The arrow controls size. |
--slidy-autoplay-control-size |
2.25em | <length> |
The autoplay control size. |
--slidy-autoplay-indicator-accent |
lightpink | The autoplay control indicator ring color. | |
--slidy-counter-bg |
#4e4e4ebf | <color> |
The counter's background color. |
--slidy-focus-ring-color |
#c9c9c9e6 | <color> |
Focus ring color for all focusable elements. |
--slidy-height |
100% | <length> |
The height of the component's node. |
--slidy-nav-item-color |
white | <color> |
The navigation elements color. |
--slidy-nav-item-radius |
50% | <length> |
The navigation elements border radius. |
--slidy-nav-item-size |
16px | <length> |
The navigation elements size. |
--slidy-progress-thumb-color |
#c44f61 | <color> |
The progress bar active track color. |
--slidy-progress-track-color |
#96969680 | <color> |
The progress bar track color. |
--slidy-progress-track-size |
5px | <length> |
The progress bar height. |
--slidy-slide-aspect-ratio |
unset | <int/int> |
Defines the slide aspect-ratio. |
--slidy-slide-bg-color |
darkgray | <color> |
The placeholder background color for loading images. |
--slidy-slide-gap |
1rem | <length> |
The gap between items in carousel. |
--slidy-slide-height |
100% | <length> |
The carousel items height. |
--slidy-slide-object-fit |
cover | - | The carousel items (images) resize behaviour. |
--slidy-slide-radius |
1rem | <length> |
The slide's border radius value. |
--slidy-slide-width |
auto | <length> |
The carousel items width. |
--slidy-thumbnail-radius |
0.5rem | <length> |
The thumbnail border-radius value. |
--slidy-thumbnail-size |
50px | <length> |
The thumbnail panel size. |
--slidy-width |
100% | <length> |
The width of the component's node. |
Inherited custom properties
All supported custom properties starts with --slidy-
. For example, to recolor navigation controls, let the component inherit a --slidy-nav-item-color
custom property from any parent:
.parent {
--slidy-navigation-color: red;
}
export default () => {
return (
<div class="parent">
<Slidy />
</div>
);
};
Or just pass a class with a set of custom properties:
.some-class {
--slidy-navigation-color: red;
--slidy-nav-item-size: 1rem;
}
import { Slidy, classNames } from '@slidy/react';
import '@slidy/react/dist/slidy.css';
export default () => {
return (
<Slidy
classNames={{
root: `${classNames.root} .some-class`,
...classNames,
}}
/>
);
};
Slots
arrow
Customizes the content of the default arrow controls.
arrows
Provides a slot for custom arrow buttons.
If the nodes are <button />
and the data-step
attribute is present, the event listener is not needed. Just provide the values -1
and 1
for data-step
on custom buttons.
Also, there are grid-area
is present in the layout for this custom controls: prev-slide
and next-slide
respectively.
button:first-of-type {
grid-area: prev-slide;
}
button:last-of-type {
grid-area: next-slide;
}
export default () => {
return (
<Slidy
arrows={() => (
<>
<button data-step="-1"> Show the previous slide </button>
<button data-step="1"> Show the next slide </button>
</>
)}
/>
);
};
default
Usually the default markup is not enough. The default
slot solves this problem. To use custom slide markup slot expose each slides
prop item item
argument.
export default () => {
return (
<Slidy>
{(item) => (
<figure>
<img src={item.src} alt={item.figcaption} />
<figcaption>{item.figcaption}</figcaption>
</figure>
)}
</Slidy>
);
};
overlay
Slot to display content overlaid content. It covers the slides area and can be customized by overriding the .slidy-overlay
. For example, it is used to display the counter.
export default () => {
return <Slidy overlay={() => <button> Share </button>} />;
};
i18n
To modify all texts used in the component use pass the dictionary as i18n
prop. For the sake of accessibility, it is recommended translating defaults:
Key | Default | Event detail |
---|---|---|
carousel |
"carousel" |
aria-label of a root element. |
counter |
"%s of %s" |
aria-label of each slide as {slide number} of {slide length} |
first |
"Go to the first slide" |
aria-label of the first item at the navigation. |
last |
"Go to the last slide" |
aria-label of the last item at the navigation. |
next |
"Go to the next slide" |
aria-label of the arrow control. |
play |
"Start autoplay" |
aria-label of the autoplay control. |
prev |
"Return back to previous slide" |
aria-label of the arrow control. |
slide |
"Slide" |
aria-roledescription of each slide item. |
slideN |
"Go to the slide %s" |
aria-label of pagination of each slide item. |
stop |
"Stop autoplay" |
aria-label of the autoplay control. |
Recipes
External controls
It is possible to control the navigation of the Slidy
instance from the parent component via binding.
There are two variables available to control the component externally: index
and position
. Declare the variables to hold the values and bind them to the instance for the carousel control.
import { Slidy } from '@slidy/react';
import { useState } from 'react';
import '@slidy/react/dist/slidy.css';
export default () => {
const [index, setIndex] = useState(0);
return (
<>
<Slidy slides={slides} index={index} setIndex={setIndex} />
<button onClick={() => setIndex((prev) => prev + 1)}>Next slide</button>
</>
);
};
Possible issues
- Slides should not have
absolute
positioning, otherwise the core script won't get correct dimentions; - Using the
background
option usually is not recommended. In case you need to use it, specify the slide sizes with custom properties:width
andheight
, or justaspect-ratio
.
License
Slidy is distributed under the MIT license