From e272b1602c5ee82ebc5d9edc9e7ebc1a3bf73efd Mon Sep 17 00:00:00 2001 From: Erik Tiekstra Date: Wed, 3 Jul 2024 11:25:24 +0200 Subject: [PATCH] feat: added accordion component --- .../AccordionItem/accordionItem.module.css | 54 +++++++++++++++++++ .../Accordion/AccordionItem/accordionItem.ts | 9 ++++ .../Accordion/AccordionItem/index.tsx | 53 ++++++++++++++++++ .../Accordion/AccordionItem/variants.ts | 15 ++++++ .../Accordion/accordion.module.css | 11 ++++ .../TempDesignSystem/Accordion/accordion.ts | 7 +++ .../TempDesignSystem/Accordion/index.tsx | 22 ++++++++ .../TempDesignSystem/Accordion/variants.ts | 15 ++++++ 8 files changed, 186 insertions(+) create mode 100644 components/TempDesignSystem/Accordion/AccordionItem/accordionItem.module.css create mode 100644 components/TempDesignSystem/Accordion/AccordionItem/accordionItem.ts create mode 100644 components/TempDesignSystem/Accordion/AccordionItem/index.tsx create mode 100644 components/TempDesignSystem/Accordion/AccordionItem/variants.ts create mode 100644 components/TempDesignSystem/Accordion/accordion.module.css create mode 100644 components/TempDesignSystem/Accordion/accordion.ts create mode 100644 components/TempDesignSystem/Accordion/index.tsx create mode 100644 components/TempDesignSystem/Accordion/variants.ts diff --git a/components/TempDesignSystem/Accordion/AccordionItem/accordionItem.module.css b/components/TempDesignSystem/Accordion/AccordionItem/accordionItem.module.css new file mode 100644 index 000000000..08183a5fb --- /dev/null +++ b/components/TempDesignSystem/Accordion/AccordionItem/accordionItem.module.css @@ -0,0 +1,54 @@ +.accordionItem { + border-bottom: 1px solid var(--Base-Border-Subtle); +} + +.card { + padding: var(--Spacing-x1); +} + +.card .summary { + padding: var(--Spacing-x1) var(--Spacing-x-one-and-half); + border-radius: var(--Corner-radius-Medium); +} + +.faq .summary { + padding: var(--Spacing-x2) 0; +} + +.faq .content { + padding: 0; +} + +.summary { + position: relative; + display: flex; + justify-content: space-between; + align-items: center; + gap: var(--Spacing-x2); + cursor: pointer; + color: var(--Base-Text-High-contrast); + font-family: var(--typography-Body-Bold-fontFamily); + font-size: var(--typography-Body-Bold-fontSize); + font-weight: var(--typography-Body-Bold-fontWeight); + transition: background-color 0.3s; +} + +.summary:hover, +.summary:focus { + background-color: var(--Base-Surface-Primary-light-Hover); +} + +.content { + padding: 0 var(--Spacing-x-one-and-half); + overflow: hidden; + max-height: 0; + transition: max-height 0.3s; +} + +.chevron { + transition: transform 0.3s; +} + +details[open] .chevron { + transform: rotate(180deg); +} diff --git a/components/TempDesignSystem/Accordion/AccordionItem/accordionItem.ts b/components/TempDesignSystem/Accordion/AccordionItem/accordionItem.ts new file mode 100644 index 000000000..10f7a9a76 --- /dev/null +++ b/components/TempDesignSystem/Accordion/AccordionItem/accordionItem.ts @@ -0,0 +1,9 @@ +import { VariantProps } from "class-variance-authority" + +import { accordionItemVariants } from "./variants" + +export interface AccordionItemProps + extends React.HtmlHTMLAttributes, + VariantProps { + title: string +} diff --git a/components/TempDesignSystem/Accordion/AccordionItem/index.tsx b/components/TempDesignSystem/Accordion/AccordionItem/index.tsx new file mode 100644 index 000000000..16a1b276b --- /dev/null +++ b/components/TempDesignSystem/Accordion/AccordionItem/index.tsx @@ -0,0 +1,53 @@ +"use client" + +import { useRef } from "react" + +import { ChevronDownIcon } from "@/components/Icons" + +import { AccordionItemProps } from "./accordionItem" +import { accordionItemVariants } from "./variants" + +import styles from "./accordionItem.module.css" + +export default function AccordionItem({ + children, + title, + variant, +}: AccordionItemProps) { + const contentRef = useRef(null) + const detailsRef = useRef(null) + + function toggleAccordion() { + const details = detailsRef.current + const content = contentRef.current + if (details && content) { + if (details.open) { + content.style.maxHeight = `${content.scrollHeight}px` + content.addEventListener( + "transitionend", + () => { + // Remove maxHeight after transition to allow content to transition multiple times + content.style.maxHeight = "none" + }, + { once: true } + ) + } else { + content.style.maxHeight = "0" + } + } + } + + return ( +
  • +
    + + {title} + + +
    + {children} +
    +
    +
  • + ) +} diff --git a/components/TempDesignSystem/Accordion/AccordionItem/variants.ts b/components/TempDesignSystem/Accordion/AccordionItem/variants.ts new file mode 100644 index 000000000..819797a2b --- /dev/null +++ b/components/TempDesignSystem/Accordion/AccordionItem/variants.ts @@ -0,0 +1,15 @@ +import { cva } from "class-variance-authority" + +import styles from "./accordionItem.module.css" + +export const accordionItemVariants = cva(styles.accordionItem, { + variants: { + variant: { + card: styles.card, + faq: styles.faq, + }, + }, + defaultVariants: { + variant: "card", + }, +}) diff --git a/components/TempDesignSystem/Accordion/accordion.module.css b/components/TempDesignSystem/Accordion/accordion.module.css new file mode 100644 index 000000000..42d1be85f --- /dev/null +++ b/components/TempDesignSystem/Accordion/accordion.module.css @@ -0,0 +1,11 @@ +.accordion { + list-style: none; +} + +.card { + border-radius: var(--Corner-radius-Medium); + background-color: var(--Base-Surface-Primary-light-Normal); +} +.faq { + background-color: var(--Base-Background-Primary-Normal); +} diff --git a/components/TempDesignSystem/Accordion/accordion.ts b/components/TempDesignSystem/Accordion/accordion.ts new file mode 100644 index 000000000..fa0ade85c --- /dev/null +++ b/components/TempDesignSystem/Accordion/accordion.ts @@ -0,0 +1,7 @@ +import { VariantProps } from "class-variance-authority" + +import { accordionVariants } from "./variants" + +export interface AccordionProps + extends React.HtmlHTMLAttributes, + VariantProps {} diff --git a/components/TempDesignSystem/Accordion/index.tsx b/components/TempDesignSystem/Accordion/index.tsx new file mode 100644 index 000000000..79d4c83bf --- /dev/null +++ b/components/TempDesignSystem/Accordion/index.tsx @@ -0,0 +1,22 @@ +import { Children, cloneElement, isValidElement } from "react" + +import { AccordionItemProps } from "./AccordionItem/accordionItem" +import { AccordionProps } from "./accordion" +import { accordionVariants } from "./variants" + +export default function Accordion({ + children, + className, + variant, +}: AccordionProps) { + return ( +
      + {Children.map(children, (child) => { + if (isValidElement(child)) { + return cloneElement(child, { variant }) + } + })} + {/* {children} */} +
    + ) +} diff --git a/components/TempDesignSystem/Accordion/variants.ts b/components/TempDesignSystem/Accordion/variants.ts new file mode 100644 index 000000000..354c03fba --- /dev/null +++ b/components/TempDesignSystem/Accordion/variants.ts @@ -0,0 +1,15 @@ +import { cva } from "class-variance-authority" + +import styles from "./accordion.module.css" + +export const accordionVariants = cva(styles.accordion, { + variants: { + variant: { + card: styles.card, + faq: styles.faq, + }, + }, + defaultVariants: { + variant: "card", + }, +})