From 7290e7e899dd8bc546de29ef2b2c93222f9a78c4 Mon Sep 17 00:00:00 2001 From: lightyfr <127269031+lightyfr@users.noreply.github.com> Date: Tue, 1 Apr 2025 05:25:54 -0400 Subject: [PATCH] feat: add SlideAccordion component with expand/collapse functionality --- .../components/SlideAccordion.module.scss | 9 ++ src/once-ui/components/SlideAccordion.tsx | 151 ++++++++++++++++++ src/once-ui/components/index.ts | 1 + 3 files changed, 161 insertions(+) create mode 100644 src/once-ui/components/SlideAccordion.module.scss create mode 100644 src/once-ui/components/SlideAccordion.tsx diff --git a/src/once-ui/components/SlideAccordion.module.scss b/src/once-ui/components/SlideAccordion.module.scss new file mode 100644 index 00000000..edcb36a1 --- /dev/null +++ b/src/once-ui/components/SlideAccordion.module.scss @@ -0,0 +1,9 @@ +/* SlideAccordion.module.scss */ +.expandTransition { + transition: width 550ms cubic-bezier(0.33, 1, 0.68, 1), + opacity 350ms ease-in-out; + will-change: width, opacity; + transform: translateZ(0); + backface-visibility: hidden; + perspective: 1000; +} diff --git a/src/once-ui/components/SlideAccordion.tsx b/src/once-ui/components/SlideAccordion.tsx new file mode 100644 index 00000000..854c26a5 --- /dev/null +++ b/src/once-ui/components/SlideAccordion.tsx @@ -0,0 +1,151 @@ +"use client"; + +import React, { useState } from "react"; +import { Flex, Text, Column, Icon, Background, Button } from "."; +import styles from "./SlideAccordion.module.scss"; +import { FlexProps } from '../interfaces'; + +export interface SlideAccordionItem { + title: string; + content: React.ReactNode; + buttonTitle: string; + icon: string; + background?: React.ComponentProps; +} + +interface SlideAccordionProps extends React.ComponentProps { + items: SlideAccordionItem[]; + size?: "s" | "m" | "l"; +} + +const SlideAccordion: React.FC = ({ items, size = "m", ...rest }) => { + const [hoveredIndex, setHoveredIndex] = useState(null); + + const collapsedWidth = size === "s" ? 5 : size === "m" ? 7 : 10; + + const expandedWidth = 20; + const iconSize = size === "s" ? "xs" : size === "m" ? "s" : "m"; + + return ( + + {items.map((item, index) => { + const isExpanded = hoveredIndex === index; + + return ( + setHoveredIndex(index)} + onMouseLeave={() => setHoveredIndex(null)} + overflow="hidden" + position="relative" + style={{ + transitionDelay: isExpanded ? '0ms' : '75ms' + }} + > + {/* Background component when specified */} + {item.background && ( + + )} + + {/* Collapsed view with vertical text and icon at bottom */} + + + {item.title} + + + + + + {/* Expanded view with full content */} + + + + {item.title} + + + + + + + {item.content} + + + + + + ); + })} + + ); +}; + +SlideAccordion.displayName = "SlideAccordion"; +export { SlideAccordion }; \ No newline at end of file diff --git a/src/once-ui/components/index.ts b/src/once-ui/components/index.ts index 66bdab42..9f7fa82b 100644 --- a/src/once-ui/components/index.ts +++ b/src/once-ui/components/index.ts @@ -55,6 +55,7 @@ export * from "./Select"; export * from "./Skeleton"; export * from "./SmartImage"; export * from "./SmartLink"; +export * from "./SlideAccordion"; export * from "./Spinner"; export * from "./StatusIndicator"; export * from "./StylePanel";