Carousel
Carousels are for displaying a related set of content items in a row. Items can be paged using the next/previous buttons or by a swipe gesture.
- Install
npm install @pluralsight/ps-design-system-carousel
- Import
import Carousel from '@pluralsight/ps-design-system-carousel'
Examples
Size
The number and width of items in the Carousel are handled automatically. Item min and max width constraints will adjust based on the size
prop passed the Carousel. Similarly, the number of items in the Carousel can be controlled by constraining the width of a container element around the Carousel.
The content that you pass as a child to Carousel.Item
to be responsive. In the case of Card
, a common item child, the width is 100%
, infinitely flexible. If not sufficiently flexible, the carousel will not look great. If the child can't expand to fill the item, the gutters will be off. If the child can't shrink to fit the item, the paging will be off.
import Card from '@pluralsight/ps-design-system-card'import Carousel from '@pluralsight/ps-design-system-carousel'import React from 'react'function Example() {return (Object.values(Carousel.sizes).map(size => (<Carousel size={size}>{MOCK_DATA.courses.map(course => (<Carousel.Item key={course.id}><Cardimage={<Card.Image src="https://picsum.photos/seed/picsum/540/360" />}metadata1={[course.author, course.level]}progress={randomInt()}title={<Card.Title>{course.title}</Card.Title>}/></Carousel.Item>))}</Carousel>)))}export default Exampleconst randomInt = (max = 100) => Math.floor(Math.random() * Math.floor(max))const MOCK_DATA = {courses: [{author: 'Jim Cooper',id: '1',level: 'Intermediate',title: 'Vue.js Fundamentals'},{author: 'Mark Heath',id: '2',level: 'Intermediate',title: 'Azure Functions Fundamentals'},{author: 'Kyle Simpson',id: '3',level: 'Advanced',title: 'Advanced JavaScript'},{author: 'Mark Zamoyta',id: '4',level: 'Advanced',title: 'Rapid JavaScript Training'},{author: 'Dan Wahlin',id: '5',level: 'Advanced',title: 'Structuring JavaScript Code'},{author: 'Jim Cooper',id: '6',level: 'Advanced',title: 'JavaScript Objects and PropTypes'},{author: 'Jim Cooper',id: '11',level: 'Intermediate',title: 'Vue.js Fundamentals'},{author: 'Mark Heath',id: '12',level: 'Intermediate',title: 'Azure Functions Fundamentals'},{author: 'Kyle Simpson',id: '13',level: 'Advanced',title: 'Advanced JavaScript'},{author: 'Mark Zamoyta',id: '14',level: 'Advanced',title: 'Rapid JavaScript Training'},{author: 'Dan Wahlin',id: '15',level: 'Advanced',title: 'Structuring JavaScript Code'},{author: 'Jim Cooper',id: '16',level: 'Advanced',title: 'JavaScript Objects and PropTypes'},{author: 'Jim Cooper',id: '21',level: 'Intermediate',title: 'Vue.js Fundamentals'},{author: 'Mark Heath',id: '22',level: 'Intermediate',title: 'Azure Functions Fundamentals'},{author: 'Kyle Simpson',id: '23',level: 'Advanced',title: 'Advanced JavaScript'},{author: 'Mark Zamoyta',id: '24',level: 'Advanced',title: 'Rapid JavaScript Training'},{author: 'Dan Wahlin',id: '25',level: 'Advanced',title: 'Structuring JavaScript Code'},{author: 'Jim Cooper',id: '26',level: 'Advanced',title: 'JavaScript Objects and PropTypes'}]}
Use portals for overflow
If there are any UI elements that need to appear in the same visual space as the carousel container, they will need to be rendered outside the Carousel
DOM. This is because the Carousel container solution requires being styled overflow: hidden
. A React Portal is a great solution. A common example could be an ActionMenu
rendered from a Card
. Here is some example code:
import ActionMenu from '@pluralsight/ps-design-system-actionmenu'import { BelowRight } from '@pluralsight/ps-design-system-position'import Card from '@pluralsight/ps-design-system-card'import Carousel from '@pluralsight/ps-design-system-carousel'import { MoreIcon } from '@pluralsight/ps-design-system-icon'import React from 'react'function Example() {return (<Carousel size={Carousel.sizes.wide}>{MOCK_DATA.courses.map(course => (<Carousel.Item key={course.id}><Toggle>{({ active, toggle }) => (<Cardimage={<Card.Image src={course.image} />}metadata1={[course.author, course.level]}title={<Card.Title>{course.title}</Card.Title>}actionBarVisibleactionBar={[<BelowRightinNode={typeof document !== 'undefined' && document.body}when={active}show={<ActionMenu onClick={toggle}><ActionMenu.Item>Useless item</ActionMenu.Item><ActionMenu.Item>Useless item</ActionMenu.Item><ActionMenu.Item>Useless item</ActionMenu.Item><ActionMenu.Item>Useless item</ActionMenu.Item><ActionMenu.Item>Useless item</ActionMenu.Item><ActionMenu.Item>Useless item</ActionMenu.Item><ActionMenu.Item>Useless item</ActionMenu.Item><ActionMenu.Item>Useless item</ActionMenu.Item></ActionMenu>}key="a"><Card.Actiontitle="See more"icon={<MoreIcon />}onClick={toggle}/></BelowRight>]}/>)}</Toggle></Carousel.Item>))}</Carousel>)}export default Examplefunction Toggle(props) {const [active, setActive] = React.useState(typeof props.active === 'undefined' ? !!props.startActive : !!props.active)function toggle() {setActive(!active)}return props.children({ active, toggle })}const MOCK_DATA = {courses: [{author: 'Jim Cooper',id: '1',level: 'Intermediate',title: 'Vue.js Fundamentals'},{author: 'Mark Heath',id: '2',level: 'Intermediate',title: 'Azure Functions Fundamentals'},{author: 'Kyle Simpson',id: '3',level: 'Advanced',title: 'Advanced JavaScript'},{author: 'Mark Zamoyta',id: '4',level: 'Advanced',title: 'Rapid JavaScript Training'},{author: 'Dan Wahlin',id: '5',level: 'Advanced',title: 'Structuring JavaScript Code'},{author: 'Jim Cooper',id: '6',level: 'Advanced',title: 'JavaScript Objects and PropTypes'},{author: 'Jim Cooper',id: '11',level: 'Intermediate',title: 'Vue.js Fundamentals'},{author: 'Mark Heath',id: '12',level: 'Intermediate',title: 'Azure Functions Fundamentals'},{author: 'Kyle Simpson',id: '13',level: 'Advanced',title: 'Advanced JavaScript'},{author: 'Mark Zamoyta',id: '14',level: 'Advanced',title: 'Rapid JavaScript Training'},{author: 'Dan Wahlin',id: '15',level: 'Advanced',title: 'Structuring JavaScript Code'},{author: 'Jim Cooper',id: '16',level: 'Advanced',title: 'JavaScript Objects and PropTypes'},{author: 'Jim Cooper',id: '21',level: 'Intermediate',title: 'Vue.js Fundamentals'},{author: 'Mark Heath',id: '22',level: 'Intermediate',title: 'Azure Functions Fundamentals'},{author: 'Kyle Simpson',id: '23',level: 'Advanced',title: 'Advanced JavaScript'},{author: 'Mark Zamoyta',id: '24',level: 'Advanced',title: 'Rapid JavaScript Training'},{author: 'Dan Wahlin',id: '25',level: 'Advanced',title: 'Structuring JavaScript Code'},{author: 'Jim Cooper',id: '26',level: 'Advanced',title: 'JavaScript Objects and PropTypes'}]}
Guidelines
The height of the carousel adapts to the height of the content it contains, but the width of its children will be equalized, so make sure to use related content for children that are intended to be used at the same height and width.
Accessibility
WCAG 2.1 AA Compliance
100% axe-core testsManual audit
WAI-ARIA Patterns: Carousel
Props
Carousel
Name | Type | Description | Default |
---|---|---|---|
children Required | Carousel.Item | items to place in carousel |
|
size |
| size of carousel items | medium |
Carousel.Controls
Name | Type | Description | Default |
---|---|---|---|
children Required | React.ReactNode | controls to advance carousel frames |
|
Carousel.Control
Name | Type | Description | Default |
---|---|---|---|
direction Required |
| (from Carousel.Control.directions) |
|
Carousel.Item
Name | Type | Description | Default |
---|---|---|---|
children Required | React.ReactNode | () => React.ReactNode | render prop used to access item and page metadata |
|