95 lines
2.4 KiB
TypeScript
95 lines
2.4 KiB
TypeScript
import {
|
|
NavigationGroup,
|
|
NavigationItem,
|
|
NavigationMenuProps,
|
|
} from "./welcome-types.ts";
|
|
import {
|
|
getNavigationGroups,
|
|
isNavigationItemActive,
|
|
} from "./navigationConfig.ts";
|
|
|
|
/**
|
|
* NavigationMenu Component
|
|
* Native-rendered dropdown content for <details> menu.
|
|
*/
|
|
export default function NavigationMenu(
|
|
{ isLoggedIn, currentRoute, navigationGroups }: NavigationMenuProps,
|
|
) {
|
|
function getItemStateClass(item: NavigationItem): string {
|
|
if (item.disabled) return "navigation-menu-item--disabled";
|
|
if (item.path === "/auth/logout") return "navigation-menu-item--logout";
|
|
if (item.path === "/auth/login") return "navigation-menu-item--login";
|
|
return "navigation-menu-item--default";
|
|
}
|
|
|
|
function renderNavigationItem(item: NavigationItem) {
|
|
if (!item.isForm && isNavigationItemActive(item, currentRoute)) {
|
|
return null;
|
|
}
|
|
|
|
const itemClass = `navigation-menu-item ${getItemStateClass(item)}`;
|
|
|
|
if (item.isForm && item.formAction) {
|
|
return (
|
|
<form method={item.formMethod || "post"} action={item.formAction}>
|
|
<button
|
|
type="submit"
|
|
onClick={item.onClick}
|
|
class={itemClass}
|
|
role="menuitem"
|
|
disabled={item.disabled}
|
|
>
|
|
{item.label}
|
|
</button>
|
|
</form>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<a
|
|
href={item.path}
|
|
class={itemClass}
|
|
role="menuitem"
|
|
aria-disabled={item.disabled}
|
|
>
|
|
{item.label}
|
|
</a>
|
|
);
|
|
}
|
|
|
|
function renderNavigationGroup(group: NavigationGroup) {
|
|
if (group.items.length === 0) return null;
|
|
|
|
return (
|
|
<div key={group.id} class="navigation-menu-group">
|
|
{group.id !== "auth" && <div class="navigation-menu-separator" />}
|
|
<p class="navigation-menu-group-label">{group.label}</p>
|
|
{group.items.map(renderNavigationItem)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const groups = getNavigationGroups(
|
|
isLoggedIn,
|
|
currentRoute,
|
|
navigationGroups,
|
|
);
|
|
|
|
if (groups.length === 0) {
|
|
return (
|
|
<div class="navigation-menu" role="menu" aria-label="Navigation menu">
|
|
<div class="navigation-menu-group">
|
|
<p class="navigation-menu-group-label">Navigation</p>
|
|
<p class="navigation-menu-empty">No actions available</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div class="navigation-menu" role="menu" aria-label="Navigation menu">
|
|
{groups.map(renderNavigationGroup)}
|
|
</div>
|
|
);
|
|
}
|