From a9ab4e3b9ba16348eb5155f5b436ab32e539ba61 Mon Sep 17 00:00:00 2001 From: Carter Date: Fri, 3 Apr 2026 22:30:33 +0000 Subject: [PATCH 01/10] feat: Added PWA for mobile --- next.config.js | 109 ++++++++++++++++++++++++------------------- public/manifest.json | 22 +++++++++ 2 files changed, 82 insertions(+), 49 deletions(-) create mode 100644 public/manifest.json diff --git a/next.config.js b/next.config.js index abee5674..aaeaba17 100644 --- a/next.config.js +++ b/next.config.js @@ -1,51 +1,62 @@ /** @type {import('next').NextConfig} */ +const withPWA = require('next-pwa')({ + dest: 'public', + register: true, + skipWaiting: true, + disable: process.env.NODE_ENV === 'development', +}); + const nextConfig = { - reactStrictMode: true, - images: { - remotePatterns: [ - { - protocol: 'https', - hostname: 'tr.rbxcdn.com', - }, - ], - }, - env: { - NEXT_PUBLIC_DATABASE_CHECK: process.env.DATABASE_URL ? 'true' : '', - }, - async headers() { - return [ - { - // Apply these headers to all routes - source: '/:path*', - headers: [ - { - key: 'X-DNS-Prefetch-Control', - value: 'on', - }, - { - key: 'X-XSS-Protection', - value: '1; mode=block', - }, - { - key: 'X-Content-Type-Options', - value: 'nosniff', - }, - { - key: 'Referrer-Policy', - value: 'origin-when-cross-origin', - }, - { - key: 'X-Frame-Options', - value: 'SAMEORIGIN', - }, - { - key: 'Content-Security-Policy', - value: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://widget.intercom.io https://js.intercomcdn.com https://cdn.posthog.com https://js.posthog.com https://cdn.intercom.com https://uploads.intercomcdn.com https://uranus.planetaryapp.cloud; script-src-elem 'self' 'unsafe-inline' https://static.cloudflareinsights.com/ https://*.posthog.com https://widget.intercom.io https://js.intercomcdn.com https://cdn.posthog.com https://js.posthog.com https://cdn.intercom.com https://uploads.intercomcdn.com https://uranus.planetaryapp.cloud; script-src-attr 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com https://fonts.intercomcdn.com; img-src 'self' data: https: blob:; connect-src 'self' https: https://api.intercom.io https://events.posthog.com https://app.posthog.com https://uranus.planetaryapp.cloud wss://*.intercom.io wss:; frame-src 'self' https://widget.intercom.io; frame-ancestors 'self'; base-uri 'self'; form-action 'self';", - }, - ], - }, - ]; - }, - }; - - module.exports = nextConfig; + reactStrictMode: true, + // This allows the build to proceed by acknowledging the custom webpack usage + experimental: { + turbopack: {}, + }, + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 'tr.rbxcdn.com', + }, + ], + }, + env: { + NEXT_PUBLIC_DATABASE_CHECK: process.env.DATABASE_URL ? 'true' : '', + }, + async headers() { + return [ + { + // Apply these headers to all routes + source: '/:path*', + headers: [ + { + key: 'X-DNS-Prefetch-Control', + value: 'on', + }, + { + key: 'X-XSS-Protection', + value: '1; mode=block', + }, + { + key: 'X-Content-Type-Options', + value: 'nosniff', + }, + { + key: 'Referrer-Policy', + value: 'origin-when-cross-origin', + }, + { + key: 'X-Frame-Options', + value: 'SAMEORIGIN', + }, + { + key: 'Content-Security-Policy', + value: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://widget.intercom.io https://js.intercomcdn.com https://cdn.posthog.com https://js.posthog.com https://cdn.intercom.com https://uploads.intercomcdn.com https://uranus.planetaryapp.cloud; script-src-elem 'self' 'unsafe-inline' https://static.cloudflareinsights.com/ https://*.posthog.com https://widget.intercom.io https://js.intercomcdn.com https://cdn.posthog.com https://js.posthog.com https://cdn.intercom.com https://uploads.intercomcdn.com https://uranus.planetaryapp.cloud; script-src-attr 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com https://fonts.intercomcdn.com; img-src 'self' data: https: blob:; connect-src 'self' https: https://api.intercom.io https://events.posthog.com https://app.posthog.com https://uranus.planetaryapp.cloud wss://*.intercom.io wss:; frame-src 'self' https://widget.intercom.io; frame-ancestors 'self'; base-uri 'self'; form-action 'self';", + }, + ], + }, + ]; + }, +}; + +module.exports = withPWA(nextConfig); diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 00000000..5faf847b --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,22 @@ +{ + "name": "Orbit Dashboard", + "short_name": "Orbit", + "description": "The ultimate management platform for gaming communities.", + "start_url": "/", + "display": "standalone", + "background_color": "#000000", + "theme_color": "#5865f2", + "icons": [ + { + "src": "/icons/icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/icons/icon-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} From fb8c907d2c72364b0985fc967704e0dea37ee9d1 Mon Sep 17 00:00:00 2001 From: Carter Date: Sat, 4 Apr 2026 00:58:00 +0000 Subject: [PATCH 02/10] fix: force mobile layout for PWA standalone mode --- styles/globals.scss | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/styles/globals.scss b/styles/globals.scss index a9aab612..0a2e221c 100644 --- a/styles/globals.scss +++ b/styles/globals.scss @@ -102,4 +102,28 @@ ul[data-type="taskList"] { flex: 1 1 auto; } } - } \ No newline at end of file + } +/* Force mobile layout when Orbit is opened as a PWA */ +@media all and (display-mode: standalone) { + /* Hide the Desktop Sidebar */ + aside, + [class*="Sidebar"], + .desktop-sidebar { + display: none !important; + } + + /* Show the Mobile/Bottom Navigation */ + nav[class*="Mobile"], + .mobile-nav, + .bottom-nav { + display: flex !important; + position: fixed; + bottom: 0; + width: 100%; + } + + /* Adjust body padding so content isn't hidden behind the bottom nav */ + body { + padding-bottom: env(safe-area-inset-bottom, 20px) !important; + } +} From 3c6d40dbd1b9504600146387f35868942163cd15 Mon Sep 17 00:00:00 2001 From: "carter.accs" Date: Fri, 3 Apr 2026 21:15:38 -0400 Subject: [PATCH 03/10] Update globals.scss --- styles/globals.scss | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/styles/globals.scss b/styles/globals.scss index 0a2e221c..a9aab612 100644 --- a/styles/globals.scss +++ b/styles/globals.scss @@ -102,28 +102,4 @@ ul[data-type="taskList"] { flex: 1 1 auto; } } - } -/* Force mobile layout when Orbit is opened as a PWA */ -@media all and (display-mode: standalone) { - /* Hide the Desktop Sidebar */ - aside, - [class*="Sidebar"], - .desktop-sidebar { - display: none !important; - } - - /* Show the Mobile/Bottom Navigation */ - nav[class*="Mobile"], - .mobile-nav, - .bottom-nav { - display: flex !important; - position: fixed; - bottom: 0; - width: 100%; - } - - /* Adjust body padding so content isn't hidden behind the bottom nav */ - body { - padding-bottom: env(safe-area-inset-bottom, 20px) !important; - } -} + } \ No newline at end of file From 83e876fb1063bec1bc794690ccb2ee2b96157001 Mon Sep 17 00:00:00 2001 From: "carter.accs" Date: Fri, 3 Apr 2026 21:26:04 -0400 Subject: [PATCH 04/10] a --- components/sidebar.tsx | 982 +++++++++++++++++------------------------ 1 file changed, 415 insertions(+), 567 deletions(-) diff --git a/components/sidebar.tsx b/components/sidebar.tsx index ecaad143..d3d07ef6 100644 --- a/components/sidebar.tsx +++ b/components/sidebar.tsx @@ -1,16 +1,15 @@ -import { useState, useEffect, useRef } from "react" -import type { NextPage } from "next" -import { loginState, workspacestate } from "@/state" -import { themeState } from "@/state/theme" -import { useRecoilState } from "recoil" -import { Menu, Listbox, Dialog } from "@headlessui/react" -import { useRouter } from "next/router" +import { useState, useEffect, useRef } from "react"; +import type { NextPage } from "next"; +import { loginState, workspacestate } from "@/state"; +import { themeState } from "@/state/theme"; +import { useRecoilState } from "recoil"; +import { Menu, Listbox } from "@headlessui/react"; +import { useRouter } from "next/router"; import { IconHome, IconHomeFilled, IconMessage2, IconMessage2Filled, - IconServer, IconClipboardList, IconClipboardListFilled, IconBell, @@ -23,94 +22,32 @@ import { IconFileText, IconFileTextFilled, IconShield, + IconShieldFilled, IconCheck, IconRosetteDiscountCheck, IconRosetteDiscountCheckFilled, IconChevronLeft, - IconMenu2, IconSun, IconMoon, - IconX, + IconLogout, IconClock, IconClockFilled, - IconTrophy, - IconTrophyFilled, - IconShieldFilled, IconTarget, - IconCopyright, - IconBook, - IconBrandGithub, - IconHistory, - IconBug, -} from "@tabler/icons-react" -import axios from "axios" -import clsx from "clsx" -import Parser from "rss-parser" -import ReactMarkdown from "react-markdown"; -import packageJson from "../package.json"; + IconDots, +} from "@tabler/icons-react"; +import axios from "axios"; +import clsx from "clsx"; interface SidebarProps { - isCollapsed: boolean - setIsCollapsed: (value: boolean) => void + isCollapsed: boolean; + setIsCollapsed: (value: boolean) => void; } -const ChangelogContent: React.FC<{ workspaceId: number }> = ({ workspaceId }) => { - const [entries, setEntries] = useState< - { title: string; link: string; pubDate: string; content: string }[] - >([]); - const [loading, setLoading] = useState(true); - - useEffect(() => { - fetch('/api/changelog') - .then(res => res.json()) - .then(data => { - setEntries(data); - setLoading(false); - }) - .catch(() => setLoading(false)); - }, [workspaceId]); - - if (loading) return

Loading...

; - if (!entries.length) return

No entries found.

; - - return ( -
- {entries.map((entry, idx) => ( -
- - {entry.title} - -
{entry.pubDate}
-
- {entry.content} -
-
- ))} -
- ); -}; - const Sidebar: NextPage = ({ isCollapsed, setIsCollapsed }) => { - const [login, setLogin] = useRecoilState(loginState) - const [workspace, setWorkspace] = useRecoilState(workspacestate) - const [theme, setTheme] = useRecoilState(themeState) - const [showOrbitInfo, setShowOrbitInfo] = useState(false); - const [showCopyright, setShowCopyright] = useState(false); - const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false) - const [showChangelog, setShowChangelog] = useState(false); - const [changelog, setChangelog] = useState<{ title: string, link: string, pubDate: string, content: string }[]>([]); - const [changelogLoading, setChangelogLoading] = useState(false); + const [login, setLogin] = useRecoilState(loginState); + const [workspace, setWorkspace] = useRecoilState(workspacestate); + const [theme, setTheme] = useRecoilState(themeState); + const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const [docsEnabled, setDocsEnabled] = useState(false); const [alliesEnabled, setAlliesEnabled] = useState(false); const [sessionsEnabled, setSessionsEnabled] = useState(false); @@ -118,65 +55,70 @@ const Sidebar: NextPage = ({ isCollapsed, setIsCollapsed }) => { const [policiesEnabled, setPoliciesEnabled] = useState(false); const [pendingPolicyCount, setPendingPolicyCount] = useState(0); const [pendingNoticesCount, setPendingNoticesCount] = useState(0); + const [mobileMoreOpen, setMobileMoreOpen] = useState(false); + const [mobileMoreVisible, setMobileMoreVisible] = useState(false); + const [isStandalone, setIsStandalone] = useState(false); // PWA Check const workspaceListboxWrapperRef = useRef(null); - const router = useRouter() + const router = useRouter(); + // Detect PWA Mode useEffect(() => { - if (isMobileMenuOpen) { - document.body.classList.add("overflow-hidden") - } else { - document.body.classList.remove("overflow-hidden") - } - return () => { - document.body.classList.remove("overflow-hidden") + if (typeof window !== "undefined" && window.matchMedia("(display-mode: standalone)").matches) { + setIsStandalone(true); } - }, [isMobileMenuOpen]) + }, []); + + const openMoreSheet = () => { + setMobileMoreOpen(true); + requestAnimationFrame(() => { + requestAnimationFrame(() => setMobileMoreVisible(true)); + }); + }; + + const closeMoreSheet = () => { + setMobileMoreVisible(false); + setTimeout(() => setMobileMoreOpen(false), 300); + }; + + useEffect(() => { + if (isMobileMenuOpen) document.body.classList.add("overflow-hidden"); + else document.body.classList.remove("overflow-hidden"); + return () => document.body.classList.remove("overflow-hidden"); + }, [isMobileMenuOpen]); const pages: { - name: string - href: string - icon: React.ElementType - filledIcon?: React.ElementType - accessible?: boolean + name: string; + href: string; + icon: React.ElementType; + filledIcon?: React.ElementType; + accessible?: boolean; }[] = [ { name: "Home", href: `/workspace/${workspace.groupId}`, icon: IconHome, filledIcon: IconHomeFilled }, { name: "Wall", href: `/workspace/${workspace.groupId}/wall`, icon: IconMessage2, filledIcon: IconMessage2Filled, accessible: workspace.yourPermission.includes("view_wall") }, { name: "Activity", href: `/workspace/${workspace.groupId}/activity`, icon: IconClipboardList, filledIcon: IconClipboardListFilled, accessible: true }, { name: "Quotas", href: `/workspace/${workspace.groupId}/quotas`, icon: IconTarget, accessible: true }, - ...(noticesEnabled ? [{ - name: "Notices", - href: `/workspace/${workspace.groupId}/notices`, - icon: IconClock, - filledIcon: IconClockFilled, - accessible: true, - }] : []), - ...(alliesEnabled ? [{ - name: "Alliances", - href: `/workspace/${workspace.groupId}/alliances`, - icon: IconRosetteDiscountCheck, - filledIcon: IconRosetteDiscountCheckFilled, - accessible: true, - }] : []), - ...(sessionsEnabled ? [{ - name: "Sessions", - href: `/workspace/${workspace.groupId}/sessions`, - icon: IconBell, - filledIcon: IconBellFilled, - accessible: true, - }] : []), + ...(noticesEnabled ? [{ name: "Notices", href: `/workspace/${workspace.groupId}/notices`, icon: IconClock, filledIcon: IconClockFilled, accessible: true }] : []), + ...(alliesEnabled ? [{ name: "Alliances", href: `/workspace/${workspace.groupId}/alliances`, icon: IconRosetteDiscountCheck, filledIcon: IconRosetteDiscountCheckFilled, accessible: true }] : []), + ...(sessionsEnabled ? [{ name: "Sessions", href: `/workspace/${workspace.groupId}/sessions`, icon: IconBell, filledIcon: IconBellFilled, accessible: true }] : []), { name: "Staff", href: `/workspace/${workspace.groupId}/views`, icon: IconUser, filledIcon: IconUserFilled, accessible: workspace.yourPermission.includes("view_members") }, ...(docsEnabled ? [{ name: "Docs", href: `/workspace/${workspace.groupId}/docs`, icon: IconFileText, filledIcon: IconFileTextFilled, accessible: true }] : []), ...(policiesEnabled ? [{ name: "Policies", href: `/workspace/${workspace.groupId}/policies`, icon: IconShield, filledIcon: IconShieldFilled, accessible: true }] : []), - { name: "Settings", href: `/workspace/${workspace.groupId}/settings`, icon: IconSettings, filledIcon: IconSettingsFilled, accessible: ["admin", "workspace_customisation", "reset_activity", "manage_features", "manage_apikeys", "view_audit_logs"].some(perm => workspace.yourPermission.includes(perm)) }, + { name: "Settings", href: `/workspace/${workspace.groupId}/settings`, icon: IconSettings, filledIcon: IconSettingsFilled, accessible: ["admin", "workspace_customisation", "reset_activity", "manage_features", "manage_apikeys", "view_audit_logs"].some((perm) => workspace.yourPermission.includes(perm)) }, ]; + const visiblePages = pages.filter((p) => p.accessible === undefined || p.accessible); + + const bottomBarPages = visiblePages.slice(0, 4); + const morePages = visiblePages.slice(4); + const gotopage = (page: string) => { - router.push(page) - setIsMobileMenuOpen(false) - } + router.push(page); + setIsMobileMenuOpen(false); + closeMoreSheet(); + }; const logout = async () => { - await axios.post("/api/auth/logout") + await axios.post("/api/auth/logout"); setLogin({ userId: 1, username: "", @@ -185,40 +127,25 @@ const Sidebar: NextPage = ({ isCollapsed, setIsCollapsed }) => { thumbnail: "", workspaces: [], isOwner: false, - }) - router.push("/login") - } + }); + router.push("/login"); + }; const toggleTheme = () => { - const newTheme = theme === "dark" ? "light" : "dark" - setTheme(newTheme) - if (typeof window !== "undefined") { - localStorage.setItem("theme", newTheme) - } - } - - useEffect(() => { - if (!showChangelog) return; - setChangelogLoading(true); - fetch('/api/changelog') - .then(res => res.json()) - .then((data) => { - const items = Array.isArray(data) ? data : (data?.items ?? []); - setChangelog(Array.isArray(items) ? items : []); - }) - .catch(() => setChangelog([])) - .finally(() => setChangelogLoading(false)); - }, [showChangelog]); + const newTheme = theme === "dark" ? "light" : "dark"; + setTheme(newTheme); + if (typeof window !== "undefined") localStorage.setItem("theme", newTheme); + }; useEffect(() => { fetch(`/api/workspace/${workspace.groupId}/settings/general/configuration`) - .then(res => res.json()) - .then(data => { - setDocsEnabled(data.value.guides?.enabled ?? false); - setAlliesEnabled(data.value.allies?.enabled ?? false); - setSessionsEnabled(data.value.sessions?.enabled ?? false); - setNoticesEnabled(data.value.notices?.enabled ?? false); - setPoliciesEnabled(data.value.policies?.enabled ?? false); + .then((res) => res.json()) + .then((data) => { + setDocsEnabled(data.value?.guides?.enabled ?? false); + setAlliesEnabled(data.value?.allies?.enabled ?? false); + setSessionsEnabled(data.value?.sessions?.enabled ?? false); + setNoticesEnabled(data.value?.notices?.enabled ?? false); + setPoliciesEnabled(data.value?.policies?.enabled ?? false); }) .catch(() => setDocsEnabled(false)); }, [workspace.groupId]); @@ -226,490 +153,411 @@ const Sidebar: NextPage = ({ isCollapsed, setIsCollapsed }) => { useEffect(() => { if (policiesEnabled) { fetch(`/api/workspace/${workspace.groupId}/policies/pending`) - .then(res => res.json()) - .then(data => { - if (data.success) { - setPendingPolicyCount(data.count); - } - }) + .then((res) => res.json()) + .then((data) => data.success && setPendingPolicyCount(data.count)) .catch(() => setPendingPolicyCount(0)); } }, [workspace.groupId, policiesEnabled]); useEffect(() => { - if (noticesEnabled) { - if (workspace.yourPermission?.includes("approve_notices") || workspace.yourPermission?.includes("manage_notices") || workspace.yourPermission?.includes("admin")) { - fetch(`/api/workspace/${workspace.groupId}/activity/notices/count`) - .then(res => res.json()) - .then(data => { - if (data.success) { - setPendingNoticesCount(data.count || 0); - } - }) - .catch(() => setPendingNoticesCount(0)); - } + if (noticesEnabled && (workspace.yourPermission?.includes("approve_notices") || workspace.yourPermission?.includes("manage_notices") || workspace.yourPermission?.includes("admin"))) { + fetch(`/api/workspace/${workspace.groupId}/activity/notices/count`) + .then((res) => res.json()) + .then((data) => data.success && setPendingNoticesCount(data.count || 0)) + .catch(() => setPendingNoticesCount(0)); } }, [workspace.groupId, noticesEnabled, workspace.yourPermission]); return ( <> - {!isMobileMenuOpen && ( - - )} - - {isMobileMenuOpen && ( -
setIsMobileMenuOpen(false)} - /> - )} -
- +
- setShowCopyright(false)} - className="relative z-50" - > - - -
- + {mobileMoreOpen && ( + <> +
- setShowOrbitInfo(false)} - className="relative z-50" +
-
- setShowChangelog(false)} - className="relative z-50" - > - - -
+ +
+ +
+ +
+ +
+
+ + )} - ) -} + ); +}; -export default Sidebar +export default Sidebar; From f699e7c6058dc8975002f37e94353beddcd589f7 Mon Sep 17 00:00:00 2001 From: "carter.accs" Date: Fri, 3 Apr 2026 21:27:07 -0400 Subject: [PATCH 05/10] Refactor global styles and remove dark mode support Removed dark mode styles and adjusted task list styles. --- styles/globals.scss | 56 +++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/styles/globals.scss b/styles/globals.scss index a9aab612..487bdba5 100644 --- a/styles/globals.scss +++ b/styles/globals.scss @@ -34,16 +34,6 @@ a { * { box-sizing: border-box; } -/* -@media (prefers-color-scheme: dark) { - html { - color-scheme: dark; - } - body { - color: white; - background: black; - } -}*/ @tailwind base; @tailwind components; @@ -57,7 +47,6 @@ a { .pagePadding { @apply 2xl:px-48 lg:px-32 md:px-20 sm:px-14 px-8 py-20; } - } @layer utilities { @@ -84,22 +73,35 @@ a { ul[data-type="taskList"] { list-style: none; padding: 0; - - p { - margin: 0; - } - + p { margin: 0; } li { display: flex; - - > label { - flex: 0 0 auto; - margin-right: 0.5rem; - user-select: none; - } - - > div { - flex: 1 1 auto; - } + > label { flex: 0 0 auto; margin-right: 0.5rem; user-select: none; } + > div { flex: 1 1 auto; } } - } \ No newline at end of file +} + +/* --- Final PWA UI Safety Fixes --- */ +@media all and (display-mode: standalone) { + /* Ensure the sidebar never renders if the JS check fails */ + aside, .lg\:flex, .w-64, [class*="Sidebar"] { + display: none !important; + width: 0 !important; + } + + /* Force main content to respect full width */ + main, .main-content { + margin-left: 0 !important; + padding-left: 0 !important; + width: 100% !important; + } + + /* Ensure bottom navigation is pinned to the floor */ + nav, .mobile-nav, .lg\:hidden { + display: flex !important; + position: fixed !important; + bottom: 0 !important; + width: 100% !important; + z-index: 9999; + } +} From 52ed2d1332ae41e41b787d164c00e05081000d24 Mon Sep 17 00:00:00 2001 From: "carter.accs" Date: Fri, 3 Apr 2026 21:32:17 -0400 Subject: [PATCH 06/10] Update globals.scss --- styles/globals.scss | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/styles/globals.scss b/styles/globals.scss index 487bdba5..89d0aa23 100644 --- a/styles/globals.scss +++ b/styles/globals.scss @@ -9,6 +9,8 @@ body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; + /* Fix for PWA elastic scrolling */ + overflow-x: hidden; } html.dark, @@ -58,6 +60,7 @@ a { display: none; } } + .dark input[type="date"]::-webkit-calendar-picker-indicator, .dark input[type="time"]::-webkit-calendar-picker-indicator { filter: invert(1) brightness(1.5) !important; @@ -81,27 +84,42 @@ ul[data-type="taskList"] { } } -/* --- Final PWA UI Safety Fixes --- */ +/* --- THE STANDALONE FIXES --- */ +/* This targets the PWA specifically to fix the layout shift */ @media all and (display-mode: standalone) { - /* Ensure the sidebar never renders if the JS check fails */ - aside, .lg\:flex, .w-64, [class*="Sidebar"] { + /* 1. Nuke the sidebar space */ + aside, + .lg\:flex, + .w-64, + .md\:block, + [class*="sidebar"] { display: none !important; width: 0 !important; + visibility: hidden !important; } - /* Force main content to respect full width */ - main, .main-content { + /* 2. Reset the main content margins (The "Shove" Fix) */ + main, + .flex-1, + [class*="layout"], + [class*="main-content"] { margin-left: 0 !important; padding-left: 0 !important; + margin-right: 0 !important; width: 100% !important; + max-width: 100vw !important; } - /* Ensure bottom navigation is pinned to the floor */ - nav, .mobile-nav, .lg\:hidden { - display: flex !important; - position: fixed !important; - bottom: 0 !important; - width: 100% !important; - z-index: 9999; + /* 3. Center the inner page padding */ + .pagePadding { + padding-left: 1.25rem !important; + padding-right: 1.25rem !important; + padding-top: 2rem !important; + } + + /* 4. Fix Bottom Nav visibility on iPhone with Home Bar */ + nav, .bottom-nav { + padding-bottom: env(safe-area-inset-bottom, 20px) !important; + height: calc(64px + env(safe-area-inset-bottom, 20px)) !important; } } From 1f097d35e584f5fd789392d3669eb5cf76f5b685 Mon Sep 17 00:00:00 2001 From: "carter.accs" Date: Fri, 3 Apr 2026 21:33:42 -0400 Subject: [PATCH 07/10] Update _document.tsx --- pages/_document.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pages/_document.tsx b/pages/_document.tsx index 27d2e0f7..20b7367d 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -4,6 +4,16 @@ export default function Document() { return ( + {/* PWA / iOS Standalone Mode Tags */} + + + + + + + {/* Favicon / Touch Icon (Crucial for iOS to treat it as an app) */} + + - {/* Prevent MIME type sniffing */} - {/* Additional XSS protection */} - {/* Control referrer information */} Date: Fri, 3 Apr 2026 21:40:50 -0400 Subject: [PATCH 08/10] Update globals.scss --- styles/globals.scss | 113 +++++++++++++++----------------------------- 1 file changed, 37 insertions(+), 76 deletions(-) diff --git a/styles/globals.scss b/styles/globals.scss index 89d0aa23..02cdf905 100644 --- a/styles/globals.scss +++ b/styles/globals.scss @@ -1,125 +1,86 @@ @import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap'); -html, -body { - padding: 0; +html, body { + padding: 0; margin: 0; - font-family: 'Inter', -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, - Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; - /* Fix for PWA elastic scrolling */ overflow-x: hidden; } -html.dark, -html.dark body { - background-color: #18181B; +html.dark, html.dark body { + background-color: #18181B; } -html.dark { - -webkit-transform: translateZ(0); - transform: translateZ(0); -} - -.dark [class*="transition"] { - -webkit-backface-visibility: hidden; - backface-visibility: hidden; -} - -a { - color: inherit; - text-decoration: none; -} - -* { - box-sizing: border-box; -} +a { color: inherit; text-decoration: none; } +* { box-sizing: border-box; } @tailwind base; @tailwind components; @tailwind utilities; @layer components { - .cardBtn { - @apply px-5 py-4 bg-white rounded-md mt-3 w-full outline-1 cursor-pointer outline-gray-300 outline text-left hover:bg-zinc-200 focus-visible:bg-zinc-200 transition; - } - - .pagePadding { - @apply 2xl:px-48 lg:px-32 md:px-20 sm:px-14 px-8 py-20; - } + .cardBtn { + @apply px-5 py-4 bg-white rounded-md mt-3 w-full outline-1 cursor-pointer outline-gray-300 outline text-left hover:bg-zinc-200 transition; + } + .pagePadding { + @apply 2xl:px-48 lg:px-32 md:px-20 sm:px-14 px-8 py-20; + } } @layer utilities { - .scrollbar-hide { - -ms-overflow-style: none; - scrollbar-width: none; - } - .scrollbar-hide::-webkit-scrollbar { - display: none; - } + .scrollbar-hide { -ms-overflow-style: none; scrollbar-width: none; } + .scrollbar-hide::-webkit-scrollbar { display: none; } } .dark input[type="date"]::-webkit-calendar-picker-indicator, .dark input[type="time"]::-webkit-calendar-picker-indicator { filter: invert(1) brightness(1.5) !important; } -.dark input::-webkit-clear-button, -.dark input::-webkit-inner-spin-button { - filter: invert(1) brightness(1.5) !important; -} -.dark .force-light-icon { - color: #fff !important; -} - -ul[data-type="taskList"] { - list-style: none; - padding: 0; - p { margin: 0; } - li { - display: flex; - > label { flex: 0 0 auto; margin-right: 0.5rem; user-select: none; } - > div { flex: 1 1 auto; } - } -} -/* --- THE STANDALONE FIXES --- */ -/* This targets the PWA specifically to fix the layout shift */ @media all and (display-mode: standalone) { - /* 1. Nuke the sidebar space */ aside, .lg\:flex, .w-64, - .md\:block, - [class*="sidebar"] { + [class*="Sidebar"] { display: none !important; width: 0 !important; - visibility: hidden !important; } - /* 2. Reset the main content margins (The "Shove" Fix) */ main, .flex-1, - [class*="layout"], + [class*="layout-wrapper"], [class*="main-content"] { margin-left: 0 !important; padding-left: 0 !important; - margin-right: 0 !important; width: 100% !important; max-width: 100vw !important; } - /* 3. Center the inner page padding */ + nav.fixed.bottom-0 { + padding-bottom: env(safe-area-inset-bottom, 24px) !important; + height: calc(70px + env(safe-area-inset-bottom, 0px)) !important; + display: flex !important; + align-items: flex-start !important; + padding-top: 10px !important; + backdrop-filter: blur(12px); + background-color: rgba(255, 255, 255, 0.75) !important; + } + + .dark nav.fixed.bottom-0 { + background-color: rgba(9, 9, 11, 0.85) !important; + border-top: 1px solid rgba(255, 255, 255, 0.1); + } + + body { + padding-bottom: calc(95px + env(safe-area-inset-bottom, 20px)) !important; + } + .pagePadding { + padding-top: calc(1rem + env(safe-area-inset-top, 20px)) !important; padding-left: 1.25rem !important; padding-right: 1.25rem !important; - padding-top: 2rem !important; - } - - /* 4. Fix Bottom Nav visibility on iPhone with Home Bar */ - nav, .bottom-nav { - padding-bottom: env(safe-area-inset-bottom, 20px) !important; - height: calc(64px + env(safe-area-inset-bottom, 20px)) !important; } } From 46b423f1533082fdf46b405821aa7d91f0c2f06c Mon Sep 17 00:00:00 2001 From: "carter.accs" Date: Fri, 3 Apr 2026 21:44:37 -0400 Subject: [PATCH 09/10] if this dosnt work ima smash my screen --- styles/globals.scss | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/styles/globals.scss b/styles/globals.scss index 02cdf905..229554bf 100644 --- a/styles/globals.scss +++ b/styles/globals.scss @@ -60,13 +60,14 @@ a { color: inherit; text-decoration: none; } } nav.fixed.bottom-0 { - padding-bottom: env(safe-area-inset-bottom, 24px) !important; - height: calc(70px + env(safe-area-inset-bottom, 0px)) !important; + padding-bottom: env(safe-area-inset-bottom, 32px) !important; + height: calc(85px + env(safe-area-inset-bottom, 0px)) !important; display: flex !important; align-items: flex-start !important; - padding-top: 10px !important; + padding-top: 14px !important; backdrop-filter: blur(12px); background-color: rgba(255, 255, 255, 0.75) !important; + z-index: 99999; } .dark nav.fixed.bottom-0 { @@ -75,7 +76,7 @@ a { color: inherit; text-decoration: none; } } body { - padding-bottom: calc(95px + env(safe-area-inset-bottom, 20px)) !important; + padding-bottom: calc(110px + env(safe-area-inset-bottom, 20px)) !important; } .pagePadding { From 9a37748f60cbed228c0b6c67aa18b08946c8b80e Mon Sep 17 00:00:00 2001 From: "carter.accs" Date: Fri, 3 Apr 2026 21:53:17 -0400 Subject: [PATCH 10/10] ts better work --- components/sidebar.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/sidebar.tsx b/components/sidebar.tsx index d3d07ef6..cb148a72 100644 --- a/components/sidebar.tsx +++ b/components/sidebar.tsx @@ -57,7 +57,7 @@ const Sidebar: NextPage = ({ isCollapsed, setIsCollapsed }) => { const [pendingNoticesCount, setPendingNoticesCount] = useState(0); const [mobileMoreOpen, setMobileMoreOpen] = useState(false); const [mobileMoreVisible, setMobileMoreVisible] = useState(false); - const [isStandalone, setIsStandalone] = useState(false); // PWA Check + const [isStandalone, setIsStandalone] = useState(false); // Added for PWA check const workspaceListboxWrapperRef = useRef(null); const router = useRouter(); @@ -396,8 +396,9 @@ const Sidebar: NextPage = ({ isCollapsed, setIsCollapsed }) => {