UNPKG

@slidy/solid

Version:

Simple, configurable & reusable carousel component built with SolidJS

384 lines (306 loc) 22.8 kB
<div align="center"> <a href="https://www.npmjs.com/package/@slidy/solid"> <img alt="npm package version" src="https://img.shields.io/npm/v/@slidy/solid?style=flat-square" /> </a> <a href="https://www.npmjs.com/package/@slidy/solid"> <img alt="types included" src="https://img.shields.io/npm/types/@slidy/solid?style=flat-square" /> </a> <a href="https://www.npmjs.com/package/@slidy/solid"> <img alt="downloads count" src="https://img.shields.io/npm/dm/@slidy/solid?style=flat-square" /> </a> <a href="https://www.npmjs.com/package/@slidy/solid"> <img alt="licence" src="https://img.shields.io/npm/l/@slidy/solid?style=flat-square" /> </a> <a href="https://bundlephobia.com/package/@slidy/solid"> <img alt="minzipped size" src="https://img.shields.io/bundlephobia/minzip/@slidy/solid?label=minzip&style=flat-square" /> </a> </div> # @slidy/solid Simple, configurable & reusable carousel component built with SolidJS based on [@slidy/core](https://github.com/Valexr/slidy/tree/master/packages/core). Try the [demo](https://playground.solidjs.com/?hash=-1777461998&version=1.4.1). ## Getting started The package is available via [npm](https://www.npmjs.com/package/@slidy/solid): ``` npm i @slidy/solid ``` ## Usage The most simple way to get started is to use named import of `<Slidy />` component: ```jsx import { Slidy } from '@slidy/solid'; import '@slidy/solid/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:** ```jsx import '@slidy/solid/dist/slidy.css'; ``` ## Core Component `Core` is a wrapper component for [@slidy/core](https://github.com/Valexr/slidy/tree/master/packages/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. ```tsx import { Core } from '@slidy/solid'; 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` | Defines number of items to jump over at one slide action. | | `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. | | `plugins` | `undefined` | `ReturnType<PluginFunc>[]` | Plugins to operate with the slidy instance and its options directly. | | `loop` | `false` | `boolean` | Makes the slideshow continious. | | `position` | `0` | `number` | The current position value of the carousel. | | `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[]; options: SlidyCoreOptions }>) => void` | Listen to the core event `resize` to fire. | | `onMutate` | `undefined` | `(event: CustomEvent<{ ML: MutationRecord[]; options: SlidyCoreOptions }>) => void` | Listen to the core event `mutate` to fire. | | `onMount` | `undefined` | `(event: CustomEvent<SlidyCoreOptions>) => 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<SlidyCoreOptions>) => 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. | | `onMutate` | `undefined` | `(event: CustomEvent<{ ML: MutationRecord[] }>) => void` | Listen to the core event `mutate` to fire. | | `onMount` | `undefined` | `(event: CustomEvent<SlidyCoreOptions>) => 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<SlidyCoreOptions>) => void` | Listen to the core event `update` to fire. | | `onDestroy` | `undefined` | `(event: CustomEvent<HTMLElement>) => void` | Listen to the core event `destroy` to fire. | | `vertical` | `false` | `boolean` | Defines the slides flow by using `aria-orientation`. | 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: ```jsx import { Slidy, classNames } from '@slidy/solid'; import '@slidy/solid/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. | | 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. | | progress-handle | `slidy-progress-hadle` | Slide progress bar control handle. | | 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-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` | 10px | `<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: ```css .parent { --slidy-navigation-color: red; } ``` ```jsx export default () => { return ( <div class="parent"> <Slidy /> </div> ); }; ``` Or just pass a class with a set of custom properties: ```css .some-class { --slidy-navigation-color: red; --slidy-nav-item-size: 1rem; } ``` ```jsx import { Slidy, classNames } from '@slidy/solid'; import '@slidy/solid/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. ```css button:first-of-type { grid-area: prev-slide; } button:last-of-type { grid-area: next-slide; } ``` ```jsx 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. ```jsx 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. ```jsx 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. ```jsx import { Slidy } from '@slidy/solid'; import { createSignal } from 'solid-js'; import '@slidy/solid/dist/slidy.css'; export default () => { const [index, setIndex] = createSignal(0); const [position, setPosition] = createSignal(0); return ( <> <Slidy index={index} setIndex={setIndex} position={position} setPosition={setPosition} /> <button onClick={() => setIndex((prev) => prev + 1)}>Next slide</button> <button onClick={() => setPosition((prev) => prev + 50)}>Move</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` and `height`, or just `aspect-ratio`. ## License Slidy is distributed under the MIT license