Enhance AppLauncherOverlay and navigation logic for improved user experience
- Added functionality to close the overlay and return focus to the launcher when the Escape key is pressed inside an iframe. - Implemented message handling to close the app launcher from the parent window. - Updated navigation logic in useControllerNav to improve focus management when navigating between sidebar and main content. - Enhanced Dashboard and Settings views with data attributes for better controller navigation support.
This commit is contained in:
@@ -266,10 +266,25 @@ export function useControllerNav(containerRef?: { value: HTMLElement | null }) {
|
||||
const mainEls = getElementsInZone('main')
|
||||
const hasZones = sidebarEls.length > 0 && mainEls.length > 0
|
||||
|
||||
// Right: from sidebar → main (on App Store/My Apps, go straight to first app container)
|
||||
// Right: from sidebar → main
|
||||
// - On Apps/Marketplace: go to first app container
|
||||
// - On Cloud: go to first folder (Pictures)
|
||||
// - On Network (server): go to Services container
|
||||
// - On Web5: go to Networking Profits container
|
||||
// - On Settings: go to Change Password container
|
||||
// - Otherwise: go to top right (App Switcher)
|
||||
const mainZone = document.querySelector('[data-controller-zone="main"]')
|
||||
const isAppsOrMarketplace = /^\/dashboard\/(apps|marketplace)(\/|$)/.test(route.path)
|
||||
const isCloud = /^\/dashboard\/cloud(\/|$)/.test(route.path)
|
||||
const isNetwork = /^\/dashboard\/server(\/|$)/.test(route.path)
|
||||
const isWeb5 = /^\/dashboard\/web5(\/|$)/.test(route.path)
|
||||
const isSettings = /^\/dashboard\/settings(\/|$)/.test(route.path)
|
||||
const firstAppContainer = mainZone?.querySelector<HTMLElement>('[data-controller-container]')
|
||||
const firstMain = firstAppContainer ?? mainEls[0]
|
||||
const topRightEntry = mainZone?.querySelector<HTMLElement>('[data-controller-main-entry]')
|
||||
const firstFocusableInTopRight = topRightEntry ? getFocusableElements(topRightEntry)[0] : null
|
||||
const firstMain = ((isAppsOrMarketplace || isCloud || isNetwork || isWeb5 || isSettings) && firstAppContainer)
|
||||
? firstAppContainer
|
||||
: (firstFocusableInTopRight ?? mainEls[0])
|
||||
if (e.key === 'ArrowRight' && hasZones && isInZone(activeEl, 'sidebar') && firstMain) {
|
||||
playNavSound('move')
|
||||
firstMain.focus()
|
||||
@@ -323,12 +338,17 @@ export function useControllerNav(containerRef?: { value: HTMLElement | null }) {
|
||||
}
|
||||
}
|
||||
|
||||
// Sidebar: linear up/down
|
||||
// Sidebar: linear up/down with wrap (Home+Up→Logout, Logout+Down→Home)
|
||||
if (isInZone(activeEl, 'sidebar')) {
|
||||
const idx = sidebarEls.indexOf(activeEl)
|
||||
if (idx >= 0) {
|
||||
const isDown = e.key === 'ArrowDown'
|
||||
const nextIdx = isDown ? Math.min(idx + 1, sidebarEls.length - 1) : Math.max(idx - 1, 0)
|
||||
let nextIdx: number
|
||||
if (isDown) {
|
||||
nextIdx = idx >= sidebarEls.length - 1 ? 0 : idx + 1
|
||||
} else {
|
||||
nextIdx = idx <= 0 ? sidebarEls.length - 1 : idx - 1
|
||||
}
|
||||
const next = sidebarEls[nextIdx]
|
||||
if (next && next !== activeEl) {
|
||||
playNavSound('move')
|
||||
|
||||
Reference in New Issue
Block a user