@@ -24,16 +25,18 @@ export default {
argTypes: {
children: {
description: "The elements to be displayed.",
+ control: { type: "range", min: 1, max: 10, step: 1 },
},
variant: {
description: "Variant for the carousel.",
options: ["default", "content-card"],
defaultValue: "default",
- control: { type: "select" },
+ control: "inline-radio",
},
},
args: {
variant: "default",
+ children: 5,
},
parameters: {
docs: {
@@ -42,6 +45,7 @@ export default {
},
},
},
-};
+ render: CarouselStory,
+} satisfies Meta;
-export const Default = CarouselStory.bind({});
+export const Default: StoryObj = {};
diff --git a/libs/ui/packages/react/src/components/layout/Carousel/ChevronArrow.tsx b/libs/ui/packages/react/src/components/layout/Carousel/ChevronArrow.tsx
new file mode 100644
index 000000000000..ed2f51322e54
--- /dev/null
+++ b/libs/ui/packages/react/src/components/layout/Carousel/ChevronArrow.tsx
@@ -0,0 +1,70 @@
+import React from "react";
+import styled from "styled-components";
+import { Icons } from "../../../assets";
+
+type Props = ContainerProps & {
+ onClick: () => void;
+};
+
+export function ChevronArrow(props: Props) {
+ return (
+
+
+
+ );
+}
+
+type ContainerProps = {
+ direction: "left" | "right";
+};
+
+const ChevronArrowContainer = styled.button
`
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ width: 32px;
+ height: 32px;
+
+ position: absolute;
+ top: 50%;
+ left: ${({ direction }) => (direction === "left" ? "0" : "auto")};
+ right: ${({ direction }) => (direction === "left" ? "auto" : "0")};
+ z-index: 1;
+
+ --dir: ${({ direction }) => (direction === "left" ? "1" : "-1")};
+ scale: var(--dir) 1;
+ translate: calc(-50% * var(--dir)) -50%;
+
+ background-color: ${({ theme }) => theme.colors.background.default}; // Fake the transparent clip
+ border-radius: 100%;
+ border: none;
+ outline: none;
+
+ ::before {
+ content: "";
+ display: block;
+ position: absolute;
+ z-index: -1;
+ inset: 3px;
+ background-color: ${({ theme }) => theme.colors.opacityDefault.c05};
+ border-color: ${({ theme }) => theme.colors.opacityDefault.c05};
+ border-radius: 100%;
+ border-style: solid;
+ border-width: 1px;
+ }
+ svg {
+ color: ${({ theme }) => theme.colors.primary.c100};
+ }
+ ::before,
+ svg {
+ cursor: pointer;
+ }
+
+ transition: opacity 0.2s ease-in-out;
+ opacity: var(--hover-transition);
+ ::before,
+ svg {
+ transition: translate 0.2s ease-in-out;
+ translate: calc(-50% + 50% * var(--hover-transition)) 0;
+ }
+`;
diff --git a/libs/ui/packages/react/src/components/layout/Carousel/Footer/Pagination/index.tsx b/libs/ui/packages/react/src/components/layout/Carousel/Footer/Pagination/index.tsx
index db5019e6bab8..62f40352ac8b 100644
--- a/libs/ui/packages/react/src/components/layout/Carousel/Footer/Pagination/index.tsx
+++ b/libs/ui/packages/react/src/components/layout/Carousel/Footer/Pagination/index.tsx
@@ -13,7 +13,7 @@ const Pagination = ({ children, currentIndex }: SubProps) => {
return (
{children.map((child, index) => (
-
+
))}
);
diff --git a/libs/ui/packages/react/src/components/layout/Carousel/Footer/Pagination/utils.ts b/libs/ui/packages/react/src/components/layout/Carousel/Footer/Pagination/utils.ts
index 1920f750ffc3..763a629a47c3 100644
--- a/libs/ui/packages/react/src/components/layout/Carousel/Footer/Pagination/utils.ts
+++ b/libs/ui/packages/react/src/components/layout/Carousel/Footer/Pagination/utils.ts
@@ -3,17 +3,17 @@ import { ItemStatus } from "./types";
/**
* Returns the status of an indexed item from the carousel index.
*/
-export const getItemStatus = (itemIndex: number, activeIndex: number) => {
- const itemDistanceFromActiveIndex = Math.abs(itemIndex - activeIndex);
+export const getItemStatus = (itemIndex: number, activeIndex: number, itemCount: number) => {
+ const isActive = itemIndex === activeIndex;
+ if (isActive) {
+ return ItemStatus.active;
+ }
- switch (itemDistanceFromActiveIndex) {
- case 0:
- return ItemStatus.active;
- case 1:
- return ItemStatus.nearby;
- case 2:
- return ItemStatus.far;
- default:
- return ItemStatus.none;
+ const isAdjacent = Math.abs(itemIndex - activeIndex) === 1;
+ if (isAdjacent) {
+ return ItemStatus.nearby;
}
+
+ const isEdge = itemIndex === 0 || itemIndex === itemCount - 1;
+ return isEdge ? ItemStatus.far : ItemStatus.nearby;
};
diff --git a/libs/ui/packages/react/src/components/layout/Carousel/Footer/index.tsx b/libs/ui/packages/react/src/components/layout/Carousel/Footer/index.tsx
index fa04654914a4..f9c809076a7d 100644
--- a/libs/ui/packages/react/src/components/layout/Carousel/Footer/index.tsx
+++ b/libs/ui/packages/react/src/components/layout/Carousel/Footer/index.tsx
@@ -9,6 +9,8 @@ const Footers: { [key in Variant]: FC } = {
};
const Footer = (props: SubProps) => {
+ if (props.children.length === 1) return null;
+
const Component = Footers[props.variant];
return ;
};
diff --git a/libs/ui/packages/react/src/components/layout/Carousel/Footer/variantContentCard.tsx b/libs/ui/packages/react/src/components/layout/Carousel/Footer/variantContentCard.tsx
index 879384a7e1ca..a809b5c1674b 100644
--- a/libs/ui/packages/react/src/components/layout/Carousel/Footer/variantContentCard.tsx
+++ b/libs/ui/packages/react/src/components/layout/Carousel/Footer/variantContentCard.tsx
@@ -25,8 +25,6 @@ const FooterArrowContainer = styled.div`
`;
const FooterContentCard = ({ children, emblaApi, currentIndex, variant }: SubProps) => {
- if (children.length === 1) return null;
-
return (
>`
+ position: relative;
+
+ --hover-transition: 0;
+ &:hover {
+ --hover-transition: 1;
+ }
+`;
+
/**
* This component uses the https://github.com/davidjerleke/embla-carousel library.
*/
@@ -45,15 +55,27 @@ const Carousel = ({ children, variant = "default" }: Props) => {
emblaApi.on("reInit", updateIndex);
}, [emblaApi, updateIndex]);
+ const handleGotoPrevSlide = () => emblaApi?.scrollPrev();
+ const handleGotoNextSlide = () => emblaApi?.scrollNext();
+
return (
-
-
- {children.map(child => (
- {child}
- ))}
-
-
+
+ {variant === "default" && children.length > 1 && (
+ <>
+
+
+ >
+ )}
+
+
+
+ {children.map(child => (
+ {child}
+ ))}
+
+
+
);
};
+
export default Carousel;
diff --git a/libs/ui/packages/shared/palettes/dark.ts b/libs/ui/packages/shared/palettes/dark.ts
index 4d798a8fdc72..8977e93cd00d 100644
--- a/libs/ui/packages/shared/palettes/dark.ts
+++ b/libs/ui/packages/shared/palettes/dark.ts
@@ -107,8 +107,10 @@ export default {
black: "#000000",
},
background: {
+ default: "#131214",
main: "#131214",
drawer: "#1D1C1F",
+ card: "#1C1D1F",
},
effects: {
dropShadow: "rgba(0, 0, 0, 0.48)",
diff --git a/libs/ui/packages/shared/palettes/light.ts b/libs/ui/packages/shared/palettes/light.ts
index 81a7e796c331..6c78cdad9397 100644
--- a/libs/ui/packages/shared/palettes/light.ts
+++ b/libs/ui/packages/shared/palettes/light.ts
@@ -107,8 +107,10 @@ export default {
black: "#000000",
},
background: {
+ default: "#F9F9F9",
main: "#FFFFFF",
drawer: "#FFFFFF",
+ card: "#FFFFFF",
},
effects: {
dropShadow: "rgba(0, 0, 0, 0.16)",