En este post, vamos a desarrollar un Carrusel utilizando la librería Embla Carousel, el framework Next.js y la librería Chakra UI - esta última, al igual que Next.js, desarrollada por Vercel y la comunidad Open Source.
A lo largo del post, aprenderemos:
- Por qué elegir Embla Carousel
- Cómo integrar Embla Carousel a tu proyecto en Next.js y Chakra UI
- Cómo agregar paginación a tu Carousel
Si querés ir directamente al repositorio en GitHub puedes hacerlo desde aquí
¿Qué es Embla Carousel?
Embla Carousel es una librería agnóstica que, como su nombre lo indica, facilita la construcción de carruseles. Su uso garantiza fluidez y precisión tanto en el movimiento como deslizamiento de los elementos (slides) que componen al carrusel. Es una librería dependency-free y liviana, por lo que su instalación es rápida y posee una baja dependencia de otras librerías para su funcionamiento.
De muy fácil integración a tu proyecto, con una API muy bien documentada y una extensa lista de plugins que permiten potenciar las funciones de tu componente carrusel.
Por último, Embla Carousel funciona en todos los navegadores modernos, incluido IE11.
Configurar nuestro proyecto
Crea un proyecto nuevo utilizando el comando create-next-app
:
npx create-next-app my-awesome-embla-carousel
Una vez creado el proyecto y dentro del mismo, vamos a continuar instalando las dependencias necesarias para integrar Chakra UI. Según la documentación oficial:
npm i @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^6
# or
yarn add @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^6
Por último, pero no menos importante, vamos a agregar a nuestro proyecto la versión de la librería Embla Carousel para React:
npm install embla-carousel-react --save
Hasta el momento, tu archivo package.json
debería verse de la siguiente manera:
Recuerda que las versiones de las dependencias pueden variar. Al momento de escribir este post, la versión de la librería Embla Carousel React es la 6.2.0
Estructura básica del componente Carousel
Para su integración con React, Embla Carousel provee el hook useEmblaCarousel
. El mismo devuelve dos parámetros, la referencia al carrusel que luego será utilizada en la composición visual de nuestro componente y la API que nos dará acceso a todos los métodos disponibles.
import useEmblaCarousel from 'embla-carousel-react'
const [emblaRef, emblaApi] = useEmblaCarousel()
A su vez, useEmblaCarousel
permite la asignación de opciones globales a nuestro carrusel. A modo de ejemplo:
const [emblaRef, embla] = useEmblaCarousel({
// alinea el primer slide al principio del viewport,
// caso contrario, por defecto, lo hará en el medio
align: "start",
// si el carrusel llegá al final retorna
// automáticamente al primer slide
loop: true,
// determina si el usuario puede desplazar los slides
// a través del mouse u otra interacción. Por defecto: true
draggable: false,
// determina la velocidad de desplazamiento entre slides.
speed: 15,
// ... más opciones globales
});
- la asignación de opciones globales debe realizarse por única vez y hacerse antes de inicializar el carrusel. Caso contrario, re asignar opciones globales puede producir efectos inesperados en el comportamiento del componente carrusel.
Para una lista detallada de las opciones globales posibles, consultar aquí.
Por otro lado, la composición visual de nuestro carrusel va a requerir de una estructura básica de tres elementos - o sub componentes:
Viewport
- El hook nos da una referencia para asociar al elemento envolvente - padre -, necesario para manipular el excedente o desbordamiento con la propiedad overflow:hidden
Container
- Un contenedor que encerrará todos los slides del carrusel bajo la propiedad flex-row
Slides
- Tendrá un listado con cada slide de nuestro carrusel
Comencemos a programar
Hasta ahora:
- Aprendimos qué es Embla Carousel
- Instalamos un proyecto Next.js
- Limpiamos la estructura de nuestro proyecto
- Agregamos las dependencias necesarias de Embla Carousel y Chakra UI
¡Es hora de empezar a trabajar con código! Vamos a construir un carrusel con repositorios de proyectos bajo distintas tecnologías y programadores. La información para completar cada slide - imagen, desarrollador, titulo, indicadores, descripción, ect - puede ser consumida de forma local o directamente desde una API. En nuestro caso, usaremos un archivo local repositories.js
al proyecto que provee un arreglo de objetos con toda la información necesaria. Para la navegación entre los slides usaremos de ejemplo una paginación de puntos (dot's type pagination).
Nuestro archivo index.jsx
debería verse de la siguiente manera:
import { ChakraProvider } from '@chakra-ui/react'
import useEmblaCarousel from 'embla-carousel-react'
import { useEffect, useCallback, useState } from 'react'
import { Container, Flex, Heading, Button, Box } from '@chakra-ui/react'
import SlideImage from '../components/SlideImage'
import SlideDetails from '../components/SlideDetails'
import repositories from '../../repositories'
const EmblaCarousel = () => {
const [emblaRef, emblaApi] = useEmblaCarousel({ loop: false })
const [scrollSnaps, setScrollSnaps] = useState([]);
const [selectedIndex, setSelectedIndex] = useState(0);
/*
* función que a través de la API de Embla Carousel
* y el método scrollTo permite navegar al índice
* correspondiente al "dot" de la navegación
*/
const scrollTo = useCallback(
(index) => emblaApi && emblaApi.scrollTo(index),
[emblaApi]
);
/*
* función que actualiza el estado del índice
* correspondiente al slide actual
*/
const onSelect = useCallback(() => {
if (!emblaApi) return;
setSelectedIndex(emblaApi.selectedScrollSnap);
}, [emblaApi, setSelectedIndex]);
/*
* por cada re-renderizado del componente nos aseguramos que
* la librería Embla esté "montada" correctamente
*/
useEffect(() => {
if (!emblaApi) return;
onSelect();
setScrollSnaps(emblaApi.scrollSnapList);
emblaApi.on("select", onSelect);
}, [emblaApi, setScrollSnaps, onSelect]);
return (
{/* código de renderizado detallado abajo */}
)
}
export default EmblaCarousel
Seguimos sumando código a nuestro archivo index.jsx
, ahora el encargado de renderiza el elemento Carrusel:
return (
<ChakraProvider>
<Box bg="#030c1b" minHeight="100vh">
<Container maxW="100%" py={10} >
<Heading textAlign="center" color="white">
My awesome Embla Carousel using + NextJS + Chakra
</Heading>
</Container>
{/* Viewport */}
<Box overflow="hidden" maxW="100%" p={0} ref={emblaRef} >
{/* Container */}
<Flex h='auto' py={[0, 5, 5]}>
{/* Slides */}
{repositories.map(repo => {
return (
<Flex key={repo.id} direction={{ base: 'column', md: 'row' }} justifyContent="center" position="relative" flex="0 0 100%">
<SlideImage imageSrc={repo.imgSrc} />
<SlideDetails item={repo} />
</Flex>
)
})}
</Flex>
</Box>
</Box>
</ChakraProvider>
)
Considere que los componentes SlideImage
y SlideDetails
tienen el objetivo de agregarle sentido en términos tanto de diseño como de contenido al carrrusel. Si lo desean podrán descargarlos directamente desde acá, sino, podrán crear su propio contenido y diseño.
Las imágenes utilizadas, pueden descargarse también del repositorio desde aquí. Las mismas están ubicadas en la carpeta public/images
de Next.js, destinada para servir archivos estáticos.
Hasta ahora, le hemos dado estilo a nuestro componente carrusel de repositorios, donde cada slide posee una imagen a la izquierda y detalles del repositorio a la derecha. Además, el componente ocupará el 100% de la viewport por lo que se mostrará de a un slide a la vez.
Por último, nos queda agregar el sistema de paginación de puntos. El mismo nos da una idea de la cantidad de elementos - slides - que posee el carrusel y a la vez provee una herramienta práctica para desplazarse entre cada slide.
Agregamos el siguiente código al final de nuestro archivo index.jsx
, dentro del provedor de contexto de Chakra UI(ChakraProvider
):
return (
<ChakraProvider>
{/* código correspondiente al elemento carrusel */}
<Container maxW="container.xl" py={10}>
<Flex justifyContent="center" alignItems="center" mt={5}>
{scrollSnaps.map((_, idx) => (
<Button w={2} h={2} mx={1} size="3" bg={idx === selectedIndex ? "yellow.500" : "gray.300"} key={idx}
onClick={() => scrollTo(idx)}/>
))}
</Flex>
</Container>
</ChakraProvider>
)
Terminamos!! Recordá que cualquier duda o comentario siempre serán bienvenidos!
Podés descargarte el repositorio del proyecto completo desde aquí.
Conclusiones
Hemos aprendido a crear fácilmente un carrusel con la ayuda de la librería Embla Carousel e integrarlo a nuestro proyecto de Next.js y Chakra UI.
Embla Carousel es muy simple y te permite crear elementos con tu propio estilo según tus necesidades.
Hasta la próxima!!!
Links de interes
Embla Carousel
React Embla Carousel
Embla API
Next.js
Chakra UI
Top comments (0)