-
Notifications
You must be signed in to change notification settings - Fork 16
Potential improvements for the Carousel #4
Copy link
Copy link
Open
Description
Just a few ideas for the carousel, I wrote my own custom carousel and I wouldn't mind if you co-opted some of the ideas or implementation details into your library. It's not perfect or anything but here are some ideas
- You don't need a dedicated CDBCarouselItem component if you just automatically parse the children as CarouselItems by default (unless say they are a CBDCarouselInner or something like that, you can do this automatically)
- Add support to customize the forward and back buttons (I've done a small implementation of this here)
I apologize if it's a little messy, it's a component from a project i had to implement myself because I couldn't find any carousel components I liked on NPM.
import React, { useState } from "react";
import "./carousel.scss";
import hasChildren from "../functions/hasChildren";
export function Carousel(props) {
// Declare a new state variable, which we'll call "count"
const [index, setIndex] = useState(0);
let rotateInterval = null;
const interval = props.hasOwnProperty("interval")
? props.interval
: 30 * 1000;
const children = (
!Array.isArray(props.children) ? [props.children] : props.children
).filter(
(child) =>
child /* exclude null and undefined and other non-truthy values */
);
const goNext = (skipInterval = false) => {
setIndex(getIndexWrapping(index + 1, children.length));
if (!skipInterval) setChangeInterval();
};
const goBack = () => {
setIndex(getIndexWrapping(index - 1, children.length));
setChangeInterval();
};
const setChangeInterval = () => {
if (rotateInterval !== null) {
clearInterval(rotateInterval);
//rotateInterval = null; // redundant as it already gets reassigned
}
rotateInterval = setInterval(() => {
console.log("called");
goNext(true);
}, interval);
};
if (Number.isFinite(interval)) setChangeInterval(interval);
if (children.length < 1) throw new Error("Expected at least 1 child");
const buttons = [];
for (let i = 0; i < children.length; i++) {
const child = children[i];
if (child.type === Next) {
children.splice(i, 1);
i--;
buttons.push(
React.cloneElement(child, {
goNext,
key: buttons.length + 1,
})
);
} else if (child.type === Back) {
children.splice(i, 1);
i--;
buttons.push(
React.cloneElement(child, {
goBack,
key: buttons.length + 1,
})
);
}
}
return (
<div className="carousel">
<span className="content">{children[index]}</span>
<span className="controls">{buttons}</span>
</div>
);
}
function getIndexWrapping(newIndex, total) {
if (!isFinite(total) || total < 1) throw new Error("Invalid Total");
while (newIndex < 0) {
newIndex += total;
}
newIndex = newIndex % total;
return newIndex;
}
export function Next(props) {
const componentProps = { ...props };
delete componentProps.children;
delete componentProps.goNext;
if (componentProps.hasOwnProperty("className")) {
componentProps.className =
typeof componentProps.className == "string"
? "next " + componentProps.className
: "next";
} else {
componentProps.className = "next";
}
return (
<button onClick={props.goNext} {...componentProps}>
{hasChildren(props.children) ? props.children : Next}
</button>
);
}
export function Back(props) {
const componentProps = { ...props };
delete componentProps.children;
delete componentProps.goBack;
if (componentProps.hasOwnProperty("className")) {
componentProps.className =
typeof componentProps.className == "string"
? "back " + componentProps.className
: "back";
} else {
componentProps.className = "back";
}
return (
<button onClick={props.goBack} {...componentProps}>
{hasChildren(props.children) ? props.children : Back}
</button>
);
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels