Native expandable disclosure component.
Unlimited projects, priority support, and export to every format we make.
No JavaScript — click the summary to toggle. The open attribute is what the control forces.
<details class="det" style="--accent:#F5C2E0;">
<summary class="det__summary">What's included in Studio Plus?</summary>
<p class="det__body">Unlimited projects, priority support, and export to every format we make.</p>
</details>
<p class="det__hint">No JavaScript — click the summary to toggle. The <code>open</code> attribute is what the control forces.</p>
<style>
.det { width: 340px; box-sizing: border-box; font: 15px/1.5 system-ui, sans-serif; color: #241430; background: #FAF7F2; border: 1.5px solid #24143025; border-radius: 10px; padding: 4px 18px; }
.det__summary { list-style: none; cursor: pointer; padding: 14px 0; font-weight: 700; display: flex; justify-content: space-between; align-items: center; }
.det__summary::-webkit-details-marker { display: none; }
.det__summary::after { content: ""; width: 9px; height: 9px; border-right: 2px solid var(--accent); border-bottom: 2px solid var(--accent); transform: rotate(-45deg); }
@media (prefers-reduced-motion: no-preference) {
.det__summary::after { transition: transform .15s; }
}
.det[open] .det__summary::after { transform: rotate(45deg); }
.det__summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.det__body { margin: 0 0 16px; font-size: 14px; color: #241430cc; }
.det__hint { width: 340px; box-sizing: border-box; margin: 10px 0 0; font-size: 12px; color: #241430888; }
.det__hint code { background: #24143012; padding: 1px 5px; border-radius: 4px; }
</style><details class="w-[340px] box-border font-sans text-[15px] text-[#241430] bg-[#FAF7F2] border-[1.5px] border-[#24143025] rounded-[10px] px-[18px] py-1 [&_summary::-webkit-details-marker]:hidden [&>summary]:list-none">
<summary class="cursor-pointer py-3.5 font-bold flex justify-between items-center">
What's included in Studio Plus?
<span aria-hidden="true" class="w-2 h-2 border-r-2 border-b-2 -rotate-45" style="border-color:#F5C2E0"></span>
</summary>
<p class="m-0 mb-4 text-sm text-[#241430]/80">Unlimited projects, priority support, and export to every format we make.</p>
</details>
<p class="w-[340px] box-border mt-2.5 text-xs text-[#241430]/55">No JavaScript — click the summary to toggle. The <code class="bg-[#24143012] px-1.5 py-0.5 rounded">open</code> attribute is what the control forces.</p>import { useState } from "react";
export function DetailsElement({
summaryText = "What's included in Studio Plus?",
body = "Unlimited projects, priority support, and export to every format we make.",
accent = "#F5C2E0",
open: initialOpen = false,
}) {
const [open, setOpen] = useState(initialOpen);
return (
<div>
<details open={open} onToggle={(e) => setOpen(e.target.open)}
style={{ width: 340, boxSizing: "border-box", font: "15px/1.5 system-ui, sans-serif", color: "#241430", background: "#FAF7F2", border: "1.5px solid #24143025", borderRadius: 10, padding: "4px 18px" }}>
<summary style={{ cursor: "pointer", padding: "14px 0", fontWeight: 700, display: "flex", justifyContent: "space-between", alignItems: "center", listStyle: "none" }}>
{summaryText}
<span aria-hidden="true" style={{ width: 9, height: 9, borderRight: `2px solid ${accent}`, borderBottom: `2px solid ${accent}`, transform: open ? "rotate(45deg)" : "rotate(-45deg)" }} />
</summary>
<p style={{ margin: "0 0 16px", fontSize: 14, color: "#241430cc" }}>{body}</p>
</details>
<p style={{ width: 340, marginTop: 10, fontSize: 12, color: "#24143088" }}>
No JavaScript needed — click the summary to toggle. <code>open</code> is the real attribute.
</p>
</div>
);
}