@defra/docusaurus-theme-govuk 0.0.6-alpha → 0.0.7-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import '../../css/theme.scss';
|
|
3
|
-
import {SkipLink, Header, Footer, PhaseBanner, ServiceNavigation
|
|
3
|
+
import {SkipLink, Header, Footer, PhaseBanner, ServiceNavigation} from '@not-govuk/simple-components';
|
|
4
4
|
import SidebarNav from '../SidebarNav';
|
|
5
5
|
import {useLocation} from '@docusaurus/router';
|
|
6
6
|
import Head from '@docusaurus/Head';
|
|
@@ -141,11 +141,6 @@ export default function Layout(props) {
|
|
|
141
141
|
}))
|
|
142
142
|
: null;
|
|
143
143
|
|
|
144
|
-
// Anchor-based sidebars (auto-generated) use a hash-aware component.
|
|
145
|
-
// Page-based sidebars (manually configured arrays) use NavigationMenu which
|
|
146
|
-
// uses React Router's active detection for sub-page expansion.
|
|
147
|
-
const isAnchorSidebar = effectiveSidebar?._auto === true;
|
|
148
|
-
|
|
149
144
|
// Convert navigation to service navigation format (Level 1 only)
|
|
150
145
|
const serviceNavItems = navigation.map(item => ({
|
|
151
146
|
href: withBase(item.href),
|
|
@@ -198,9 +193,7 @@ export default function Layout(props) {
|
|
|
198
193
|
{sidebarItems ? (
|
|
199
194
|
<div className="app-layout-sidebar">
|
|
200
195
|
<aside className="app-layout-sidebar__nav">
|
|
201
|
-
{
|
|
202
|
-
? <SidebarNav items={sidebarItems} />
|
|
203
|
-
: <NavigationMenu items={sidebarItems} />}
|
|
196
|
+
<SidebarNav items={sidebarItems} />
|
|
204
197
|
</aside>
|
|
205
198
|
<div className="app-layout-sidebar__content">
|
|
206
199
|
{children}
|
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { useLocation } from '@docusaurus/router';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
|
-
* Hash-aware sidebar navigation
|
|
5
|
+
* Hash- and pathname-aware sidebar navigation.
|
|
6
|
+
*
|
|
7
|
+
* Works for both anchor-based (auto-generated) and page-based (manual) sidebars.
|
|
5
8
|
*
|
|
6
9
|
* SSR / no-JS: all groups are rendered expanded so content is accessible.
|
|
7
|
-
* CSR after hydration:
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
10
|
+
* CSR after hydration:
|
|
11
|
+
* - Anchor hrefs (e.g. /api#constructor): active when pathname AND hash both match
|
|
12
|
+
* - Page hrefs (e.g. /building-a-plugin): active when pathname matches
|
|
13
|
+
* - Groups expand when the group itself or any child is active
|
|
11
14
|
*
|
|
12
15
|
* State sentinel:
|
|
13
|
-
* null
|
|
14
|
-
*
|
|
15
|
-
* str = JS loaded, hash present → expand matching group only
|
|
16
|
+
* null = not yet hydrated → expand all groups (SSR safe)
|
|
17
|
+
* str = JS loaded (empty string means no hash present)
|
|
16
18
|
*/
|
|
17
19
|
export default function SidebarNav({ items }) {
|
|
18
20
|
const [hash, setHash] = useState(null);
|
|
21
|
+
const location = useLocation();
|
|
19
22
|
|
|
20
23
|
useEffect(() => {
|
|
21
24
|
const update = () => setHash(window.location.hash.slice(1));
|
|
@@ -24,6 +27,28 @@ export default function SidebarNav({ items }) {
|
|
|
24
27
|
return () => window.removeEventListener('hashchange', update);
|
|
25
28
|
}, []);
|
|
26
29
|
|
|
30
|
+
// Split an href into its path and anchor components.
|
|
31
|
+
function parseHref(href) {
|
|
32
|
+
if (!href) return { path: '', anchor: '' };
|
|
33
|
+
const idx = href.indexOf('#');
|
|
34
|
+
if (idx === -1) return { path: href, anchor: '' };
|
|
35
|
+
return { path: href.slice(0, idx) || '/', anchor: href.slice(idx + 1) };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Return true if the given href matches the current browser location.
|
|
39
|
+
// Anchor hrefs: both pathname and hash must match.
|
|
40
|
+
// Page hrefs: pathname match is sufficient (exact or child path).
|
|
41
|
+
function isActive(href) {
|
|
42
|
+
const { path, anchor } = parseHref(href);
|
|
43
|
+
if (anchor) {
|
|
44
|
+
return location.pathname === path && hash === anchor;
|
|
45
|
+
}
|
|
46
|
+
return (
|
|
47
|
+
path !== '' &&
|
|
48
|
+
(location.pathname === path || location.pathname.startsWith(path + '/'))
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
27
52
|
const cls = 'not-govuk-navigation-menu';
|
|
28
53
|
const lCls = `${cls}__list`;
|
|
29
54
|
|
|
@@ -31,23 +56,16 @@ export default function SidebarNav({ items }) {
|
|
|
31
56
|
<nav className={cls}>
|
|
32
57
|
<ul className={lCls}>
|
|
33
58
|
{items.map((item, i) => {
|
|
34
|
-
const anchor = item.href ? (item.href.split('#')[1] ?? '') : '';
|
|
35
59
|
const hasChildren = Array.isArray(item.items) && item.items.length > 0;
|
|
36
|
-
const childAnchors = hasChildren
|
|
37
|
-
? item.items.map(sub => sub.href ? (sub.href.split('#')[1] ?? '') : '')
|
|
38
|
-
: [];
|
|
39
60
|
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
childAnchors.includes(hash)
|
|
47
|
-
);
|
|
61
|
+
// Pre-hydration (hash === null): expand everything so content is
|
|
62
|
+
// accessible without JS. After hydration: expand only if this group
|
|
63
|
+
// or one of its children is the active location.
|
|
64
|
+
const expanded =
|
|
65
|
+
hasChildren &&
|
|
66
|
+
(hash === null || isActive(item.href) || item.items.some(sub => isActive(sub.href)));
|
|
48
67
|
|
|
49
|
-
const
|
|
50
|
-
const active = hash !== null && hashMatchesGroup;
|
|
68
|
+
const active = hash !== null && isActive(item.href);
|
|
51
69
|
|
|
52
70
|
return (
|
|
53
71
|
<li
|
|
@@ -60,8 +78,7 @@ export default function SidebarNav({ items }) {
|
|
|
60
78
|
{expanded && (
|
|
61
79
|
<ul className={`${lCls}__subitems`}>
|
|
62
80
|
{item.items.map((sub, j) => {
|
|
63
|
-
const
|
|
64
|
-
const subActive = hash !== null && hash === subAnchor;
|
|
81
|
+
const subActive = hash !== null && isActive(sub.href);
|
|
65
82
|
return (
|
|
66
83
|
<li
|
|
67
84
|
key={j}
|
|
@@ -82,3 +99,4 @@ export default function SidebarNav({ items }) {
|
|
|
82
99
|
</nav>
|
|
83
100
|
);
|
|
84
101
|
}
|
|
102
|
+
|