Skip to content

Commit

Permalink
Added FAQ heading choice behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
pookmish committed Nov 25, 2024
1 parent 1fee74d commit 6bd03e6
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 12 deletions.
27 changes: 23 additions & 4 deletions src/components/elements/accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import {HTMLAttributes, JSX, useId} from "react"
import {useBoolean} from "usehooks-ts"
import {H2, H3, H4} from "@components/elements/headers"
import {H2, H3, H4, H5} from "@components/elements/headers"
import {ChevronDownIcon} from "@heroicons/react/20/solid"
import {clsx} from "clsx"
import twMerge from "@lib/utils/twMerge"

export type AccordionHeaderChoice = "h2" | "h3" | "h4" | "h5"

type Props = HTMLAttributes<HTMLElement> & {
/**
* Button clickable element or string.
Expand All @@ -15,7 +17,7 @@ type Props = HTMLAttributes<HTMLElement> & {
/**
* Heading level element.
*/
headingLevel?: "h2" | "h3" | "h4"
headingLevel?: AccordionHeaderChoice
/**
* If the accordion should be visible on first render.
*/
Expand Down Expand Up @@ -63,7 +65,24 @@ const Accordion = ({
// When the accordion is externally controlled.
const isExpanded = onClick ? isVisible : expanded

const Heading = headingLevel === "h2" ? H2 : headingLevel === "h3" ? H3 : H4
let Heading
switch (headingLevel) {
case "h3":
Heading = H3
break

case "h4":
Heading = H4
break

case "h5":
Heading = H5
break

default:
Heading = H2
}

return (
<section aria-labelledby={`${id}-button`} {...props}>
<Heading>
Expand All @@ -86,7 +105,7 @@ const Accordion = ({
<div
{...panelProps}
id={`${id}-panel`}
className={twMerge(isExpanded ? "block" : "hidden", panelProps?.className)}
className={twMerge(isExpanded ? "mb-20 block" : "hidden", panelProps?.className)}
role="region"
aria-labelledby={`${id}-button`}
>
Expand Down
17 changes: 14 additions & 3 deletions src/components/paragraphs/stanford-faq/expand-collapse-all.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import Button from "@components/elements/button"
import {useBoolean} from "usehooks-ts"
import {HTMLAttributes, useEffect, useRef} from "react"
import {MinusIcon, PlusIcon} from "@heroicons/react/16/solid"
import twMerge from "@lib/utils/twMerge"

type Props = HTMLAttributes<HTMLButtonElement>

const ExpandCollapseAll = ({...props}: Props) => {
const {value: expand, toggle} = useBoolean(false)
const {value: expand, toggle} = useBoolean(true)
const ref = useRef<HTMLButtonElement>(null)

useEffect(() => {
Expand All @@ -24,9 +26,18 @@ const ExpandCollapseAll = ({...props}: Props) => {
}, [expand])

return (
// @ts-expect-error ref object type issue.
<Button ref={ref} buttonElem onClick={toggle} {...props}>
<Button
/* @ts-expect-error ref object type issue. */
ref={ref}
buttonElem
onClick={toggle}
secondary
{...props}
className={twMerge("flex items-center gap-5 whitespace-nowrap", props.className)}
>
{expand ? "Expand All" : "Collapse All"}
{expand && <PlusIcon width={20} />}
{!expand && <MinusIcon width={20} />}
</Button>
)
}
Expand Down
27 changes: 23 additions & 4 deletions src/components/paragraphs/stanford-faq/faq-paragraph.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,39 @@
import {HtmlHTMLAttributes} from "react"
import {ParagraphStanfordFaq} from "@lib/gql/__generated__/drupal.d"
import {H2} from "@components/elements/headers"
import {H2, H3, H4} from "@components/elements/headers"
import Wysiwyg from "@components/elements/wysiwyg"
import Accordion from "@components/elements/accordion"
import Accordion, {AccordionHeaderChoice} from "@components/elements/accordion"
import twMerge from "@lib/utils/twMerge"
import ExpandCollapseAll from "@components/paragraphs/stanford-faq/expand-collapse-all"
import {getParagraphBehaviors} from "@components/paragraphs/get-paragraph-behaviors"
import {FAQParagraphBehaviors} from "@lib/drupal/drupal-jsonapi.d"

type Props = HtmlHTMLAttributes<HTMLDivElement> & {
paragraph: ParagraphStanfordFaq
}

const FaqParagraph = ({paragraph, ...props}: Props) => {
const behaviors = getParagraphBehaviors<FAQParagraphBehaviors>(paragraph)
const headerTag = behaviors.faq_accordions?.heading || "h2"
const heading = paragraph.suFaqHeadline

let accordionHeadingLevel: AccordionHeaderChoice = "h2"
if (heading) {
if (headerTag === "h2") accordionHeadingLevel = "h3"
if (headerTag === "h3") accordionHeadingLevel = "h4"
if (headerTag === "h4") accordionHeadingLevel = "h5"
}

return (
<div {...props} className={twMerge("space-y-10", props.className)}>
<div className="flex items-center justify-between gap-20">
{paragraph.suFaqHeadline && <H2>{paragraph.suFaqHeadline}</H2>}
{heading && (
<>
{headerTag === "h2" && <H2 id={paragraph.id}>{heading}</H2>}
{headerTag === "h3" && <H3 id={paragraph.id}>{heading}</H3>}
{headerTag === "h4" && <H4 id={paragraph.id}>{heading}</H4>}
</>
)}

<ExpandCollapseAll className="ml-auto" />
</div>
Expand All @@ -27,7 +46,7 @@ const FaqParagraph = ({paragraph, ...props}: Props) => {
buttonProps={{className: "mt-6"}}
key={question.id}
button={question.suAccordionTitle}
headingLevel={paragraph.suFaqHeadline ? "h3" : "h2"}
headingLevel={accordionHeadingLevel}
>
<Wysiwyg html={question.suAccordionBody.processed} />
</Accordion>
Expand Down
12 changes: 11 additions & 1 deletion src/lib/drupal/drupal-jsonapi.d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,19 @@ export type TeaserParagraphBehaviors = {
}
}

export type FAQParagraphBehaviors = {
faq_accordions?: {heading?: "h2" | "h3" | "h4"}
}

type ParagraphBehaviorsBase = {
layout_paragraphs?: LayoutParagraphBehaviors
}

export type ParagraphBehaviors = ParagraphBehaviorsBase &
(TeaserParagraphBehaviors | BannerParagraphBehaviors | CardParagraphBehaviors | ListParagraphBehaviors)
(
| TeaserParagraphBehaviors
| BannerParagraphBehaviors
| CardParagraphBehaviors
| ListParagraphBehaviors
| FAQParagraphBehaviors
)

0 comments on commit 6bd03e6

Please sign in to comment.