Bottom-mounted temporary panel.
Choose the categories you'd like to include, then apply to update your results.
<div class="bs-demo">
<div class="bs-backdrop"></div>
<div class="bs-sheet bs-sheet--handle" style="height:260px;" role="dialog" aria-modal="true" aria-labelledby="bs-title">
<div class="bs-grabber" aria-hidden="true"></div>
<div class="bs-header">
<h3 id="bs-title" class="bs-title">Filter results</h3>
<button type="button" class="bs-close" aria-label="Close">
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true" focusable="false"><path d="M1 1L13 13M13 1L1 13" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
</button>
</div>
<div class="bs-body">
<p>Choose the categories you'd like to include, then apply to update your results.</p>
</div>
<div class="bs-footer">
<button type="button" class="bs-apply" style="background:#A8E6C1;border-color:#A8E6C1;">Apply</button>
</div>
</div>
</div>
<style>
.bs-demo { position: relative; min-height: 460px; border-radius: 12px; overflow: hidden; background: linear-gradient(135deg, #BFD9F2, #D9C8F0); }
.bs-backdrop { position: absolute; inset: 0; background: rgba(36,20,48,.45); }
.bs-sheet { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1; background: #FAF7F2; color: #241430; border-radius: 20px 20px 0 0; box-shadow: 0 -14px 40px rgba(36,20,48,.25); box-sizing: border-box; padding: 14px 20px 20px; display: flex; flex-direction: column; font: 16px/1.5 system-ui, sans-serif; }
.bs-grabber { width: 40px; height: 4px; border-radius: 2px; background: #24143033; margin: 0 auto 12px; }
.bs-sheet--tabs .bs-grabber { width: 64px; border-radius: 4px; background: linear-gradient(90deg, #241430 50%, #24143033 50%); }
.bs-sheet--plain .bs-grabber { visibility: hidden; }
.bs-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.bs-title { margin: 0; font-size: 18px; font-weight: 600; }
.bs-close { border: none; background: #24143012; color: #241430; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; cursor: pointer; flex: none; padding: 0; }
.bs-close:hover, .bs-close:focus-visible { background: #24143022; outline: none; }
.bs-body { flex: 1; overflow: auto; font-size: 14px; color: #241430cc; margin-bottom: 16px; }
.bs-body p { margin: 0; }
.bs-footer { display: flex; justify-content: flex-end; }
.bs-apply { font: 600 14px system-ui, sans-serif; padding: 9px 20px; border-radius: 8px; border: 1.5px solid transparent; color: #241430; cursor: pointer; }
.bs-apply:focus-visible { outline: 2px solid #241430; outline-offset: 2px; }
</style><div class="relative min-h-[460px] rounded-xl overflow-hidden" style="background:linear-gradient(135deg,#BFD9F2,#D9C8F0);">
<div class="absolute inset-0 bg-[#241430]/45"></div>
<div role="dialog" aria-modal="true" aria-labelledby="bs-tw-title" class="bs-tw bs-tw--handle absolute left-0 right-0 bottom-0 z-10 bg-[#FAF7F2] text-[#241430] rounded-t-[20px] shadow-[0_-14px_40px_rgba(36,20,48,.25)] box-border px-5 pb-5 pt-3.5 flex flex-col font-sans" style="height:260px;">
<div aria-hidden="true" class="bs-tw-grabber w-10 h-1 rounded-full bg-[#24143033] mx-auto mb-3"></div>
<div class="flex items-start justify-between gap-3 mb-2.5">
<h3 id="bs-tw-title" class="m-0 text-lg font-semibold">Filter results</h3>
<button type="button" aria-label="Close" class="border-0 bg-[#24143012] text-[#241430] w-[30px] h-[30px] rounded-full grid place-items-center cursor-pointer shrink-0 p-0 hover:bg-[#24143022] focus-visible:outline-none">
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true" focusable="false"><path d="M1 1L13 13M13 1L1 13" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
</button>
</div>
<div class="flex-1 overflow-auto text-sm text-[#241430]/80 mb-4">
<p class="m-0">Choose the categories you'd like to include, then apply to update your results.</p>
</div>
<div class="flex justify-end">
<button type="button" class="font-semibold text-sm px-5 py-2 rounded-lg border border-transparent text-[#241430]" style="background:#A8E6C1;border-color:#A8E6C1">Apply</button>
</div>
</div>
</div>
<style>
.bs-tw--tabs .bs-tw-grabber { width: 64px; border-radius: 4px; background: linear-gradient(90deg, #241430 50%, #24143033 50%); }
.bs-tw--plain .bs-tw-grabber { visibility: hidden; }
</style>export function BottomSheet({
title = "Filter results",
content = "Choose the categories you'd like to include, then apply to update your results.",
variant = "handle",
accent = "#A8E6C1",
height = 260,
backdrop = true,
}) {
const grabberStyle = variant === "tabs"
? { width: 64, height: 4, borderRadius: 4, background: "linear-gradient(90deg, #241430 50%, #24143033 50%)", margin: "0 auto 12px" }
: { width: 40, height: 4, borderRadius: 2, background: "#24143033", margin: "0 auto 12px",
visibility: variant === "plain" ? "hidden" : "visible" };
return (
<div style={{ position: "relative", minHeight: 460, borderRadius: 12, overflow: "hidden",
background: "linear-gradient(135deg, #BFD9F2, #D9C8F0)" }}>
{backdrop && <div style={{ position: "absolute", inset: 0, background: "rgba(36,20,48,.45)" }} />}
<div role="dialog" aria-modal="true" aria-labelledby="bs-title" style={{ position: "absolute", left: 0,
right: 0, bottom: 0, zIndex: 1, height, boxSizing: "border-box", background: "#FAF7F2", color: "#241430",
borderRadius: "20px 20px 0 0", boxShadow: "0 -14px 40px rgba(36,20,48,.25)", padding: "14px 20px 20px",
display: "flex", flexDirection: "column", fontFamily: "system-ui, sans-serif" }}>
<div aria-hidden="true" style={grabberStyle} />
<div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 12, marginBottom: 10 }}>
<h3 id="bs-title" style={{ margin: 0, fontSize: 18, fontWeight: 600 }}>{title}</h3>
<button type="button" aria-label="Close" style={{ border: "none", background: "#24143012", color: "#241430",
width: 30, height: 30, borderRadius: "50%", display: "grid", placeItems: "center", cursor: "pointer", padding: 0 }}>
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true" focusable="false"><path d="M1 1L13 13M13 1L1 13" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" /></svg>
</button>
</div>
<div style={{ flex: 1, overflow: "auto", fontSize: 14, color: "#241430cc", marginBottom: 16 }}>
<p style={{ margin: 0 }}>{content}</p>
</div>
<div style={{ display: "flex", justifyContent: "flex-end" }}>
<button type="button" style={{ background: accent, borderColor: accent, color: "#241430" }}>Apply</button>
</div>
</div>
</div>
);
}