import { createSignal, createEffect, For, Show, JSXElement } from "solid-js"; import { Icon } from "./Icons.tsx"; // Baseline Tailwind for the scoped .ui-accordion stack. The ui-* class // names are kept so page-specific CSS overrides (e.g. sale.css, // licensing.css) can continue to layer on top. const ROOT = "ui-accordion border border-line rounded-default overflow-hidden"; const ITEM = "ui-accordion-item border-b border-line last:border-b-0"; const TRIGGER = "ui-accordion-trigger flex items-center justify-between w-full py-3 px-4 text-left font-medium text-ink bg-surface-muted cursor-pointer border-none transition-colors hover:bg-surface-raised active:bg-surface-strong focus:outline-hidden disabled:text-ink-faint disabled:cursor-not-allowed disabled:bg-surface-muted"; const TITLE = "ui-accordion-title flex-1"; const CONTENT = "ui-accordion-content px-4 pb-4 text-ink"; function iconCls(open: boolean): string { return "ui-accordion-icon text-ink-muted leading-none transition-transform duration-200" + (open ? " rotate-180" : ""); } interface AccordionItemProps { startOpen?: boolean; isOpen?: boolean; disabled?: boolean; title?: string; children?: JSXElement; } export function AccordionItem(props: AccordionItemProps) { const getStartOpen = () => typeof props.startOpen === "function" ? (props.startOpen as () => boolean)() : !!props.startOpen; const [isOpen, setIsOpen] = createSignal(getStartOpen()); createEffect(() => { if (props.isOpen === undefined) return; const v = typeof props.isOpen === "function" ? (props.isOpen as () => boolean)() : !!props.isOpen; setIsOpen(v); }); const isDisabled = () => typeof props.disabled === "function" ? (props.disabled as () => boolean)() : !!props.disabled; const title = () => typeof props.title === "function" ? (props.title as () => string)() : props.title; const toggle = () => { if (isDisabled()) return; setIsOpen(!isOpen()); }; return (
{props.children}
); } interface AccordionItemData { title: string; content: JSXElement; disabled?: boolean; } interface AccordionProps { items?: AccordionItemData[]; } export function Accordion(props: AccordionProps) { const items = () => props.items || []; return (
{(item) => ( { const t = item.title; return typeof t === "function" ? (t as () => string)() : t; })()} disabled={(() => { const d = item.disabled; return typeof d === "function" ? (d as () => boolean)() : !!d; })()}> {item.content} )}
); } interface SingleAccordionProps { items?: AccordionItemData[]; startOpen?: number; } export function SingleAccordion(props: SingleAccordionProps) { const items = () => props.items || []; const [openIndex, setOpenIndex] = createSignal(props.startOpen ?? 0); const toggleItem = (index: number) => { setOpenIndex(openIndex() === index ? -1 : index); }; return (
{(item, index) => (
{item.content}
)}
); }