diff --git a/apps/webapp/app/assets/images/blurred-dashboard-background-menu-bottom.jpg b/apps/webapp/app/assets/images/blurred-dashboard-background-menu-bottom.jpg new file mode 100644 index 0000000000..2a993f8212 Binary files /dev/null and b/apps/webapp/app/assets/images/blurred-dashboard-background-menu-bottom.jpg differ diff --git a/apps/webapp/app/assets/images/blurred-dashboard-background-menu-top.jpg b/apps/webapp/app/assets/images/blurred-dashboard-background-menu-top.jpg new file mode 100644 index 0000000000..8aca8563cd Binary files /dev/null and b/apps/webapp/app/assets/images/blurred-dashboard-background-menu-top.jpg differ diff --git a/apps/webapp/app/assets/images/blurred-dashboard-background-table.jpg b/apps/webapp/app/assets/images/blurred-dashboard-background-table.jpg new file mode 100644 index 0000000000..a2ae4029fe Binary files /dev/null and b/apps/webapp/app/assets/images/blurred-dashboard-background-table.jpg differ diff --git a/apps/webapp/app/components/BackgroundWrapper.tsx b/apps/webapp/app/components/BackgroundWrapper.tsx new file mode 100644 index 0000000000..ecff3af6dd --- /dev/null +++ b/apps/webapp/app/components/BackgroundWrapper.tsx @@ -0,0 +1,48 @@ +import { type ReactNode } from "react"; +import blurredDashboardBackgroundMenuTop from "~/assets/images/blurred-dashboard-background-menu-top.jpg"; +import blurredDashboardBackgroundMenuBottom from "~/assets/images/blurred-dashboard-background-menu-bottom.jpg"; +import blurredDashboardBackgroundTable from "~/assets/images/blurred-dashboard-background-table.jpg"; + +export function BackgroundWrapper({ children }: { children: ReactNode }) { + return ( +
+ {/* Left menu top background - fixed width 260px, maintains aspect ratio */} +
+ + {/* Left menu bottom background - fixed width 260px, maintains aspect ratio */} +
+ + {/* Right table background - fixed width 2000px, positioned next to menu */} +
+ + {/* Content layer */} +
{children}
+
+ ); +} diff --git a/apps/webapp/app/components/layout/AppLayout.tsx b/apps/webapp/app/components/layout/AppLayout.tsx index e45836e496..0793c52cac 100644 --- a/apps/webapp/app/components/layout/AppLayout.tsx +++ b/apps/webapp/app/components/layout/AppLayout.tsx @@ -1,8 +1,18 @@ import { cn } from "~/utils/cn"; /** This container is used to surround the entire app, it correctly places the nav bar */ -export function AppContainer({ children }: { children: React.ReactNode }) { - return
{children}
; +export function AppContainer({ + children, + className, +}: { + children: React.ReactNode; + className?: string; +}) { + return ( +
+ {children} +
+ ); } export function MainBody({ children }: { children: React.ReactNode }) { diff --git a/apps/webapp/app/components/primitives/Spinner.tsx b/apps/webapp/app/components/primitives/Spinner.tsx index a9182b46ce..158ea2c998 100644 --- a/apps/webapp/app/components/primitives/Spinner.tsx +++ b/apps/webapp/app/components/primitives/Spinner.tsx @@ -66,8 +66,8 @@ export function ButtonSpinner() { ); diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.invite/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.invite/route.tsx index f3bf509b0f..8f82153052 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.invite/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.invite/route.tsx @@ -143,7 +143,7 @@ export default function Page() { const emailFields = useFieldList(form.ref, emails); return ( - +
} @@ -203,7 +203,7 @@ export default function Page() { } cancelButton={ - + Cancel } diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug_.projects.new/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug_.projects.new/route.tsx index 3cd51e2641..9b292cb5ad 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug_.projects.new/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug_.projects.new/route.tsx @@ -7,7 +7,8 @@ import { Form, useActionData, useNavigation } from "@remix-run/react"; import { redirect, typedjson, useTypedLoaderData } from "remix-typedjson"; import invariant from "tiny-invariant"; import { z } from "zod"; -import { MainCenteredContainer } from "~/components/layout/AppLayout"; +import { BackgroundWrapper } from "~/components/BackgroundWrapper"; +import { AppContainer, MainCenteredContainer } from "~/components/layout/AppLayout"; import { Button, LinkButton } from "~/components/primitives/Buttons"; import { Callout } from "~/components/primitives/Callout"; import { Fieldset } from "~/components/primitives/Fieldset"; @@ -20,15 +21,14 @@ import { Label } from "~/components/primitives/Label"; import { ButtonSpinner } from "~/components/primitives/Spinner"; import { prisma } from "~/db.server"; import { featuresForRequest } from "~/features.server"; -import { useFeatures } from "~/hooks/useFeatures"; import { redirectWithSuccessMessage } from "~/models/message.server"; import { createProject } from "~/models/project.server"; import { requireUserId } from "~/services/session.server"; import { OrganizationParamsSchema, organizationPath, - v3ProjectPath, selectPlanPath, + v3ProjectPath, } from "~/utils/pathBuilder"; export async function loader({ params, request }: LoaderFunctionArgs) { @@ -138,57 +138,61 @@ export default function Page() { const isLoading = navigation.state === "submitting" || navigation.state === "loading"; return ( - -
- } - title="Create a new project" - description={`This will create a new project in your "${organization.title}" organization.`} - /> -
- {message && ( - - {message} - - )} -
- - - - {projectName.error} - - {canCreateV3Projects ? ( - - ) : ( - - )} - - {isLoading ? "Creating…" : "Create"} - - } - cancelButton={ - organization.projectsCount > 0 ? ( - - Cancel - - ) : undefined - } + + + +
+ } + title="Create a new project" + description={`This will create a new project in your "${organization.title}" organization.`} /> -
-
-
-
+
+ {message && ( + + {message} + + )} +
+ + + + {projectName.error} + + {canCreateV3Projects ? ( + + ) : ( + + )} + + {isLoading ? "Creating…" : "Create"} + + } + cancelButton={ + organization.projectsCount > 0 ? ( + + Cancel + + ) : undefined + } + /> +
+
+
+
+ + ); } diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug_.select-plan/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug_.select-plan/route.tsx index e1561becf4..844c5d66ee 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug_.select-plan/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug_.select-plan/route.tsx @@ -1,6 +1,7 @@ import { LoaderFunctionArgs } from "@remix-run/server-runtime"; import { redirect, typedjson, useTypedLoaderData } from "remix-typedjson"; -import { MainCenteredContainer } from "~/components/layout/AppLayout"; +import { BackgroundWrapper } from "~/components/BackgroundWrapper"; +import { AppContainer } from "~/components/layout/AppLayout"; import { Header1 } from "~/components/primitives/Headers"; import { prisma } from "~/db.server"; import { featuresForRequest } from "~/features.server"; @@ -48,16 +49,22 @@ export default function ChoosePlanPage() { useTypedLoaderData(); return ( - - Subscribe for full access - - + + +
+ Subscribe for full access +
+ +
+
+
+
); } diff --git a/apps/webapp/app/routes/_app.orgs.new/route.tsx b/apps/webapp/app/routes/_app.orgs.new/route.tsx index a171153510..a677782eae 100644 --- a/apps/webapp/app/routes/_app.orgs.new/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.new/route.tsx @@ -7,7 +7,8 @@ import { json, redirect } from "@remix-run/node"; import { Form, useActionData, useNavigation } from "@remix-run/react"; import { typedjson, useTypedLoaderData } from "remix-typedjson"; import { z } from "zod"; -import { MainCenteredContainer } from "~/components/layout/AppLayout"; +import { BackgroundWrapper } from "~/components/BackgroundWrapper"; +import { AppContainer, MainCenteredContainer } from "~/components/layout/AppLayout"; import { Button, LinkButton } from "~/components/primitives/Buttons"; import { Fieldset } from "~/components/primitives/Fieldset"; import { FormButtons } from "~/components/primitives/FormButtons"; @@ -94,85 +95,92 @@ export default function NewOrganizationPage() { const isLoading = navigation.state === "submitting" || navigation.state === "loading"; return ( - - } - title="Create an Organization" - /> -
-
- - - - E.g. your company name or your workspace name. - {orgName.error} - - {isManagedCloud && ( - <> - - - - - - - - - + + + + } + title="Create an Organization" + /> + +
- -