fix: toggle section accordion open
This commit is contained in:
@@ -1,176 +0,0 @@
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
import { getProfileSafely } from "@/lib/trpc/memoizedRequests"
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
|
||||
import BedType from "@/components/HotelReservation/EnterDetails/BedType"
|
||||
import Breakfast from "@/components/HotelReservation/EnterDetails/Breakfast"
|
||||
import Details from "@/components/HotelReservation/EnterDetails/Details"
|
||||
import HotelSelectionHeader from "@/components/HotelReservation/HotelSelectionHeader"
|
||||
import Payment from "@/components/HotelReservation/SelectRate/Payment"
|
||||
import SectionAccordion from "@/components/HotelReservation/SelectRate/SectionAccordion"
|
||||
import Summary from "@/components/HotelReservation/SelectRate/Summary"
|
||||
import { getIntl } from "@/i18n"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import { SectionPageProps } from "@/types/components/hotelReservation/selectRate/section"
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
const bedAlternatives = [
|
||||
{
|
||||
value: "queen",
|
||||
name: "Queen bed",
|
||||
payment: "160 cm",
|
||||
pricePerNight: 0,
|
||||
membersPricePerNight: 0,
|
||||
currency: "SEK",
|
||||
},
|
||||
{
|
||||
value: "king",
|
||||
name: "King bed",
|
||||
payment: "160 cm",
|
||||
pricePerNight: 0,
|
||||
membersPricePerNight: 0,
|
||||
currency: "SEK",
|
||||
},
|
||||
{
|
||||
value: "twin",
|
||||
name: "Twin bed",
|
||||
payment: "90 cm + 90 cm",
|
||||
pricePerNight: 82,
|
||||
membersPricePerNight: 67,
|
||||
currency: "SEK",
|
||||
},
|
||||
]
|
||||
|
||||
const breakfastAlternatives = [
|
||||
{
|
||||
value: "no",
|
||||
name: "No breakfast",
|
||||
payment: "Always cheeper to get it online",
|
||||
pricePerNight: 0,
|
||||
currency: "SEK",
|
||||
},
|
||||
{
|
||||
value: "buffe",
|
||||
name: "Breakfast buffé",
|
||||
payment: "Always cheeper to get it online",
|
||||
pricePerNight: 150,
|
||||
currency: "SEK",
|
||||
},
|
||||
]
|
||||
|
||||
const getFlexibilityMessage = (value: string) => {
|
||||
switch (value) {
|
||||
case "non-refundable":
|
||||
return "Non refundable"
|
||||
case "free-rebooking":
|
||||
return "Free rebooking"
|
||||
case "free-cancellation":
|
||||
return "Free cancellation"
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
export default async function SectionsPage({
|
||||
params,
|
||||
searchParams,
|
||||
}: PageArgs<LangParams & { section: string }, SectionPageProps>) {
|
||||
setLang(params.lang)
|
||||
const profile = await getProfileSafely()
|
||||
|
||||
const hotel = await serverClient().hotel.hotelData.get({
|
||||
hotelId: "811",
|
||||
language: params.lang,
|
||||
})
|
||||
|
||||
if (!hotel) {
|
||||
// TODO: handle case with hotel missing
|
||||
return notFound()
|
||||
}
|
||||
|
||||
const rooms = await serverClient().hotel.rates.get({
|
||||
// TODO: pass the correct hotel ID and all other parameters that should be included in the search
|
||||
hotelId: hotel.data.id,
|
||||
})
|
||||
const intl = await getIntl()
|
||||
|
||||
const selectedBed = searchParams.bed
|
||||
? bedAlternatives.find((a) => a.value === searchParams.bed)?.name
|
||||
: undefined
|
||||
|
||||
const selectedBreakfast = searchParams.breakfast
|
||||
? breakfastAlternatives.find((a) => a.value === searchParams.breakfast)
|
||||
?.name
|
||||
: undefined
|
||||
|
||||
const selectedRoom = searchParams.roomClass
|
||||
? rooms.find((room) => room.id.toString() === searchParams.roomClass)?.name
|
||||
: undefined
|
||||
const selectedFlexibility = searchParams.flexibility
|
||||
? getFlexibilityMessage(searchParams.flexibility)
|
||||
: undefined
|
||||
|
||||
const currentSearchParams = new URLSearchParams(searchParams).toString()
|
||||
|
||||
let user = null
|
||||
if (profile && !("error" in profile)) {
|
||||
user = profile
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<HotelSelectionHeader hotel={hotel.data.attributes} />
|
||||
|
||||
<div className={styles.content}>
|
||||
<div className={styles.main}>
|
||||
<SectionAccordion
|
||||
header={intl.formatMessage({ id: "Room & Terms" })}
|
||||
selection={
|
||||
selectedRoom
|
||||
? [
|
||||
selectedRoom,
|
||||
intl.formatMessage({ id: selectedFlexibility }),
|
||||
]
|
||||
: undefined
|
||||
}
|
||||
path={`select-rate?${currentSearchParams}`}
|
||||
></SectionAccordion>
|
||||
<SectionAccordion
|
||||
header={intl.formatMessage({ id: "Bed type" })}
|
||||
selection={selectedBed}
|
||||
path={`select-bed?${currentSearchParams}`}
|
||||
>
|
||||
{params.section === "select-bed" ? <BedType /> : null}
|
||||
</SectionAccordion>
|
||||
<SectionAccordion
|
||||
header={intl.formatMessage({ id: "Breakfast" })}
|
||||
selection={selectedBreakfast}
|
||||
path={`breakfast?${currentSearchParams}`}
|
||||
>
|
||||
{params.section === "breakfast" ? <Breakfast /> : null}
|
||||
</SectionAccordion>
|
||||
<SectionAccordion
|
||||
header={intl.formatMessage({ id: "Your details" })}
|
||||
path={`details?${currentSearchParams}`}
|
||||
>
|
||||
{params.section === "details" ? <Details user={user} /> : null}
|
||||
</SectionAccordion>
|
||||
<SectionAccordion
|
||||
header={intl.formatMessage({ id: "Payment info" })}
|
||||
path={`payment?${currentSearchParams}`}
|
||||
>
|
||||
{params.section === "payment" && (
|
||||
<Payment hotel={hotel.data.attributes} />
|
||||
)}
|
||||
</SectionAccordion>
|
||||
</div>
|
||||
<div className={styles.summary}>
|
||||
<Summary />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -16,10 +16,15 @@
|
||||
gap: var(--Spacing-x7);
|
||||
}
|
||||
|
||||
.main {
|
||||
.section {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.summary {
|
||||
max-width: 340px;
|
||||
}
|
||||
|
||||
.form {
|
||||
display: grid;
|
||||
gap: var(--Spacing-x2);
|
||||
}
|
||||
|
||||
@@ -1,58 +1,18 @@
|
||||
"use client"
|
||||
|
||||
import { notFound } from "next/navigation"
|
||||
import { useState } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { notFound } from "@/server/errors/next"
|
||||
|
||||
import SectionAccordion from "@/components/HotelReservation/SelectRate/SectionAccordion"
|
||||
import Summary from "@/components/HotelReservation/SelectRate/Summary"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
// const bedAlternatives = [
|
||||
// {
|
||||
// value: "queen",
|
||||
// name: "Queen bed",
|
||||
// payment: "160 cm",
|
||||
// pricePerNight: 0,
|
||||
// membersPricePerNight: 0,
|
||||
// currency: "SEK",
|
||||
// },
|
||||
// {
|
||||
// value: "king",
|
||||
// name: "King bed",
|
||||
// payment: "160 cm",
|
||||
// pricePerNight: 0,
|
||||
// membersPricePerNight: 0,
|
||||
// currency: "SEK",
|
||||
// },
|
||||
// {
|
||||
// value: "twin",
|
||||
// name: "Twin bed",
|
||||
// payment: "90 cm + 90 cm",
|
||||
// pricePerNight: 82,
|
||||
// membersPricePerNight: 67,
|
||||
// currency: "SEK",
|
||||
// },
|
||||
// ]
|
||||
|
||||
// const breakfastAlternatives = [
|
||||
// {
|
||||
// value: "no",
|
||||
// name: "No breakfast",
|
||||
// payment: "Always cheeper to get it online",
|
||||
// pricePerNight: 0,
|
||||
// currency: "SEK",
|
||||
// },
|
||||
// {
|
||||
// value: "buffe",
|
||||
// name: "Breakfast buffé",
|
||||
// payment: "Always cheeper to get it online",
|
||||
// pricePerNight: 150,
|
||||
// currency: "SEK",
|
||||
// },
|
||||
// ]
|
||||
|
||||
enum StepEnum {
|
||||
"select-bed" = "select-bed",
|
||||
breakfast = "breakfast",
|
||||
@@ -68,22 +28,100 @@ function isValidStep(step: string): step is Step {
|
||||
|
||||
export default function StepPage({
|
||||
params,
|
||||
}: PageArgs<LangParams & { step: string }>) {
|
||||
const { step } = params
|
||||
}: PageArgs<LangParams & { step: Step }>) {
|
||||
const [activeStep, setActiveStep] = useState<Step>(params.step)
|
||||
const intl = useIntl()
|
||||
|
||||
if (isValidStep(step)) {
|
||||
if (!isValidStep(activeStep)) {
|
||||
return notFound()
|
||||
}
|
||||
|
||||
switch (step) {
|
||||
switch (activeStep) {
|
||||
case StepEnum.breakfast:
|
||||
return <div>Select BREAKFAST</div>
|
||||
//return <div>Select BREAKFAST</div>
|
||||
case StepEnum.details:
|
||||
return <div>Select DETAILS</div>
|
||||
//return <div>Select DETAILS</div>
|
||||
case StepEnum.payment:
|
||||
return <div>Select PAYMENT</div>
|
||||
//return <div>Select PAYMENT</div>
|
||||
case StepEnum["select-bed"]:
|
||||
return <div>Select BED</div>
|
||||
// return <div>Select BED</div>
|
||||
}
|
||||
|
||||
function onNav(step: Step) {
|
||||
setActiveStep(step)
|
||||
if (typeof window !== "undefined") {
|
||||
window.history.pushState({}, "", step)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<main className={styles.page}>
|
||||
<div className={styles.content}>
|
||||
<section className={styles.section}>
|
||||
<SectionAccordion
|
||||
header="Select bed"
|
||||
isCompleted={true}
|
||||
isOpen={activeStep === StepEnum["select-bed"]}
|
||||
label={intl.formatMessage({ id: "Request bedtype" })}
|
||||
path="/select-bed"
|
||||
>
|
||||
<div className={styles.form}>
|
||||
Hejhej lorem ipsim heheheheh andi fpok veoi cdfionaw aoiwube
|
||||
cskdfaen
|
||||
<Button onClick={() => onNav("breakfast")}>
|
||||
Go to breakfast!
|
||||
</Button>
|
||||
</div>
|
||||
</SectionAccordion>
|
||||
<SectionAccordion
|
||||
header="Food options"
|
||||
isCompleted={true}
|
||||
isOpen={activeStep === StepEnum.breakfast}
|
||||
label={intl.formatMessage({ id: "Select breakfast options" })}
|
||||
path="/breakfast"
|
||||
>
|
||||
<div className={styles.form}>
|
||||
Hejhej lorem ipsim heheheheh andi fpok veoi cdfionaw aoiwube
|
||||
cskdfaen
|
||||
<Button onClick={() => onNav("details")}>Go to details!</Button>
|
||||
</div>
|
||||
</SectionAccordion>
|
||||
<SectionAccordion
|
||||
header="Details"
|
||||
isCompleted={false}
|
||||
isOpen={activeStep === StepEnum.details}
|
||||
label={intl.formatMessage({ id: "Enter your details" })}
|
||||
path="/details"
|
||||
>
|
||||
<div className={styles.form}>
|
||||
Hejhej lorem ipsim heheheheh andi fpok veoi cdfionaw aoiwube
|
||||
cskdfaen
|
||||
<Button onClick={() => onNav("payment")}>Go to payment!</Button>
|
||||
</div>
|
||||
</SectionAccordion>
|
||||
<SectionAccordion
|
||||
header="Payment"
|
||||
isCompleted={false}
|
||||
isOpen={activeStep === StepEnum.payment}
|
||||
label={intl.formatMessage({ id: "Select payment method" })}
|
||||
path="/hotelreservation/select-bed"
|
||||
>
|
||||
<div className={styles.form}>
|
||||
Hejhej lorem ipsim heheheheh andi fpok veoi cdfionaw aoiwube
|
||||
cskdfaen Hejhej lorem ipsim heheheheh andi fpok veoi cdfionaw
|
||||
aoiwube cskdfaen Hejhej lorem ipsim heheheheh andi fpok veoi
|
||||
cdfionaw aoiwube cskdfaen Hejhej lorem ipsim heheheheh andi fpok
|
||||
veoi cdfionaw aoiwube cskdfaen v Hejhej lorem ipsim heheheheh andi
|
||||
fpok veoi cdfionaw aoiwube cskdfaen Hejhej lorem ipsim heheheheh
|
||||
andi fpok veoi cdfionaw aoiwube cskdfaen
|
||||
<Button onClick={() => onNav("select-bed")}>Go to beds!</Button>
|
||||
</div>
|
||||
</SectionAccordion>
|
||||
</section>
|
||||
<aside className={styles.summary}>
|
||||
<Summary />
|
||||
</aside>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
.layout {
|
||||
min-height: 100dvh;
|
||||
background-color: var(--Base-Background-Primary-Normal);
|
||||
}
|
||||
|
||||
@@ -1,57 +1,91 @@
|
||||
import { getHotelDataSchema } from "@/server/routers/hotels/output"
|
||||
import tempHotelData from "@/server/routers/hotels/tempHotelData.json"
|
||||
"use client"
|
||||
import { useEffect, useRef } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { CheckCircleIcon, ChevronDownIcon } from "@/components/Icons"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import { CheckIcon, ChevronDownIcon } from "@/components/Icons"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import HotelSelectionHeader from "../../HotelSelectionHeader"
|
||||
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
|
||||
import styles from "./sectionAccordion.module.css"
|
||||
|
||||
import { SectionAccordionProps } from "@/types/components/hotelReservation/selectRate/sectionAccordion"
|
||||
|
||||
export default async function SectionAccordion({
|
||||
export default function SectionAccordion({
|
||||
header,
|
||||
selection,
|
||||
isOpen,
|
||||
isCompleted,
|
||||
label,
|
||||
path,
|
||||
children,
|
||||
}: React.PropsWithChildren<SectionAccordionProps>) {
|
||||
const hotel = getHotelDataSchema.parse(tempHotelData)
|
||||
const intl = useIntl()
|
||||
|
||||
const intl = await getIntl()
|
||||
const contentRef = useRef<HTMLDivElement>(null)
|
||||
const circleRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const content = contentRef.current
|
||||
const circle = circleRef.current
|
||||
if (content) {
|
||||
if (isOpen) {
|
||||
content.style.maxHeight = `${content.scrollHeight}px`
|
||||
} else {
|
||||
content.style.maxHeight = "0"
|
||||
}
|
||||
}
|
||||
|
||||
if (circle) {
|
||||
if (isOpen) {
|
||||
circle.style.backgroundColor = `var(--UI-Text-Placeholder);`
|
||||
} else {
|
||||
circle.style.backgroundColor = `var(--Base-Surface-Subtle-Hover);`
|
||||
}
|
||||
}
|
||||
}, [isOpen])
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<HotelSelectionHeader hotel={hotel.data.attributes} />
|
||||
|
||||
<div className={styles.top}>
|
||||
<div>
|
||||
<CheckCircleIcon color={selection ? "green" : "pale"} />
|
||||
</div>
|
||||
<div className={styles.header}>
|
||||
<Caption color={"burgundy"} asChild>
|
||||
<h2>{header}</h2>
|
||||
</Caption>
|
||||
{(Array.isArray(selection) ? selection : [selection]).map((s) => (
|
||||
<Body key={s} className={styles.selection} color={"burgundy"}>
|
||||
{s}
|
||||
</Body>
|
||||
))}
|
||||
</div>
|
||||
{selection && (
|
||||
<Button intent="secondary" size="small" asChild>
|
||||
<Link href={path}>{intl.formatMessage({ id: "Modify" })}</Link>
|
||||
</Button>
|
||||
)}
|
||||
<div>
|
||||
<ChevronDownIcon />
|
||||
<section className={styles.wrapper} data-open={isOpen}>
|
||||
<div className={styles.iconWrapper}>
|
||||
<div
|
||||
className={styles.circle}
|
||||
data-checked={isCompleted}
|
||||
ref={circleRef}
|
||||
>
|
||||
{isCompleted ? (
|
||||
<CheckIcon color="white" height="16" width="16" />
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
<main className={styles.main}>
|
||||
<header className={styles.headerContainer}>
|
||||
<div>
|
||||
<Footnote
|
||||
asChild
|
||||
textTransform="uppercase"
|
||||
color="uiTextPlaceholder"
|
||||
>
|
||||
<h2>{header}</h2>
|
||||
</Footnote>
|
||||
<Subtitle
|
||||
type="two"
|
||||
className={styles.selection}
|
||||
color="highContrast"
|
||||
>
|
||||
{label}
|
||||
</Subtitle>
|
||||
</div>
|
||||
{isCompleted && !isOpen && (
|
||||
<Link href={path} color="burgundy" variant="icon">
|
||||
{intl.formatMessage({ id: "Modify" })}{" "}
|
||||
<ChevronDownIcon color="burgundy" />
|
||||
</Link>
|
||||
)}
|
||||
</header>
|
||||
<div className={styles.content} ref={contentRef}>
|
||||
{children}
|
||||
</div>
|
||||
</main>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,21 +1,73 @@
|
||||
.wrapper {
|
||||
border-bottom: 1px solid var(--Base-Border-Normal);
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: var(--Spacing-x3);
|
||||
|
||||
padding-top: var(--Spacing-x3);
|
||||
}
|
||||
|
||||
.top {
|
||||
.wrapper:not(:last-child)::after {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
bottom: 0;
|
||||
top: var(--Spacing-x5);
|
||||
height: 100%;
|
||||
content: "";
|
||||
border-left: 1px solid var(--Primary-Light-On-Surface-Divider-subtle);
|
||||
}
|
||||
|
||||
.main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x3);
|
||||
width: 100%;
|
||||
border-bottom: 1px solid var(--Primary-Light-On-Surface-Divider-subtle);
|
||||
padding-bottom: var(--Spacing-x3);
|
||||
padding-top: var(--Spacing-x3);
|
||||
}
|
||||
|
||||
.headerContainer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: var(--Spacing-x2);
|
||||
}
|
||||
|
||||
.header {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.selection {
|
||||
font-weight: 450;
|
||||
font-size: var(--typography-Title-4-fontSize);
|
||||
}
|
||||
|
||||
.iconWrapper {
|
||||
position: relative;
|
||||
top: var(--Spacing-x1);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.circle {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 100px;
|
||||
transition: background-color 0.4s;
|
||||
border: 2px solid var(--Base-Border-Inverted);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.circle[data-checked="true"] {
|
||||
background-color: var(--UI-Input-Controls-Fill-Selected);
|
||||
}
|
||||
|
||||
.wrapper[data-open="true"] .circle[data-checked="false"] {
|
||||
background-color: var(--UI-Text-Placeholder);
|
||||
}
|
||||
|
||||
.wrapper[data-open="false"] .circle[data-checked="false"] {
|
||||
background-color: var(--Base-Surface-Subtle-Hover);
|
||||
}
|
||||
|
||||
.content {
|
||||
overflow: hidden;
|
||||
transition: max-height 0.4s ease-out;
|
||||
max-height: 0;
|
||||
}
|
||||
|
||||
@@ -61,3 +61,8 @@
|
||||
.uiTextMediumContrast * {
|
||||
fill: var(--UI-Text-Medium-contrast);
|
||||
}
|
||||
|
||||
.blue,
|
||||
.blue * {
|
||||
fill: var(--UI-Input-Controls-Fill-Selected);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ const config = {
|
||||
white: styles.white,
|
||||
uiTextHighContrast: styles.uiTextHighContrast,
|
||||
uiTextMediumContrast: styles.uiTextMediumContrast,
|
||||
blue: styles.blue,
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
||||
@@ -58,3 +58,7 @@
|
||||
.pale {
|
||||
color: var(--Scandic-Brand-Pale-Peach);
|
||||
}
|
||||
|
||||
.highContrast {
|
||||
color: var(--UI-Text-High-contrast);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ const config = {
|
||||
black: styles.black,
|
||||
burgundy: styles.burgundy,
|
||||
pale: styles.pale,
|
||||
highContrast: styles.highContrast,
|
||||
},
|
||||
textAlign: {
|
||||
center: styles.center,
|
||||
|
||||
@@ -14,19 +14,8 @@ import type { MiddlewareMatcher } from "@/types/middleware"
|
||||
|
||||
export const middleware: NextMiddleware = async (request) => {
|
||||
const { nextUrl } = request
|
||||
const lang = findLang(nextUrl.pathname)!
|
||||
|
||||
const pathWithoutTrailingSlash = removeTrailingSlash(nextUrl.pathname)
|
||||
const pathNameWithoutLang = pathWithoutTrailingSlash.replace(`/${lang}`, "")
|
||||
const { contentType, uid } = await resolveEntry(pathNameWithoutLang, lang)
|
||||
|
||||
const headers = getDefaultRequestHeaders(request)
|
||||
if (uid) {
|
||||
headers.set("x-uid", uid)
|
||||
}
|
||||
if (contentType) {
|
||||
headers.set("x-contenttype", contentType)
|
||||
}
|
||||
return NextResponse.next({
|
||||
request: {
|
||||
headers,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export interface SectionAccordionProps {
|
||||
header: string
|
||||
selection?: string | string[]
|
||||
isOpen: boolean
|
||||
isCompleted: boolean
|
||||
label: string
|
||||
path: string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user