diff --git a/src/components/journal/JournalContext.tsx b/src/components/journal/JournalContext.tsx new file mode 100644 index 0000000..83c5eae --- /dev/null +++ b/src/components/journal/JournalContext.tsx @@ -0,0 +1,18 @@ +/** + * Journal context — provides `onClose` to message renderers so that + * clicking a link message can close the panel on mobile. + */ + +import { createContext, useContext } from "solid-js"; + +export interface JournalContextValue { + onClose: () => void; +} + +const JournalContext = createContext(); + +export function useJournalContext(): JournalContextValue | undefined { + return useContext(JournalContext); +} + +export { JournalContext }; diff --git a/src/components/journal/JournalPanel.tsx b/src/components/journal/JournalPanel.tsx index d4ee546..2d2d1df 100644 --- a/src/components/journal/JournalPanel.tsx +++ b/src/components/journal/JournalPanel.tsx @@ -26,6 +26,7 @@ import { } from "../stores/journalStream"; import { StreamView } from "./StreamView"; import { JournalInput } from "./JournalInput"; +import { JournalContext } from "./JournalContext"; export interface JournalPanelProps { open: boolean; @@ -57,49 +58,51 @@ export const JournalPanel: Component = (props) => { transition-transform duration-300 ease-in-out ${ props.open ? "translate-x-0" : "translate-x-full" }`} - aria-hidden={!props.open} + inert={!props.open} > - {/* Header */} - + + {/* Header */} + - {/* Player list tabs */} - -
- - {([name]) => ( - - {name} - - )} - - -
-
- - - + {/* Player list tabs */} + +
+ + {([name]) => ( + + {name} + + )} + +
- } - > -
- -
- -
+
- {/* Invite modal */} - - setShowInvite(false)} /> - + + + + } + > +
+ +
+ +
+ + {/* Invite modal */} + + setShowInvite(false)} /> + +
); diff --git a/src/components/journal/index.ts b/src/components/journal/index.ts index a799f87..eb4c623 100644 --- a/src/components/journal/index.ts +++ b/src/components/journal/index.ts @@ -44,3 +44,5 @@ export { ComposePanel } from "./ComposePanel"; export { JournalInput } from "./JournalInput"; export { DynamicForm } from "./DynamicForm"; export { useJournalCompletions, invalidateCompletions } from "./completions"; +export { JournalContext, useJournalContext } from "./JournalContext"; +export type { JournalContextValue } from "./JournalContext"; diff --git a/src/components/journal/types/link.tsx b/src/components/journal/types/link.tsx index 18ac991..c3960fa 100644 --- a/src/components/journal/types/link.tsx +++ b/src/components/journal/types/link.tsx @@ -11,6 +11,7 @@ import { z } from "zod"; import { registerMessageType } from "../registry"; import { journalSetState } from "../../stores/journalStream"; import { produce } from "solid-js/store"; +import { useJournalContext } from "../JournalContext"; const schema = z.object({ path: z.string().min(1), @@ -44,6 +45,7 @@ function slugToTitle(slug: string): string { const RevealLink: Component = (p) => { const navigate = useNavigateWithParams(); + const ctx = useJournalContext(); const target = () => { let t = encodePath(p.path); @@ -59,6 +61,10 @@ const RevealLink: Component = (p) => { const handleClick = (e: MouseEvent) => { e.preventDefault(); navigate(target()); + // On mobile, close the journal panel to reveal the article + if (window.innerWidth < 768) { + ctx?.onClose(); + } }; return (