@onsvisual/svelte-components 1.1.43 → 1.1.45
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.
|
@@ -25,6 +25,19 @@
|
|
|
25
25
|
|
|
26
26
|
<Story name="Compact with page title" args={{ compact: true, title: "Page title" }} />
|
|
27
27
|
|
|
28
|
+
<Story
|
|
29
|
+
name="Compact with page title and nav links"
|
|
30
|
+
args={{
|
|
31
|
+
compact: true,
|
|
32
|
+
title: "Page title",
|
|
33
|
+
navLinks: [
|
|
34
|
+
{ label: "Home", href: "" },
|
|
35
|
+
{ label: "Some page", href: "#0" },
|
|
36
|
+
{ label: "Another page", href: "#1" }
|
|
37
|
+
]
|
|
38
|
+
}}
|
|
39
|
+
/>
|
|
40
|
+
|
|
28
41
|
<Story name="Compact dark theme" args={{ compact: true, title: "Page title", theme: "dark" }} />
|
|
29
42
|
|
|
30
43
|
<Story name="Legacy header" args={{ legacy: true }} />
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { onMount, getContext } from "svelte";
|
|
3
|
+
import initNav from "./nav.js";
|
|
3
4
|
import Theme from "../Theme/Theme.svelte";
|
|
4
5
|
import Container from "../Container/Container.svelte";
|
|
5
6
|
import SkipLink from "../SkipLink/SkipLink.svelte";
|
|
@@ -7,8 +8,6 @@
|
|
|
7
8
|
import HeaderNavCompact from "./HeaderNavCompact.svelte";
|
|
8
9
|
import HeaderNavLegacy from "./HeaderNavLegacy.svelte";
|
|
9
10
|
|
|
10
|
-
const page = getContext("page");
|
|
11
|
-
|
|
12
11
|
/**
|
|
13
12
|
* Optional product title
|
|
14
13
|
* @type {string|null}
|
|
@@ -64,25 +63,43 @@
|
|
|
64
63
|
* @type {boolean}
|
|
65
64
|
*/
|
|
66
65
|
export let legacy = false;
|
|
66
|
+
/**
|
|
67
|
+
* Optional: Pass the "page" store from "$app/state" in SvelteKit (gets read from context by default if it exists)
|
|
68
|
+
* @type {any}
|
|
69
|
+
*/
|
|
70
|
+
export let page = getContext("page");
|
|
67
71
|
/**
|
|
68
72
|
* Anchor link to skip to main body content (default "#main")
|
|
69
73
|
* @type {string|null}
|
|
70
74
|
*/
|
|
71
75
|
export let skipHref = "#main";
|
|
76
|
+
/**
|
|
77
|
+
* Optional: Nav links below title (only works in combination with title block). An array of links in the format {label, href}
|
|
78
|
+
* @type {{label: string, href: string}[]|null}
|
|
79
|
+
*/
|
|
80
|
+
export let navLinks = null;
|
|
72
81
|
|
|
82
|
+
let el; // Header HTML element
|
|
83
|
+
|
|
84
|
+
let url = null;
|
|
73
85
|
let lang = "en";
|
|
74
86
|
let baseurl = "https://www.ons.gov.uk";
|
|
75
87
|
let baseother = "https://cy.ons.gov.uk";
|
|
76
88
|
let path = "";
|
|
77
89
|
|
|
78
90
|
function setPaths() {
|
|
79
|
-
|
|
91
|
+
url = page?.url || document.location;
|
|
80
92
|
lang = url.host.startsWith("cy") ? "cy" : "en";
|
|
81
93
|
baseurl = lang === "cy" ? "https://cy.ons.gov.uk" : "https://www.ons.gov.uk";
|
|
82
94
|
baseother = lang === "cy" ? "https://www.ons.gov.uk" : "https://cy.ons.gov.uk";
|
|
83
95
|
path = url.pathname;
|
|
84
96
|
}
|
|
85
97
|
|
|
98
|
+
function getActiveLink(navLinks, path) {
|
|
99
|
+
const candidates = navLinks.filter((link) => path.endsWith(link.href));
|
|
100
|
+
return candidates.length ? candidates[candidates.length - 1] : null;
|
|
101
|
+
}
|
|
102
|
+
|
|
86
103
|
const texts = {
|
|
87
104
|
Home: "Hafan",
|
|
88
105
|
Search: "Chwilio",
|
|
@@ -99,9 +116,19 @@
|
|
|
99
116
|
};
|
|
100
117
|
|
|
101
118
|
$: i18n = (text) => (lang === "cy" && texts[text] ? texts[text] : text);
|
|
119
|
+
$: activeLink =
|
|
120
|
+
Array.isArray(navLinks) && url?.pathname ? getActiveLink(navLinks, url.pathname) : null;
|
|
102
121
|
|
|
103
122
|
onMount(() => {
|
|
104
123
|
setPaths();
|
|
124
|
+
|
|
125
|
+
if ((!compact && !legacy) || (title && Array.isArray(navLinks))) {
|
|
126
|
+
const hasBodyClass = "className" in document.body || {};
|
|
127
|
+
const bodyClassString = document.body?.className || "";
|
|
128
|
+
if (hasBodyClass && !bodyClassString.includes("ons-js-enabled"))
|
|
129
|
+
document.body.className = bodyClassString + " ons-js-enabled";
|
|
130
|
+
initNav(el?.parentElement || document);
|
|
131
|
+
}
|
|
105
132
|
});
|
|
106
133
|
</script>
|
|
107
134
|
|
|
@@ -110,6 +137,7 @@
|
|
|
110
137
|
class:ons-header--basic={!compact && !legacy}
|
|
111
138
|
class:ons-header__full={width === "full"}
|
|
112
139
|
role="banner"
|
|
140
|
+
bind:this={el}
|
|
113
141
|
>
|
|
114
142
|
{#if skipHref}
|
|
115
143
|
<SkipLink href={skipHref} />
|
|
@@ -166,9 +194,60 @@
|
|
|
166
194
|
<div class="ons-header__title">{title}</div>
|
|
167
195
|
{/if}
|
|
168
196
|
</div>
|
|
197
|
+
{#if Array.isArray(navLinks)}
|
|
198
|
+
<div class="ons-grid__col ons-col-auto ons-u-flex-no-shrink ons-u-d-no@l">
|
|
199
|
+
<button
|
|
200
|
+
type="submit"
|
|
201
|
+
class="ons-btn ons-u-ml-2xs ons-u-d-no ons-js-navigation-button ons-u-d-no@l ons-btn--mobile ons-btn--ghost"
|
|
202
|
+
aria-label="Toggle main menu"
|
|
203
|
+
aria-controls="main-nav"
|
|
204
|
+
aria-expanded="false"
|
|
205
|
+
>
|
|
206
|
+
<span class="ons-btn__inner"
|
|
207
|
+
><span class="ons-btn__text">Menu</span><svg
|
|
208
|
+
class="ons-icon ons-u-ml-2xs"
|
|
209
|
+
viewBox="0 0 8 13"
|
|
210
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
211
|
+
focusable="false"
|
|
212
|
+
fill="currentColor"
|
|
213
|
+
role="img"
|
|
214
|
+
aria-hidden="true"
|
|
215
|
+
>
|
|
216
|
+
<path
|
|
217
|
+
d="M5.74,14.28l-.57-.56a.5.5,0,0,1,0-.71h0l5-5-5-5a.5.5,0,0,1,0-.71h0l.57-.56a.5.5,0,0,1,.71,0h0l5.93,5.93a.5.5,0,0,1,0,.7L6.45,14.28a.5.5,0,0,1-.71,0Z"
|
|
218
|
+
transform="translate(-5.02 -1.59)"
|
|
219
|
+
/>
|
|
220
|
+
</svg></span
|
|
221
|
+
>
|
|
222
|
+
</button>
|
|
223
|
+
</div>
|
|
224
|
+
{/if}
|
|
169
225
|
</div>
|
|
170
226
|
</Container>
|
|
171
227
|
</div>
|
|
228
|
+
{#if Array.isArray(navLinks)}
|
|
229
|
+
<div class="ons-navigation-wrapper">
|
|
230
|
+
<Container {width}>
|
|
231
|
+
<nav
|
|
232
|
+
class="ons-navigation ons-navigation--main ons-js-navigation"
|
|
233
|
+
id="main-nav"
|
|
234
|
+
aria-label="Main menu"
|
|
235
|
+
data-analytics="header-navigation"
|
|
236
|
+
>
|
|
237
|
+
<ul class="ons-navigation__list">
|
|
238
|
+
{#each navLinks as link (link.href)}
|
|
239
|
+
<li
|
|
240
|
+
class="ons-navigation__item"
|
|
241
|
+
class:ons-navigation__item--active={activeLink?.href === link.href}
|
|
242
|
+
>
|
|
243
|
+
<a class="ons-navigation__link" href={link.href}> {link.label} </a>
|
|
244
|
+
</li>
|
|
245
|
+
{/each}
|
|
246
|
+
</ul>
|
|
247
|
+
</nav>
|
|
248
|
+
</Container>
|
|
249
|
+
</div>
|
|
250
|
+
{/if}
|
|
172
251
|
{/if}
|
|
173
252
|
</Theme>
|
|
174
253
|
</header>
|
|
@@ -9,11 +9,16 @@ export default class Header extends SvelteComponentTyped<{
|
|
|
9
9
|
title?: string | null | undefined;
|
|
10
10
|
skipHref?: string | null | undefined;
|
|
11
11
|
compact?: boolean | undefined;
|
|
12
|
+
page?: any;
|
|
12
13
|
headerBorder?: boolean | undefined;
|
|
13
14
|
menuBorder?: boolean | undefined;
|
|
14
15
|
bilingual?: boolean | undefined;
|
|
15
16
|
titleHref?: string | null | undefined;
|
|
16
17
|
legacy?: boolean | undefined;
|
|
18
|
+
navLinks?: {
|
|
19
|
+
label: string;
|
|
20
|
+
href: string;
|
|
21
|
+
}[] | null | undefined;
|
|
17
22
|
}, {
|
|
18
23
|
[evt: string]: CustomEvent<any>;
|
|
19
24
|
}, {
|
|
@@ -33,11 +38,16 @@ declare const __propDef: {
|
|
|
33
38
|
title?: string | null | undefined;
|
|
34
39
|
skipHref?: string | null | undefined;
|
|
35
40
|
compact?: boolean | undefined;
|
|
41
|
+
page?: any;
|
|
36
42
|
headerBorder?: boolean | undefined;
|
|
37
43
|
menuBorder?: boolean | undefined;
|
|
38
44
|
bilingual?: boolean | undefined;
|
|
39
45
|
titleHref?: string | null | undefined;
|
|
40
46
|
legacy?: boolean | undefined;
|
|
47
|
+
navLinks?: {
|
|
48
|
+
label: string;
|
|
49
|
+
href: string;
|
|
50
|
+
}[] | null | undefined;
|
|
41
51
|
};
|
|
42
52
|
events: {
|
|
43
53
|
[evt: string]: CustomEvent<any>;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { onMount } from "svelte";
|
|
3
2
|
import Container from "../Container/Container.svelte";
|
|
4
|
-
import initNav from "./nav.js";
|
|
5
3
|
|
|
6
4
|
export let width = "wide";
|
|
7
5
|
export let headerBorder = false;
|
|
@@ -14,8 +12,6 @@
|
|
|
14
12
|
export let path = "";
|
|
15
13
|
export let i18n = (text) => text;
|
|
16
14
|
|
|
17
|
-
let el; // Header HTML element
|
|
18
|
-
|
|
19
15
|
const menu = {
|
|
20
16
|
main: [
|
|
21
17
|
{
|
|
@@ -239,17 +235,9 @@
|
|
|
239
235
|
]
|
|
240
236
|
};
|
|
241
237
|
const columns = [[menu.topics[0]], [menu.topics[1], menu.topics[2]], [menu.topics[3]]];
|
|
242
|
-
|
|
243
|
-
onMount(() => {
|
|
244
|
-
const hasBodyClass = "className" in document.body || {};
|
|
245
|
-
const bodyClassString = document.body?.className || "";
|
|
246
|
-
if (hasBodyClass && !bodyClassString.includes("ons-js-enabled"))
|
|
247
|
-
document.body.className = bodyClassString + " ons-js-enabled";
|
|
248
|
-
initNav(el?.parentElement || document);
|
|
249
|
-
});
|
|
250
238
|
</script>
|
|
251
239
|
|
|
252
|
-
<div class="ons-header__top" class:ons-header--border={headerBorder}
|
|
240
|
+
<div class="ons-header__top" class:ons-header--border={headerBorder}>
|
|
253
241
|
<Container {width}>
|
|
254
242
|
<div
|
|
255
243
|
class="ons-header__grid-top ons-grid ons-grid-flex ons-grid-flex--between ons-grid-flex--vertical-center ons-grid-flex--no-wrap ons-grid--gutterless"
|