actions.saveDmnModel(currentDmnModel())}
>
Save Changes
diff --git a/builder-frontend/src/components/project/Project.tsx b/builder-frontend/src/components/project/Project.tsx
index 5fb28868..a92d0b12 100644
--- a/builder-frontend/src/components/project/Project.tsx
+++ b/builder-frontend/src/components/project/Project.tsx
@@ -2,7 +2,7 @@ import { createSignal, createResource, Accessor } from "solid-js";
import { useParams } from "@solidjs/router";
import FormEditorView from "./FormEditorView";
-import Header from "../Header";
+import Header from "../Header/Header";
import Loading from "../Loading";
import ManageBenefits from "./manageBenefits/ManageBenefits";
import Preview from "./preview/Preview";
@@ -11,7 +11,6 @@ import Publish from "./Publish";
import { fetchProject } from "@/api/screener";
import BdtNavbar, { NavbarProps } from "@/components/shared/BdtNavbar";
-
type TabOption = "manageBenefits" | "formEditor" | "preview" | "publish";
function Project() {
@@ -34,16 +33,32 @@ function Project() {
// including a dummy signal 'forceUpdate' that can be unique for
// each call to the refetch
() => [params.projectId, forceUpdate()],
- fetchAndCacheProject
+ fetchAndCacheProject,
);
const navbarDefs: Accessor
= () => {
return {
tabDefs: [
- { key: "manageBenefits", label: "Manage Benefits", onClick: () => setActiveTab("manageBenefits") },
- { key: "formEditor", label: "Form Editor", onClick: () => setActiveTab("formEditor") },
- { key: "preview", label: "Preview", onClick: () => setActiveTab("preview") },
- { key: "publish", label: "Publish", onClick: () => setActiveTab("publish") },
+ {
+ key: "manageBenefits",
+ label: "Manage Benefits",
+ onClick: () => setActiveTab("manageBenefits"),
+ },
+ {
+ key: "formEditor",
+ label: "Form Editor",
+ onClick: () => setActiveTab("formEditor"),
+ },
+ {
+ key: "preview",
+ label: "Preview",
+ onClick: () => setActiveTab("preview"),
+ },
+ {
+ key: "publish",
+ label: "Publish",
+ onClick: () => setActiveTab("publish"),
+ },
],
activeTabKey: () => activeTab(),
titleDef: { label: project().screenerName },
@@ -52,9 +67,9 @@ function Project() {
return (
-
+
{project.loading ? (
-
+
) : (
<>
@@ -64,11 +79,9 @@ function Project() {
setFormSchema={setFormSchema}
/>
)}
- {activeTab() == "manageBenefits" && (
-
- )}
+ {activeTab() == "manageBenefits" &&
}
{activeTab() == "preview" && (
-
+
)}
{activeTab() == "publish" && (
= (props) => {
+ const menuCtx = useHamburgerMenuContext();
+ return (
+
+ );
+};
diff --git a/builder-frontend/src/components/shared/HamburgerMenu/HamburgerMenuItem.tsx b/builder-frontend/src/components/shared/HamburgerMenu/HamburgerMenuItem.tsx
new file mode 100644
index 00000000..2ed37191
--- /dev/null
+++ b/builder-frontend/src/components/shared/HamburgerMenu/HamburgerMenuItem.tsx
@@ -0,0 +1,13 @@
+import { Component } from "solid-js";
+
+interface Props {
+ label: string;
+ onClick: () => void;
+}
+export const HamburgerMenuItem: Component = (props) => {
+ return (
+
+ );
+};
diff --git a/builder-frontend/src/components/shared/HamburgerMenu/HamburgerMenuPanel.tsx b/builder-frontend/src/components/shared/HamburgerMenu/HamburgerMenuPanel.tsx
new file mode 100644
index 00000000..18a6c268
--- /dev/null
+++ b/builder-frontend/src/components/shared/HamburgerMenu/HamburgerMenuPanel.tsx
@@ -0,0 +1,21 @@
+import { Component, JSX, Show } from "solid-js";
+import { useHamburgerMenuContext } from "./HamburgerMenuWrapper";
+
+interface Props {
+ children: JSX.Element;
+}
+export const HamburgerMenuPanel: Component = (props) => {
+ const { showMenu, setShowMenu } = useHamburgerMenuContext();
+ return (
+
+
+
+
+
+ );
+};
diff --git a/builder-frontend/src/components/shared/HamburgerMenu/HamburgerMenuWrapper.tsx b/builder-frontend/src/components/shared/HamburgerMenu/HamburgerMenuWrapper.tsx
new file mode 100644
index 00000000..336b4038
--- /dev/null
+++ b/builder-frontend/src/components/shared/HamburgerMenu/HamburgerMenuWrapper.tsx
@@ -0,0 +1,60 @@
+import {
+ createContext,
+ createSignal,
+ onCleanup,
+ onMount,
+ ParentComponent,
+ useContext,
+} from "solid-js";
+
+export type HamburgerMenuContextValue = {
+ showMenu: () => boolean;
+ setShowMenu: (show: boolean) => void;
+ toggle: () => void;
+};
+
+export const HamburgerMenuContext = createContext();
+
+export const useHamburgerMenuContext = () => {
+ const ctx = useContext(HamburgerMenuContext);
+ if (!ctx) {
+ throw new Error(
+ "HamburgerMenu components must be used within ",
+ );
+ }
+ return ctx;
+};
+
+export const HamburgerMenuWrapper: ParentComponent = (props) => {
+ const [root, setRoot] = createSignal();
+ const [showMenu, setShowMenu] = createSignal(false);
+
+ const handleClickOutside = (ev: MouseEvent) => {
+ const el = root();
+ if (showMenu() && el && !el.contains(ev.target as Node)) {
+ setShowMenu(false);
+ }
+ };
+
+ const ctx: HamburgerMenuContextValue = {
+ showMenu,
+ setShowMenu,
+ toggle: () => setShowMenu(!showMenu()),
+ };
+
+ onMount(() => {
+ document.addEventListener("click", handleClickOutside);
+ });
+
+ onCleanup(() => {
+ document.removeEventListener("click", handleClickOutside);
+ });
+
+ return (
+
+
+
+ );
+};
diff --git a/builder-frontend/src/components/shared/HamburgerMenu/index.tsx b/builder-frontend/src/components/shared/HamburgerMenu/index.tsx
new file mode 100644
index 00000000..3c81a233
--- /dev/null
+++ b/builder-frontend/src/components/shared/HamburgerMenu/index.tsx
@@ -0,0 +1,27 @@
+/**
+ * HamburgerMenu component
+ *
+ * Usage:
+ * - Wrap all sub-components in
+ * - Opens a panel on the left side (can be parameterized in the future)
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+import { HamburgerMenuWrapper } from "@/components/shared/HamburgerMenu/HamburgerMenuWrapper";
+import { HamburgerMenuButton } from "@/components/shared/HamburgerMenu/HamburgerMenuButton";
+import { HamburgerMenuPanel } from "@/components/shared/HamburgerMenu/HamburgerMenuPanel";
+
+import "./HamburgerMenu.css";
+
+export const HamburgerMenu = Object.assign(HamburgerMenuWrapper, {
+ Button: HamburgerMenuButton,
+ Panel: HamburgerMenuPanel,
+});