Skip to content

Commit ca1cb33

Browse files
committed
added support for responsive height
1 parent 94921d1 commit ca1cb33

9 files changed

Lines changed: 118 additions & 55 deletions

File tree

README.md

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,34 @@ export default function App() {
5252
}
5353
```
5454

55+
## Responsive height
56+
57+
Height prop supports [Tailwind CSS based](https://tailwindcss.com/docs/responsive-design) breakpoint system to accommodate responsive design.
58+
To specify a height at a certain breakpoint, prefix the breakpoint name, followed by the ":" character.
59+
60+
```html
61+
<!-- 200px on mobile (default), 500px on medium screens and 750px on large screens -->
62+
<StackedCarousel height="200 md:500 lg:750">{...}</StackedCarousel>
63+
```
64+
65+
Visit [responsive-design](https://tailwindcss.com/docs/responsive-design) for the exhaustive list of supported breakpoints.
66+
5567
## Props
5668

57-
| Prop | Type | Default | Required | Description |
58-
| ----------------------- | --------- | ------------------------------------ | -------- | ------------------------------------------------- |
59-
| `height` | number | - | Yes | Height of the carousel. |
60-
| `children` | ReactNode | - | Yes | Children nodes of the carousel. |
61-
| `autoplay` | boolean | false | No | Automatically transition between items. |
62-
| `autoplayInterval` | number | 4000 | No | Interval between automatic transitions. |
63-
| `containerClassName` | string | - | No | CSS class name for the carousel container. |
64-
| `easingFunction` | string | cubic-bezier(0.93, 0.01, 0.39, 1.01) | No | Easing function to use for the transitions. |
65-
| `navContainerClassName` | string | - | No | CSS class name for the navigation container. |
66-
| `onNext` | function | - | No | Callback function on moving to the next item. |
67-
| `onPrevious` | function | - | No | Callback function on moving to the previous item. |
68-
| `scaleFactor` | number | 0.9 | No | Scale factor for the carousel items. |
69-
| `startIndex` | number | 0 | No | Index of the item to start on. |
70-
| `transitionDuration` | number | 400 | No | Duration of the transitions in milliseconds. |
71-
| `verticalOffset` | number | 10 | No | % vertical offset for the carousel items. |
69+
| Prop | Type | Default | Required | Description |
70+
| -------------------- | ---------------- | ------------------------------------ | -------- | ------------------------------------------------- |
71+
| `height` | number or string | - | Yes | Height of the carousel. |
72+
| `children` | ReactNode | - | Yes | Children nodes of the carousel. |
73+
| `autoplay` | boolean | false | No | Automatically transition between items. |
74+
| `autoplayInterval` | number | 4000 | No | Interval between automatic transitions. |
75+
| `easingFunction` | string | cubic-bezier(0.93, 0.01, 0.39, 1.01) | No | Easing function to use for the transitions. |
76+
| `onNext` | function | - | No | Callback function on moving to the next item. |
77+
| `onPrevious` | function | - | No | Callback function on moving to the previous item. |
78+
| `styleOverrides` | object | - | No | Override default styles of the carousel |
79+
| `scaleFactor` | number | 0.9 | No | Scale factor for the carousel items. |
80+
| `startIndex` | number | 0 | No | Index of the item to start on. |
81+
| `transitionDuration` | number | 400 | No | Duration of the transitions in milliseconds. |
82+
| `verticalOffset` | number | 10 | No | % vertical offset for the carousel items. |
7283

7384
## Running locally
7485

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-card-stack-carousel",
3-
"version": "0.1.5",
3+
"version": "0.2.0",
44
"description": "A tiny configurable carousel component for React",
55
"main": "dist/index.js",
66
"scripts": {

playground/App.jsx

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,15 @@
11
import React from "react";
2-
import { StackedCarousel } from "react-card-stack-carousel";
2+
import { StackedCarousel } from "react-card-stack-carousel/index";
33
import "react-card-stack-carousel/styles/styles.css";
44

55
export default function App() {
6-
const cardWidth = 200;
7-
const cardHeight = 200;
8-
9-
const cardStyles = { width: cardWidth, height: cardHeight };
10-
116
return (
127
<main className="container">
13-
<StackedCarousel autoplay={false} height={cardHeight}>
14-
<div className="sample-card bg-color-1" style={cardStyles}>
15-
0
16-
</div>
17-
<div className="sample-card bg-color-2" style={cardStyles}>
18-
1
19-
</div>
20-
<div className="sample-card bg-color-3" style={cardStyles}>
21-
2
22-
</div>
23-
<div className="sample-card bg-color-4" style={cardStyles}>
24-
3
25-
</div>
8+
<StackedCarousel autoplay={false} height={"200 md:500"}>
9+
<div className="sample-card bg-color-1">0</div>
10+
<div className="sample-card bg-color-2">1</div>
11+
<div className="sample-card bg-color-3">2</div>
12+
<div className="sample-card bg-color-4">3</div>
2613
</StackedCarousel>
2714
</main>
2815
);

playground/styles.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ body {
2424
color: #fff;
2525
font-family: sans-serif;
2626
font-size: 1.5em;
27+
height: 200px;
28+
width: 200px;
29+
}
30+
31+
@media screen and (min-width: 768px) {
32+
.sample-card {
33+
height: 500px;
34+
width: 500px;
35+
}
2736
}
2837

2938
.bg-color-1 {
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import React from "react";
22

3-
export default React.memo(function CarousalItem(props) {
3+
export default React.memo(function CarouselItem(props) {
44
const {
55
easing,
66
delay,
77
transitionDuration,
88
opacity,
99
rotateX,
1010
scale,
11+
styleOverride,
1112
tX,
1213
tY,
1314
tZ,
@@ -23,16 +24,17 @@ export default React.memo(function CarousalItem(props) {
2324
scale(${scale})
2425
`;
2526

26-
const style = {
27+
const computedStyle = {
2728
opacity,
2829
transition,
2930
transitionDelay: `${delay}s, ${delay}s`,
3031
transform,
3132
zIndex,
3233
};
34+
const mergedStyles = Object.assign({}, styleOverride, computedStyle);
3335

3436
return (
35-
<div style={style} className="rcsc-item">
37+
<div style={mergedStyles} className="rcsc-item">
3638
{children}
3739
</div>
3840
);

src/Navigation.jsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
import { ArrowLeft, ArrowRight } from "./Icons";
22

33
export default function Navigation(props) {
4-
const { className = "", onNext, onPrevious } = props;
4+
const { onNext, onPrevious, styleOverrides } = props;
55
const arrowSize = 16;
66

7-
const containerClasses = `rcsc-nav-container ${className}`;
8-
97
return (
10-
<nav className={containerClasses}>
11-
<div onClick={onPrevious} className="rcsc-nav-icon">
8+
<nav style={styleOverrides.Navigation} className="rcsc-nav-container">
9+
<div
10+
style={styleOverrides.NavIcon}
11+
onClick={onPrevious}
12+
className="rcsc-nav-icon"
13+
>
1214
<ArrowLeft color="#fff" size={arrowSize} />
1315
</div>
14-
<div onClick={onNext} className="rcsc-nav-icon">
16+
<div
17+
style={styleOverrides.NavIcon}
18+
onClick={onNext}
19+
className="rcsc-nav-icon"
20+
>
1521
<ArrowRight color="#fff" size={arrowSize} />
1622
</div>
1723
</nav>

src/StackedCarousel.jsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
import React from "react";
1+
import React, { useMemo } from "react";
22
import { useCardStackCarousel } from "./useCardStackCarousel";
3-
import CarousalItem from "./CarousalItem";
3+
import CarouselItem from "./CarouselItem";
44
import Navigation from "./Navigation";
5+
import { getRootHeight } from "./getRootHeight";
56

67
export function StackedCarousel(props) {
78
const {
89
autoplay,
910
autoplayInterval,
1011
children,
11-
containerClassName,
1212
easingFunction,
1313
height,
14-
navContainerClassName,
1514
onNext,
1615
onPrevious,
1716
scaleFactor,
1817
startIndex,
18+
styleOverrides = {},
1919
transitionDuration,
2020
verticalOffset,
2121
} = props;
@@ -38,22 +38,27 @@ export function StackedCarousel(props) {
3838
const styles = getState(index);
3939

4040
return (
41-
<CarousalItem key={index} {...styles}>
41+
<CarouselItem
42+
key={index}
43+
styleOverride={styleOverrides.CarouselItem}
44+
{...styles}
45+
>
4246
{child}
43-
</CarousalItem>
47+
</CarouselItem>
4448
);
4549
});
4650
};
4751

48-
const styles = { height };
49-
const containerClasses = `rcsc-container ${containerClassName || ""}`;
52+
const { Root } = styleOverrides;
53+
const rootHeight = useMemo(() => Number(getRootHeight(height)), [height]);
54+
const styles = Object.assign({}, Root, { height: rootHeight });
5055

5156
return (
52-
<section className={containerClasses} style={styles}>
57+
<section className="rcsc-container" style={styles}>
5358
{renderCards()}
5459

5560
<Navigation
56-
className={navContainerClassName}
61+
styleOverrides={styleOverrides}
5762
onNext={handleNext}
5863
onPrevious={handlePrevious}
5964
/>

src/getRootHeight.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const BREAKPOINTS = [
2+
{ name: "2xl", value: 1536 },
3+
{ name: "xl", value: 1280 },
4+
{ name: "lg", value: 1024 },
5+
{ name: "md", value: 768 },
6+
{ name: "sm", value: 640 },
7+
];
8+
9+
export const getRootHeight = (heightProp) => {
10+
if (!heightProp) {
11+
throw new Error("'height' prop is required");
12+
}
13+
14+
if (typeof heightProp === "number") {
15+
return heightProp;
16+
}
17+
18+
for (const breakpoint of BREAKPOINTS) {
19+
const mediaQuery = window.matchMedia(
20+
`(min-width: ${breakpoint.value}px)`
21+
);
22+
23+
if (mediaQuery.matches) {
24+
const regex = new RegExp(`${breakpoint.name}:(\\d+)`);
25+
const matches = regex.exec(heightProp);
26+
if (matches) {
27+
return matches[1];
28+
}
29+
}
30+
}
31+
32+
// fallback to default
33+
const defaultHeightMatch = heightProp.match(/^(\d+)/);
34+
if (defaultHeightMatch) {
35+
return defaultHeightMatch[1];
36+
} else {
37+
throw new Error(`Invalid height prop: ${heightProp}`);
38+
}
39+
};

types/index.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
declare module "react-card-stack-carousel" {
22
import { ReactNode } from "react";
33

4+
type StyleKeys = "Root" | "CarouselItem" | "Navigation" | "NavIcon";
5+
type StyleOverrides = Record<StyleKeys, React.CSSProperties>;
6+
47
export interface StackedCarouselProps {
5-
height: number;
8+
height: number | string;
69
children: ReactNode;
710
autoplay?: boolean;
811
autoplayInterval?: number;
@@ -13,6 +16,7 @@ declare module "react-card-stack-carousel" {
1316
onPrevious?: () => void;
1417
scaleFactor?: number;
1518
startIndex?: number;
19+
styleOverrides?: StyleOverrides;
1620
transitionDuration?: number;
1721
verticalOffset?: number;
1822
}

0 commit comments

Comments
 (0)