Skip to content

Commit aa0dc50

Browse files
author
Alain Bourgeois
committed
mobile/tablet trial
1 parent 0cac9df commit aa0dc50

3 files changed

Lines changed: 88 additions & 9 deletions

File tree

src/mainPage/menu.css

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,22 @@
4646
z-index: 100;
4747
}
4848

49+
html[data-layout='mobile'] .app-nav {
50+
position: fixed;
51+
top: var(--app-header-height, 4.5rem);
52+
left: 0;
53+
bottom: 0;
54+
z-index: 110;
55+
width: min(80vw, 320px);
56+
max-width: min(80vw, 320px);
57+
background: var(--color-background);
58+
border-right: 1px solid var(--color-border);
59+
padding: 0.75rem;
60+
overflow-y: auto;
61+
box-sizing: border-box;
62+
transition: transform 0.25s ease-in-out;
63+
}
64+
4965
.app-nav.mobile-hidden {
5066
transform: translateX(-100%);
5167
transition: transform 0.25s ease-in-out;
@@ -59,4 +75,6 @@
5975

6076
.app-nav.mobile-visible {
6177
transform: translateX(0);
78+
display: block;
79+
visibility: visible;
6280
}

src/mainPage/menu.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ type MenuItem = {
1010

1111
const ensureMenuSkeleton = () => {
1212
const root = document.querySelector('[role="main"]') || document.body
13+
const headerHost = document.getElementById('mainSolidUiHeader') || document.querySelector('solid-ui-header') || document.getElementById('PageHeader')
1314

1415
let navMenu = document.getElementById('NavMenu') as HTMLElement | null
1516
if (!navMenu) {
@@ -39,6 +40,12 @@ const ensureMenuSkeleton = () => {
3940
toggle.type = 'button'
4041
toggle.setAttribute('aria-label', 'Toggle navigation menu')
4142
toggle.textContent = '\u2630'
43+
}
44+
45+
toggle.slot = 'navigation-toggle'
46+
if (headerHost && toggle.parentElement !== headerHost) {
47+
headerHost.appendChild(toggle)
48+
} else if (!headerHost && toggle.parentElement !== root) {
4249
root.insertBefore(toggle, root.firstChild)
4350
}
4451

@@ -101,6 +108,42 @@ const renderMenuItems = async (outliner: OutlineManager, container: HTMLElement)
101108
container.replaceChildren(...menuItems.map(createMenuButton))
102109
}
103110

111+
const applyMobileMenuStyles = (navMenu: HTMLElement, isOpen: boolean) => {
112+
navMenu.hidden = false
113+
navMenu.style.position = 'fixed'
114+
navMenu.style.top = 'var(--app-header-height, 4.5rem)'
115+
navMenu.style.left = '0'
116+
navMenu.style.bottom = '0'
117+
navMenu.style.width = 'min(80vw, 320px)'
118+
navMenu.style.maxWidth = 'min(80vw, 320px)'
119+
navMenu.style.zIndex = '110'
120+
navMenu.style.display = 'block'
121+
navMenu.style.visibility = 'visible'
122+
navMenu.style.overflowY = 'auto'
123+
navMenu.style.background = 'var(--color-background)'
124+
navMenu.style.borderRight = '1px solid var(--color-border)'
125+
navMenu.style.boxShadow = '0 0.75rem 2rem rgba(0, 0, 0, 0.2)'
126+
navMenu.style.transform = isOpen ? 'translateX(0)' : 'translateX(-100%)'
127+
}
128+
129+
const clearDesktopMenuStyles = (navMenu: HTMLElement) => {
130+
navMenu.hidden = false
131+
navMenu.style.position = ''
132+
navMenu.style.top = ''
133+
navMenu.style.left = ''
134+
navMenu.style.bottom = ''
135+
navMenu.style.width = ''
136+
navMenu.style.maxWidth = ''
137+
navMenu.style.zIndex = ''
138+
navMenu.style.display = ''
139+
navMenu.style.visibility = ''
140+
navMenu.style.overflowY = ''
141+
navMenu.style.background = ''
142+
navMenu.style.borderRight = ''
143+
navMenu.style.boxShadow = ''
144+
navMenu.style.transform = ''
145+
}
146+
104147
export const refreshMenu = (layout: 'mobile' | 'desktop') => {
105148
const navMenu = document.getElementById('NavMenu') as HTMLElement | null
106149
const toggle = document.getElementById('MenuToggleBtn') as HTMLButtonElement | null
@@ -111,15 +154,15 @@ export const refreshMenu = (layout: 'mobile' | 'desktop') => {
111154
if (layout === 'mobile') {
112155
navMenu.classList.add('mobile-hidden')
113156
navMenu.classList.remove('mobile-visible')
157+
applyMobileMenuStyles(navMenu, false)
114158
toggle.hidden = false
115159
overlay.hidden = true
116-
navMenu.hidden = false
117160
toggle.setAttribute('aria-expanded', 'false')
118161
} else {
119162
navMenu.classList.remove('mobile-hidden', 'mobile-visible')
163+
clearDesktopMenuStyles(navMenu)
120164
toggle.hidden = true
121165
overlay.hidden = true
122-
navMenu.hidden = false
123166
toggle.setAttribute('aria-expanded', 'false')
124167
}
125168
}
@@ -135,6 +178,7 @@ export const createLeftSideMenu = async (outliner: OutlineManager) => {
135178
if (!navMenu || !menuToggle || !menuOverlay) return
136179
navMenu.classList.remove('mobile-visible')
137180
navMenu.classList.add('mobile-hidden')
181+
applyMobileMenuStyles(navMenu, false)
138182
menuToggle.setAttribute('aria-expanded', 'false')
139183
menuOverlay.hidden = true
140184
}
@@ -143,6 +187,7 @@ export const createLeftSideMenu = async (outliner: OutlineManager) => {
143187
if (!navMenu || !menuToggle || !menuOverlay) return
144188
navMenu.classList.remove('mobile-hidden')
145189
navMenu.classList.add('mobile-visible')
190+
applyMobileMenuStyles(navMenu, true)
146191
menuToggle.setAttribute('aria-expanded', 'true')
147192
menuOverlay.hidden = false
148193
}
@@ -184,6 +229,8 @@ export const createLeftSideMenu = async (outliner: OutlineManager) => {
184229
}
185230
})
186231
}
232+
233+
refreshMenu(outliner.context?.environment?.layout === 'mobile' ? 'mobile' : 'desktop')
187234
}
188235

189236
async function openDashboardPane (outliner: any, pane: string): Promise<void> {

src/outline/manager.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ export default function (context) {
5454
if (envLayout === 'mobile' || envLayout === 'desktop') return envLayout
5555

5656
if (typeof window !== 'undefined' && window.matchMedia) {
57-
return window.matchMedia('(max-width: 768px)').matches ? 'mobile' : 'desktop'
57+
const viewportWidth = Math.round(Math.min(window.innerWidth, window.visualViewport?.width || window.innerWidth))
58+
const isTouchInput = window.matchMedia('(pointer: coarse)').matches || navigator.maxTouchPoints > 0
59+
60+
return viewportWidth <= 768 || (isTouchInput && viewportWidth <= 1024) ? 'mobile' : 'desktop'
5861
}
5962

6063
return 'desktop'
@@ -476,10 +479,21 @@ export default function (context) {
476479
async function showDashboard (options = {}) {
477480
const dashboardContainer = getDashboardContainer()
478481
const outlineContainer = getOutlineContainer()
482+
483+
function showContainer (container) {
484+
container.removeAttribute('hidden')
485+
container.style.display = ''
486+
}
487+
488+
function hideContainer (container) {
489+
container.setAttribute('hidden', '')
490+
container.style.display = 'none'
491+
}
492+
479493
// reuse dashboard if children already inserted
480494
if (dashboardContainer.childNodes.length > 0 && options.pane) {
481-
outlineContainer.setAttribute('hidden', '')
482-
dashboardContainer.removeAttribute('hidden')
495+
hideContainer(outlineContainer)
496+
showContainer(dashboardContainer)
483497
const tab = dashboardContainer.querySelector(
484498
`[data-global-pane-name="${options.pane}"]`
485499
)
@@ -502,8 +516,8 @@ export default function (context) {
502516
authSession.events.on('logout', closeDashboard)
503517

504518
// finally - switch to showing dashboard
505-
outlineContainer.setAttribute('hidden', '')
506-
dashboardContainer.removeAttribute('hidden')
519+
hideContainer(outlineContainer)
520+
showContainer(dashboardContainer)
507521
dashboardContainer.appendChild(dashboard)
508522
const tab = dashboardContainer.querySelector(
509523
`[data-global-pane-name="${options.pane}"]`
@@ -513,8 +527,8 @@ export default function (context) {
513527
}
514528

515529
function closeDashboard () {
516-
dashboardContainer.setAttribute('hidden', '')
517-
outlineContainer.removeAttribute('hidden')
530+
hideContainer(dashboardContainer)
531+
showContainer(outlineContainer)
518532
}
519533
}
520534
this.showDashboard = showDashboard

0 commit comments

Comments
 (0)