rename
Deploy Static Site / deploy (push) Failing after 4m58s

This commit is contained in:
Lars Nolden
2026-08-14 14:41:46 +02:00
parent fdb3f11e47
commit 3f21baa13d
165 changed files with 378 additions and 378 deletions
@@ -0,0 +1,84 @@
import * as React from "react"
import { Plus } from "lucide-react"
import { cn } from "@/lib/utils"
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
type FaqItem = {
question: React.ReactNode
answer: React.ReactNode
}
/**
* Toggle disc: hairline teal plus that fills in and turns into an × once its
* item opens. Driven by the trigger's own `group`, so hovering the answer body
* below leaves the disc alone.
*/
function FaqIndicator() {
return (
<span
aria-hidden="true"
className="flex size-8 shrink-0 items-center justify-center rounded-full border border-brand-100 bg-card text-primary shadow-pill transition-[transform,color,background-color,border-color] duration-200 group-hover:border-brand-200 group-hover:bg-accent group-data-[state=open]:rotate-45 group-data-[state=open]:border-transparent group-data-[state=open]:bg-primary group-data-[state=open]:text-primary-foreground"
>
<Plus className="size-4" strokeWidth={2.5} />
</span>
)
}
/**
* FAQ list: one white card per question, plus disc as the toggle, and the open
* card tinted brand-50 behind a mint hairline so the answer reads as its own
* panel. Single-open and collapsible — the block only ever moves one card's
* worth of height, and every answer can be closed again.
*
* Sized for a reading column (centred `max-w-3xl`) instead of the full 6xl
* container; override the width via `className`.
*/
function FaqAccordion({
items,
defaultOpen = 0,
className,
}: {
items: FaqItem[]
/** index of the item open on first paint; `null` starts fully collapsed */
defaultOpen?: number | null
className?: string
}) {
return (
<Accordion
type="single"
collapsible
defaultValue={defaultOpen == null ? undefined : `faq-${defaultOpen}`}
className={cn("mx-auto flex w-full max-w-3xl flex-col gap-3", className)}
>
{items.map((item, i) => (
<AccordionItem
key={i}
value={`faq-${i}`}
/* the all-round `border` supersedes the primitive's divider width,
which leaves `last:border-b-0` to strip the final card's bottom
edge — `last:border-b` puts it back. */
className="rounded-2xl border border-border/70 bg-card px-5 shadow-card transition-colors duration-200 last:border-b hover:border-brand-200 data-[state=open]:border-brand-200 data-[state=open]:bg-brand-50/50 sm:px-6"
>
<AccordionTrigger
className="group items-center gap-5 rounded-xl py-5 text-base leading-snug font-bold text-navy"
indicator={<FaqIndicator />}
>
{item.question}
</AccordionTrigger>
<AccordionContent className="pb-6 leading-relaxed text-pretty sm:pr-13">
{item.answer}
</AccordionContent>
</AccordionItem>
))}
</Accordion>
)
}
export { FaqAccordion }
export type { FaqItem }