feat: add task-manager workspace layout
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
const region = document.getElementById("workspace-region");
|
||||
const navigation = document.getElementById("workspace-navigation");
|
||||
const navigationItems = document.getElementById("workspace-nav-items");
|
||||
const toggle = document.getElementById("workspace-nav-toggle");
|
||||
const toggleLabel = toggle && toggle.querySelector(".workspace-nav-toggle-label");
|
||||
const stockTab = document.getElementById("workspace-stock-tab");
|
||||
const catalogTab = document.getElementById("workspace-catalog-tab");
|
||||
const stockWorkspace = document.getElementById("stock-workspace");
|
||||
const catalogWorkspace = document.getElementById("catalog-workspace");
|
||||
const marketTabs = document.getElementById("market-tabs");
|
||||
const title = document.getElementById("workspace-title");
|
||||
|
||||
if (!region || !navigation || !navigationItems || !toggle || !toggleLabel ||
|
||||
!stockTab || !catalogTab || !stockWorkspace || !catalogWorkspace ||
|
||||
!marketTabs || !title) {
|
||||
return;
|
||||
}
|
||||
|
||||
const views = Object.freeze({
|
||||
stock: Object.freeze({ tab: stockTab, view: stockWorkspace, title: "종목·컷" }),
|
||||
catalog: Object.freeze({ tab: catalogTab, view: catalogWorkspace, title: "기타 그래픽" })
|
||||
});
|
||||
|
||||
function setNavigationExpanded(expanded) {
|
||||
const isExpanded = expanded === true;
|
||||
region.classList.toggle("nav-collapsed", !isExpanded);
|
||||
toggle.setAttribute("aria-expanded", isExpanded ? "true" : "false");
|
||||
toggle.setAttribute("aria-label", isExpanded ? "작업 메뉴 접기" : "작업 메뉴 펼치기");
|
||||
toggle.title = isExpanded ? "메뉴 접기" : "메뉴 펼치기";
|
||||
toggleLabel.textContent = isExpanded ? "메뉴 접기" : "메뉴 펼치기";
|
||||
}
|
||||
|
||||
function setWorkspace(name) {
|
||||
const selected = views[name];
|
||||
if (!selected) return false;
|
||||
|
||||
const currentFocus = document.activeElement;
|
||||
const focusWillBeHidden = Object.keys(views).some(function (key) {
|
||||
return key !== name && views[key].view.contains(currentFocus);
|
||||
});
|
||||
if (focusWillBeHidden) selected.tab.focus();
|
||||
|
||||
Object.keys(views).forEach(function (key) {
|
||||
const entry = views[key];
|
||||
const isCurrent = key === name;
|
||||
entry.tab.classList.toggle("workspace-current", isCurrent);
|
||||
entry.tab.setAttribute("aria-current", isCurrent ? "page" : "false");
|
||||
entry.view.hidden = !isCurrent;
|
||||
entry.view.toggleAttribute("inert", !isCurrent);
|
||||
entry.view.setAttribute("aria-hidden", isCurrent ? "false" : "true");
|
||||
});
|
||||
|
||||
region.dataset.activeWorkspace = name;
|
||||
title.textContent = selected.title;
|
||||
return true;
|
||||
}
|
||||
|
||||
function focusAdjacentItem(direction) {
|
||||
const items = [stockTab, catalogTab].filter(function (button) {
|
||||
return button.disabled !== true;
|
||||
});
|
||||
const currentIndex = items.indexOf(document.activeElement);
|
||||
const nextIndex = currentIndex < 0
|
||||
? 0
|
||||
: (currentIndex + direction + items.length) % items.length;
|
||||
items[nextIndex].focus();
|
||||
}
|
||||
|
||||
toggle.addEventListener("click", function () {
|
||||
setNavigationExpanded(toggle.getAttribute("aria-expanded") !== "true");
|
||||
});
|
||||
stockTab.addEventListener("click", function () { setWorkspace("stock"); });
|
||||
catalogTab.addEventListener("click", function () { setWorkspace("catalog"); });
|
||||
|
||||
navigationItems.addEventListener("keydown", function (event) {
|
||||
const menuButton = event.target.closest && event.target.closest(".workspace-nav-item");
|
||||
if ((event.key === "Enter" || event.key === " ") && menuButton) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setWorkspace(menuButton === stockTab ? "stock" : "catalog");
|
||||
return;
|
||||
}
|
||||
if (event.key !== "ArrowUp" && event.key !== "ArrowDown") return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
focusAdjacentItem(event.key === "ArrowUp" ? -1 : 1);
|
||||
});
|
||||
|
||||
// A market tab can also be activated by automation or accessibility tools.
|
||||
// Reveal its owning workspace before app.js dispatches the native select-tab intent.
|
||||
marketTabs.addEventListener("click", function (event) {
|
||||
if (event.target.closest("button[data-tab-id]")) setWorkspace("catalog");
|
||||
}, true);
|
||||
|
||||
setNavigationExpanded(true);
|
||||
setWorkspace("stock");
|
||||
|
||||
window.LegacyWorkspaceNavigation = Object.freeze({
|
||||
select: setWorkspace,
|
||||
setExpanded: setNavigationExpanded,
|
||||
active: function () { return region.dataset.activeWorkspace; },
|
||||
expanded: function () { return toggle.getAttribute("aria-expanded") === "true"; }
|
||||
});
|
||||
}());
|
||||
Reference in New Issue
Block a user