-
+ >
+ );
+};
+
+type DraftListProps = {
+ guides: Array
;
+ activeGuideId: string;
+ collapsed?: boolean;
+ onSelectGuide: (localDraftId: string) => void;
+};
+
+export const DraftList = ({
+ guides,
+ activeGuideId,
+ collapsed = false,
+ onSelectGuide,
+}: DraftListProps) => {
+ return (
+
+ {guides.map((guide, index) => {
+ const active = guide.localDraftId === activeGuideId;
+
+ const displayTitle = guide.title.trim() || `Guide ${index + 1}`;
+
+ return (
+ -
+
+
+
+
+ );
+ })}
+
);
};
diff --git a/app/src/components/sidebar/MobileDraftSwitcher.tsx b/app/src/components/sidebar/MobileDraftSwitcher.tsx
new file mode 100644
index 00000000..e1d73460
--- /dev/null
+++ b/app/src/components/sidebar/MobileDraftSwitcher.tsx
@@ -0,0 +1,104 @@
+import { useState } from "react";
+import { PanelLeftOpen } from "lucide-react";
+
+import type { GuideOption } from "@/components/sidebar/EditorSidebar";
+
+import { Separator } from "@/components/ui/separator";
+import {
+ Sheet,
+ SheetContent,
+ SheetDescription,
+ SheetHeader,
+ SheetTitle,
+ SheetTrigger,
+} from "@/components/ui/sheet";
+import { DraftActions, DraftList } from "@/components/sidebar/EditorSidebar";
+
+type Props = {
+ guides: Array;
+ activeGuideId: string;
+
+ onSelectGuide: (localDraftId: string) => void;
+ onAddGuide: () => void;
+ onDeleteGuide: (localDraftId: string) => void;
+};
+
+/**
+ * mobile replacement for EditorSidebar - a bar showing the active draft
+ * that opens the draft list in a sheet sliding in from the left
+ */
+export const MobileDraftSwitcher = ({
+ guides,
+ activeGuideId,
+ onSelectGuide,
+ onAddGuide,
+ onDeleteGuide,
+}: Props) => {
+ const [open, setOpen] = useState(false);
+
+ const activeIndex = guides.findIndex(
+ (guide) => guide.localDraftId === activeGuideId
+ );
+ const activeTitle =
+ guides[activeIndex]?.title.trim() || `Guide ${activeIndex + 1}`;
+
+ const selectGuide = (localDraftId: string) => {
+ onSelectGuide(localDraftId);
+ setOpen(false);
+ };
+
+ const addGuide = () => {
+ onAddGuide();
+ setOpen(false);
+ };
+
+ return (
+
+
+
+
+
+
+
+
+ Drafts
+
+
+ Switch between, add or remove guide drafts.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/app/src/components/ui/sheet.tsx b/app/src/components/ui/sheet.tsx
index 46757797..f27490b3 100644
--- a/app/src/components/ui/sheet.tsx
+++ b/app/src/components/ui/sheet.tsx
@@ -36,7 +36,7 @@ function SheetOverlay({
+ useSyncExternalStore(
+ (onChange) => {
+ const mql = window.matchMedia(query);
+ mql.addEventListener("change", onChange);
+ return () => mql.removeEventListener("change", onChange);
+ },
+ () => window.matchMedia(query).matches,
+ () => false
+ );
diff --git a/app/src/styles.css b/app/src/styles.css
index 107ee0db..6573976b 100644
--- a/app/src/styles.css
+++ b/app/src/styles.css
@@ -586,3 +586,8 @@
math-field::part(virtual-keyboard-toggle) {
display: none !important;
}
+
+/* Stop scroll on `Sheet` elements for mobile users */
+html body[data-scroll-locked] {
+ margin-right: 0 !important;
+}