@financial-times/dotcom-ui-header 7.2.7 → 7.3.1
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/dist/node/components/drawer/additionalPartials.d.ts +11 -0
- package/dist/node/components/drawer/topLevelPartials.d.ts +3 -0
- package/dist/node/components/drawer/topLevelPartials.js +17 -18
- package/dist/node/components/navigation/partials.d.ts +8 -0
- package/dist/node/components/search/partials.d.ts +5 -0
- package/dist/node/components/sticky/partials.d.ts +10 -0
- package/dist/node/components/sub-navigation/partials.d.ts +4 -0
- package/dist/node/components/svg-components/BrandFtMasthead.d.ts +6 -0
- package/dist/node/components/top/partials.d.ts +24 -0
- package/dist/node/index.d.ts +38 -0
- package/dist/node/utils.d.ts +2 -0
- package/dist/tsconfig.tsbuildinfo +2124 -0
- package/package.json +10 -8
- package/screenshots/header-navigation.png +0 -0
- package/screenshots/header-sub-navigation.png +0 -0
- package/screenshots/header-top-search.png +0 -0
- package/scripts/convertSvgsToReactComponents.js +0 -23
- package/src/components/drawer/additionalPartials.tsx +0 -105
- package/src/components/drawer/topLevelPartials.tsx +0 -165
- package/src/components/navigation/partials.tsx +0 -192
- package/src/components/search/partials.tsx +0 -52
- package/src/components/sticky/partials.tsx +0 -164
- package/src/components/sub-navigation/partials.tsx +0 -106
- package/src/components/svg-components/BrandFtMasthead.tsx +0 -16
- package/src/components/top/partials.tsx +0 -189
- package/src/header.scss +0 -29
- package/src/index.tsx +0 -123
- package/src/interfaces.d.ts +0 -19
- package/src/utils.ts +0 -5
- package/styles.scss +0 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@financial-times/dotcom-ui-header",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.3.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"browser": "browser.js",
|
|
6
6
|
"main": "component.js",
|
|
@@ -8,14 +8,13 @@
|
|
|
8
8
|
"styles": "styles.scss",
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
-
"tsc": "../../node_modules/.bin/tsc --incremental",
|
|
12
11
|
"clean": "npm run clean:dist && npm run clean:node_modules",
|
|
13
12
|
"clean:dist": "rm -rf dist",
|
|
14
13
|
"clean:node_modules": "rm -rf node_modules",
|
|
15
14
|
"clean:install": "npm run clean && npm i",
|
|
16
|
-
"build": "
|
|
17
|
-
"build:node": "npm run tsc -- --module commonjs --outDir ./dist/node",
|
|
15
|
+
"build:node": "tsc",
|
|
18
16
|
"build:svg-to-react": "node scripts/convertSvgsToReactComponents.js",
|
|
17
|
+
"build": "npm run build:node",
|
|
19
18
|
"dev": "npm run build:node -- --watch",
|
|
20
19
|
"preinstall": "[ \"$INIT_CWD\" != \"$PWD\" ] || npm_config_yes=true npx check-engine"
|
|
21
20
|
},
|
|
@@ -23,7 +22,7 @@
|
|
|
23
22
|
"author": "",
|
|
24
23
|
"license": "MIT",
|
|
25
24
|
"dependencies": {
|
|
26
|
-
"@financial-times/dotcom-types-navigation": "
|
|
25
|
+
"@financial-times/dotcom-types-navigation": "file:../dotcom-types-navigation",
|
|
27
26
|
"n-topic-search": "^4.0.0",
|
|
28
27
|
"n-ui-foundations": "^9.0.0"
|
|
29
28
|
},
|
|
@@ -32,11 +31,11 @@
|
|
|
32
31
|
"@svgr/core": "^5.0.0",
|
|
33
32
|
"camelcase": "^6.0.0",
|
|
34
33
|
"check-engine": "^1.10.1",
|
|
35
|
-
"@financial-times/o-header": "^
|
|
34
|
+
"@financial-times/o-header": "^11.0.4",
|
|
36
35
|
"react": "^16.8.6"
|
|
37
36
|
},
|
|
38
37
|
"peerDependencies": {
|
|
39
|
-
"@financial-times/o-header": "^
|
|
38
|
+
"@financial-times/o-header": "^11.0.4",
|
|
40
39
|
"@financial-times/logo-images": "^1.10.1",
|
|
41
40
|
"react": "16.x || 17.x"
|
|
42
41
|
},
|
|
@@ -44,6 +43,9 @@
|
|
|
44
43
|
"node": ">= 14.0.0",
|
|
45
44
|
"npm": "7.x || 8.x"
|
|
46
45
|
},
|
|
46
|
+
"files": [
|
|
47
|
+
"dist/"
|
|
48
|
+
],
|
|
47
49
|
"repository": {
|
|
48
50
|
"type": "git",
|
|
49
51
|
"repository": "https://github.com/Financial-Times/dotcom-page-kit.git",
|
|
@@ -53,4 +55,4 @@
|
|
|
53
55
|
"volta": {
|
|
54
56
|
"extends": "../../package.json"
|
|
55
57
|
}
|
|
56
|
-
}
|
|
58
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
|
|
3
|
-
const camelCase = require('camelcase')
|
|
4
|
-
const svgr = require('@svgr/core').default
|
|
5
|
-
|
|
6
|
-
const logoNames = ['brand-ft-masthead']
|
|
7
|
-
|
|
8
|
-
logoNames.forEach((logoName) => {
|
|
9
|
-
const pathToSvg = require.resolve(`@financial-times/logo-images/src/${logoName}.svg`)
|
|
10
|
-
|
|
11
|
-
const svgString = fs.readFileSync(pathToSvg).toString()
|
|
12
|
-
|
|
13
|
-
const componentName = camelCase(logoName, { pascalCase: true })
|
|
14
|
-
|
|
15
|
-
svgr(svgString, { titleProp: true }, { componentName }).then((jsCode) => {
|
|
16
|
-
const comment =
|
|
17
|
-
'// **THIS IS AN AUTO-GENERATED FILE (`npm run build:svg-to-react`) - DO NOT EDIT MANUALLY.**\n\n'
|
|
18
|
-
|
|
19
|
-
const fileExtension = 'tsx'
|
|
20
|
-
|
|
21
|
-
fs.writeFileSync(`src/components/svg-components/${componentName}.${fileExtension}`, comment + jsCode)
|
|
22
|
-
})
|
|
23
|
-
})
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { ariaSelected } from '../../utils'
|
|
3
|
-
import { TNavMenuItem, TNavEditions, TNavAction } from '@financial-times/dotcom-types-navigation'
|
|
4
|
-
|
|
5
|
-
export type TDrawerParentItemProps = {
|
|
6
|
-
item: TNavMenuItem
|
|
7
|
-
idSuffix: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const DrawerParentItem = ({ item, idSuffix }: TDrawerParentItemProps) => {
|
|
11
|
-
const selected = item.selected ? 'selected' : 'unselected'
|
|
12
|
-
return (
|
|
13
|
-
<React.Fragment>
|
|
14
|
-
<div key={item.url} className="o-header__drawer-menu-toggle-wrapper">
|
|
15
|
-
<a
|
|
16
|
-
className={`o-header__drawer-menu-link o-header__drawer-menu-link--${selected} o-header__drawer-menu-link--parent`}
|
|
17
|
-
href={item.url ?? undefined}
|
|
18
|
-
{...ariaSelected(item)}
|
|
19
|
-
data-trackable={item.label}
|
|
20
|
-
>
|
|
21
|
-
{item.label}
|
|
22
|
-
</a>
|
|
23
|
-
<button
|
|
24
|
-
className={`o-header__drawer-menu-toggle o-header__drawer-menu-toggle--${selected}`}
|
|
25
|
-
aria-controls={`o-header-drawer-child-${idSuffix}`}
|
|
26
|
-
data-trackable={`sub-level-toggle | ${item.label}`}
|
|
27
|
-
>
|
|
28
|
-
{`Show more ${item.label}`}
|
|
29
|
-
</button>
|
|
30
|
-
</div>
|
|
31
|
-
<ul
|
|
32
|
-
className="o-header__drawer-menu-list o-header__drawer-menu-list--child"
|
|
33
|
-
id={`o-header-drawer-child-${idSuffix}`}
|
|
34
|
-
data-trackable="sub-level"
|
|
35
|
-
>
|
|
36
|
-
{(item.submenu?.items as TNavMenuItem[]).map((item) => {
|
|
37
|
-
const selected = item.selected ? 'selected' : 'unselected'
|
|
38
|
-
return (
|
|
39
|
-
<li key={item.url} className="o-header__drawer-menu-item">
|
|
40
|
-
<a
|
|
41
|
-
className={`o-header__drawer-menu-link o-header__drawer-menu-link--${selected} o-header__drawer-menu-link--child`}
|
|
42
|
-
href={item.url ?? undefined}
|
|
43
|
-
data-trackable={item.label}
|
|
44
|
-
{...ariaSelected(item)}
|
|
45
|
-
>
|
|
46
|
-
{item.label}
|
|
47
|
-
</a>
|
|
48
|
-
</li>
|
|
49
|
-
)
|
|
50
|
-
})}
|
|
51
|
-
</ul>
|
|
52
|
-
</React.Fragment>
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export const DrawerSingleItem = (item: TNavMenuItem) => {
|
|
57
|
-
const selected = item.selected ? 'selected' : 'unselected'
|
|
58
|
-
return (
|
|
59
|
-
<a
|
|
60
|
-
className={`o-header__drawer-menu-link o-header__drawer-menu-link--${selected}`}
|
|
61
|
-
href={item.url ?? undefined}
|
|
62
|
-
data-trackable={item.label}
|
|
63
|
-
{...ariaSelected(item)}
|
|
64
|
-
>
|
|
65
|
-
{item.label}
|
|
66
|
-
</a>
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export const DrawerSpecialItem = (item: TNavMenuItem) => {
|
|
71
|
-
const selected = item.selected ? 'selected' : 'unselected'
|
|
72
|
-
return (
|
|
73
|
-
<a
|
|
74
|
-
className={`o-header__drawer-menu-link o-header__drawer-menu-link--${selected} o-header__drawer-menu-link--secondary`}
|
|
75
|
-
href={item.url ?? undefined}
|
|
76
|
-
data-trackable={item.label}
|
|
77
|
-
{...ariaSelected(item)}
|
|
78
|
-
>
|
|
79
|
-
{item.label}
|
|
80
|
-
</a>
|
|
81
|
-
)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export const EditionsSwitcher = (editions: TNavEditions) => (
|
|
85
|
-
<ul className="o-header__drawer-menu-list">
|
|
86
|
-
{editions.others.map(({ id, name, url }) => {
|
|
87
|
-
const href = `${url}?edition=${id}`
|
|
88
|
-
return (
|
|
89
|
-
<li key={id} className="o-header__drawer-menu-item" data-trackable="edition-switcher">
|
|
90
|
-
<a className="o-header__drawer-menu-link" href={href} data-trackable={id}>
|
|
91
|
-
Switch to {name} Edition
|
|
92
|
-
</a>
|
|
93
|
-
</li>
|
|
94
|
-
)
|
|
95
|
-
})}
|
|
96
|
-
</ul>
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
export const SubscribeButton = (action: TNavAction) => (
|
|
100
|
-
<div className="o-header__drawer-actions">
|
|
101
|
-
<a className="o-header__drawer-button" role="button" href={action.url} data-trackable="subscribe-button">
|
|
102
|
-
{action.name}
|
|
103
|
-
</a>
|
|
104
|
-
</div>
|
|
105
|
-
)
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import {
|
|
3
|
-
DrawerParentItem,
|
|
4
|
-
DrawerSingleItem,
|
|
5
|
-
DrawerSpecialItem,
|
|
6
|
-
EditionsSwitcher,
|
|
7
|
-
SubscribeButton
|
|
8
|
-
} from './additionalPartials'
|
|
9
|
-
import { THeaderProps } from '../../interfaces'
|
|
10
|
-
import { TNavMenuItem, TNavMenu, TNavEditions } from '@financial-times/dotcom-types-navigation'
|
|
11
|
-
|
|
12
|
-
const IncludeDrawer = (props) => <Drawer {...props} />
|
|
13
|
-
|
|
14
|
-
const Drawer = (props: THeaderProps) => {
|
|
15
|
-
const editions = props.data.editions
|
|
16
|
-
const subscribeAction = props.data.subscribeAction
|
|
17
|
-
const [primary, secondary, tertiary] = props.data.drawer.items
|
|
18
|
-
const user = props.userIsLoggedIn ? props.data.user : props.data.anon
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<div
|
|
22
|
-
className="o-header__drawer"
|
|
23
|
-
id="o-header-drawer"
|
|
24
|
-
role="navigation"
|
|
25
|
-
aria-label="Drawer menu"
|
|
26
|
-
data-o-header-drawer
|
|
27
|
-
data-o-header-drawer--no-js
|
|
28
|
-
data-trackable="drawer"
|
|
29
|
-
data-trackable-terminate
|
|
30
|
-
>
|
|
31
|
-
<div className="o-header__drawer-inner">
|
|
32
|
-
<DrawerTools {...editions} />
|
|
33
|
-
{!props.userIsSubscribed && subscribeAction && <SubscribeButton {...subscribeAction} />}
|
|
34
|
-
<Search />
|
|
35
|
-
<nav className="o-header__drawer-menu o-header__drawer-menu--primary o-header__drawer-menu--border">
|
|
36
|
-
{editions && <EditionsSwitcher {...editions} />}
|
|
37
|
-
<ul data-component="drawer-menu--primary__drawer-menu-list" className="o-header__drawer-menu-list">
|
|
38
|
-
{primary ? <SectionPrimary {...primary} /> : null}
|
|
39
|
-
{secondary ? <SectionSecondary {...secondary} /> : null}
|
|
40
|
-
{tertiary ? <SectionTertiary {...tertiary} /> : null}
|
|
41
|
-
</ul>
|
|
42
|
-
</nav>
|
|
43
|
-
<UserMenu {...user} />
|
|
44
|
-
</div>
|
|
45
|
-
</div>
|
|
46
|
-
)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const DrawerTools = (props: TNavEditions) => (
|
|
50
|
-
<div className="o-header__drawer-tools">
|
|
51
|
-
<button
|
|
52
|
-
type="button"
|
|
53
|
-
className="o-header__drawer-tools-close"
|
|
54
|
-
title="Close drawer menu"
|
|
55
|
-
aria-controls="o-header-drawer"
|
|
56
|
-
data-trackable="close"
|
|
57
|
-
>
|
|
58
|
-
<span className="o-header__visually-hidden">Close drawer menu</span>
|
|
59
|
-
</button>
|
|
60
|
-
<a className="o-header__drawer-tools-logo" href="/" data-trackable="logo">
|
|
61
|
-
<span className="o-header__visually-hidden">Financial Times</span>
|
|
62
|
-
</a>
|
|
63
|
-
{props.current && <p className="o-header__drawer-current-edition">{`${props.current.name} Edition`}</p>}
|
|
64
|
-
</div>
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
const Search = () => (
|
|
68
|
-
<div className="o-header__drawer-search">
|
|
69
|
-
<form
|
|
70
|
-
className="o-header__drawer-search-form"
|
|
71
|
-
action="/search"
|
|
72
|
-
role="search"
|
|
73
|
-
aria-label="Site search"
|
|
74
|
-
data-n-topic-search
|
|
75
|
-
data-n-topic-search-categories="concepts,equities"
|
|
76
|
-
data-n-topic-search-view-all
|
|
77
|
-
>
|
|
78
|
-
<label className="o-header__visually-hidden" htmlFor="o-header-drawer-search-term">
|
|
79
|
-
Search the <abbr title="Financial Times">FT</abbr>
|
|
80
|
-
</label>
|
|
81
|
-
<input
|
|
82
|
-
className="o-header__drawer-search-term"
|
|
83
|
-
id="o-header-drawer-search-term"
|
|
84
|
-
name="q"
|
|
85
|
-
type="text"
|
|
86
|
-
autoComplete="off"
|
|
87
|
-
autoCorrect="off"
|
|
88
|
-
autoCapitalize="off"
|
|
89
|
-
spellCheck={false}
|
|
90
|
-
placeholder="Search the FT"
|
|
91
|
-
data-trackable="search-term"
|
|
92
|
-
data-n-topic-search-input
|
|
93
|
-
/>
|
|
94
|
-
<button className="o-header__drawer-search-submit" type="submit" data-trackable="search-submit">
|
|
95
|
-
<span className="o-header__visually-hidden">Search</span>
|
|
96
|
-
</button>
|
|
97
|
-
</form>
|
|
98
|
-
</div>
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
const SectionPrimary = (props: TNavMenuItem) => {
|
|
102
|
-
return (
|
|
103
|
-
<React.Fragment>
|
|
104
|
-
<li className="o-header__drawer-menu-item o-header__drawer-menu-item--heading">{props.label}</li>
|
|
105
|
-
{(props.submenu?.items as TNavMenuItem[]).map((item, index) => (
|
|
106
|
-
<li key={item.url} className="o-header__drawer-menu-item">
|
|
107
|
-
{item.submenu ? (
|
|
108
|
-
<DrawerParentItem item={item} idSuffix={`${index}`} />
|
|
109
|
-
) : (
|
|
110
|
-
<DrawerSingleItem {...item} />
|
|
111
|
-
)}
|
|
112
|
-
</li>
|
|
113
|
-
))}
|
|
114
|
-
</React.Fragment>
|
|
115
|
-
)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const SectionSecondary = (props: TNavMenuItem) => (
|
|
119
|
-
<React.Fragment>
|
|
120
|
-
<li className="o-header__drawer-menu-item o-header__drawer-menu-item--heading">{props.label}</li>
|
|
121
|
-
{(props.submenu?.items as TNavMenuItem[]).map((item, index) => (
|
|
122
|
-
<li key={item.url} className="o-header__drawer-menu-item">
|
|
123
|
-
{item.submenu ? (
|
|
124
|
-
<DrawerParentItem item={item} idSuffix={'inner' + index} />
|
|
125
|
-
) : (
|
|
126
|
-
<DrawerSingleItem {...item} />
|
|
127
|
-
)}
|
|
128
|
-
</li>
|
|
129
|
-
))}
|
|
130
|
-
</React.Fragment>
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
const SectionTertiary = (props: TNavMenuItem) => (
|
|
134
|
-
<React.Fragment>
|
|
135
|
-
{(props.submenu?.items as TNavMenuItem[]).map((item, index) => {
|
|
136
|
-
const divideItem = index === 0 ? 'o-header__drawer-menu-item--divide' : ''
|
|
137
|
-
|
|
138
|
-
return (
|
|
139
|
-
<li
|
|
140
|
-
data-component={divideItem ? 'drawer-menu-item--divide' : undefined}
|
|
141
|
-
key={item.url}
|
|
142
|
-
className={`o-header__drawer-menu-item ${divideItem}`}
|
|
143
|
-
>
|
|
144
|
-
<DrawerSpecialItem {...item} />
|
|
145
|
-
</li>
|
|
146
|
-
)
|
|
147
|
-
})}
|
|
148
|
-
</React.Fragment>
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
const UserMenu = (props: TNavMenu) => (
|
|
152
|
-
<nav className="o-header__drawer-menu o-header__drawer-menu--user" data-trackable="user-nav">
|
|
153
|
-
<ul className="o-header__drawer-menu-list">
|
|
154
|
-
{props.items.map((item) => (
|
|
155
|
-
<li key={item.url} className="o-header__drawer-menu-item">
|
|
156
|
-
<a className="o-header__drawer-menu-link" href={item.url ?? undefined} data-trackable={item.label}>
|
|
157
|
-
{item.label}
|
|
158
|
-
</a>
|
|
159
|
-
</li>
|
|
160
|
-
))}
|
|
161
|
-
</ul>
|
|
162
|
-
</nav>
|
|
163
|
-
)
|
|
164
|
-
|
|
165
|
-
export { IncludeDrawer }
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { THeaderProps } from '../../interfaces'
|
|
3
|
-
import { ariaSelected } from '../../utils'
|
|
4
|
-
import {
|
|
5
|
-
TNavMenuItem,
|
|
6
|
-
TNavMeganav,
|
|
7
|
-
INavMeganavSections,
|
|
8
|
-
INavMeganavArticles
|
|
9
|
-
} from '@financial-times/dotcom-types-navigation'
|
|
10
|
-
|
|
11
|
-
const MobileNav = (props: THeaderProps) => {
|
|
12
|
-
// Only display navigation on pages which are included in this menu
|
|
13
|
-
const targetUrls = props.data['navbar-simple'].items.map((item) => item.url)
|
|
14
|
-
|
|
15
|
-
return props.data.currentPath && targetUrls.includes(props.data.currentPath) ? (
|
|
16
|
-
<NavMobile items={props.data['navbar-simple'].items} />
|
|
17
|
-
) : null
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const NavMobile = ({ items }: { items: TNavMenuItem[] }) => {
|
|
21
|
-
return (
|
|
22
|
-
<nav
|
|
23
|
-
id="o-header-nav-mobile"
|
|
24
|
-
className="o-header__row o-header__nav o-header__nav--mobile"
|
|
25
|
-
aria-hidden="true"
|
|
26
|
-
data-trackable="header-nav:mobile"
|
|
27
|
-
>
|
|
28
|
-
<ul className="o-header__nav-list">
|
|
29
|
-
{items.map((item, index) => (
|
|
30
|
-
<li className="o-header__nav-item" key={`link-${index}`}>
|
|
31
|
-
<a
|
|
32
|
-
className="o-header__nav-link o-header__nav-link--primary"
|
|
33
|
-
href={item.url ?? undefined}
|
|
34
|
-
{...ariaSelected(item)}
|
|
35
|
-
data-trackable={item.label}
|
|
36
|
-
>
|
|
37
|
-
{item.label}
|
|
38
|
-
</a>
|
|
39
|
-
</li>
|
|
40
|
-
))}
|
|
41
|
-
</ul>
|
|
42
|
-
</nav>
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const NavDesktop = (props) => (
|
|
47
|
-
<nav
|
|
48
|
-
id="o-header-nav-desktop"
|
|
49
|
-
className="o-header__row o-header__nav o-header__nav--desktop"
|
|
50
|
-
role="navigation"
|
|
51
|
-
aria-label="Primary navigation"
|
|
52
|
-
data-trackable="header-nav:desktop"
|
|
53
|
-
>
|
|
54
|
-
<div className="o-header__container">{props.children}</div>
|
|
55
|
-
</nav>
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
const NavListLeft = (props: THeaderProps) => (
|
|
59
|
-
<ul className="o-header__nav-list o-header__nav-list--left" data-trackable="primary-nav">
|
|
60
|
-
{props.data.navbar.items.map((item, index) => (
|
|
61
|
-
<li className="o-header__nav-item" key={`link-${index}`}>
|
|
62
|
-
<a
|
|
63
|
-
className="o-header__nav-link o-header__nav-link--primary"
|
|
64
|
-
href={item.url ?? undefined}
|
|
65
|
-
id={`o-header-link-${index}`}
|
|
66
|
-
{...ariaSelected(item)}
|
|
67
|
-
data-trackable={item.label}
|
|
68
|
-
>
|
|
69
|
-
{item.label}
|
|
70
|
-
</a>
|
|
71
|
-
{props.showMegaNav && Array.isArray(item.meganav) ? (
|
|
72
|
-
<MegaNav meganav={item.meganav} label={item.label} index={index} />
|
|
73
|
-
) : null}
|
|
74
|
-
</li>
|
|
75
|
-
))}
|
|
76
|
-
</ul>
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
const NavListRight = (props: THeaderProps) => {
|
|
80
|
-
return props.userIsLoggedIn ? <NavListRightLoggedIn items={props.data['navbar-right'].items} /> : null
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const NavListRightLoggedIn = ({ items }: { items: TNavMenuItem[] }) => {
|
|
84
|
-
return (
|
|
85
|
-
<ul
|
|
86
|
-
data-component="nav-list--right"
|
|
87
|
-
className="o-header__nav-list o-header__nav-list--right"
|
|
88
|
-
data-trackable="user-nav"
|
|
89
|
-
>
|
|
90
|
-
{items.map((item, index) => (
|
|
91
|
-
<li className="o-header__nav-item" key={`link-${index}`}>
|
|
92
|
-
<a className="o-header__nav-link" href={item.url ?? undefined} data-trackable={item.label}>
|
|
93
|
-
{item.label}
|
|
94
|
-
</a>
|
|
95
|
-
</li>
|
|
96
|
-
))}
|
|
97
|
-
</ul>
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const MegaNav = ({ label, meganav, index }: { label: string; meganav: TNavMeganav[]; index: number }) => {
|
|
102
|
-
const sections = meganav.find(({ component }) => component === 'sectionlist')
|
|
103
|
-
const articles = meganav.find(({ component }) => component === 'articlelist')
|
|
104
|
-
|
|
105
|
-
return (
|
|
106
|
-
<div
|
|
107
|
-
className="o-header__mega"
|
|
108
|
-
id={`o-header-mega-${index}`}
|
|
109
|
-
role="group"
|
|
110
|
-
aria-labelledby={`o-header-link-${index}`}
|
|
111
|
-
data-o-header-mega
|
|
112
|
-
data-trackable={`meganav | ${label}`}
|
|
113
|
-
>
|
|
114
|
-
<div className="o-header__container">
|
|
115
|
-
<div className="o-header__mega-wrapper">
|
|
116
|
-
{sections ? <SectionList {...(sections as INavMeganavSections)} /> : null}
|
|
117
|
-
{articles ? <ArticleList {...(articles as INavMeganavArticles)} /> : null}
|
|
118
|
-
</div>
|
|
119
|
-
</div>
|
|
120
|
-
</div>
|
|
121
|
-
)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const SectionList = ({ title, data }: INavMeganavSections) => {
|
|
125
|
-
return (
|
|
126
|
-
<div className="o-header__mega-column o-header__mega-column--subsections" data-trackable="sections">
|
|
127
|
-
<div className="o-header__mega-heading">{title}</div>
|
|
128
|
-
<div className="o-header__mega-content">
|
|
129
|
-
<ul className="o-header__mega-list">
|
|
130
|
-
{data?.map((column) =>
|
|
131
|
-
column.map((item, index) => (
|
|
132
|
-
<li className="o-header__mega-item" key={`link-${index}`}>
|
|
133
|
-
<a
|
|
134
|
-
className="o-header__mega-link"
|
|
135
|
-
href={item.url ?? undefined}
|
|
136
|
-
{...ariaSelected(item)}
|
|
137
|
-
data-trackable="link"
|
|
138
|
-
>
|
|
139
|
-
{item.label}
|
|
140
|
-
</a>
|
|
141
|
-
</li>
|
|
142
|
-
))
|
|
143
|
-
)}
|
|
144
|
-
</ul>
|
|
145
|
-
</div>
|
|
146
|
-
</div>
|
|
147
|
-
)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const ArticleList = ({ title, data }: INavMeganavArticles) => {
|
|
151
|
-
return (
|
|
152
|
-
<div className="o-header__mega-column o-header__mega-column--articles" data-trackable="popular">
|
|
153
|
-
<div className="o-header__mega-heading">{title}</div>
|
|
154
|
-
<div className="o-header__mega-content">
|
|
155
|
-
<ul className="o-header__mega-list">
|
|
156
|
-
{data?.map((item, index) => (
|
|
157
|
-
<li className="o-header__mega-item" key={`link-${index}`}>
|
|
158
|
-
<a
|
|
159
|
-
className="o-header__mega-link"
|
|
160
|
-
href={item.url ?? undefined}
|
|
161
|
-
{...ariaSelected(item)}
|
|
162
|
-
data-trackable="link"
|
|
163
|
-
>
|
|
164
|
-
{item.label}
|
|
165
|
-
</a>
|
|
166
|
-
</li>
|
|
167
|
-
))}
|
|
168
|
-
</ul>
|
|
169
|
-
</div>
|
|
170
|
-
</div>
|
|
171
|
-
)
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const UserActionsNav = (props: THeaderProps) => {
|
|
175
|
-
const userNavItems = props.data['navbar-right-anon'].items
|
|
176
|
-
|
|
177
|
-
return (
|
|
178
|
-
<div className="o-header__row o-header__anon" data-trackable="header-anon">
|
|
179
|
-
<ul className="o-header__anon-list">
|
|
180
|
-
{userNavItems.map((item, index) => (
|
|
181
|
-
<li className="o-header__anon-item" key={`link-${index}`}>
|
|
182
|
-
<a className="o-header__anon-link" href={item.url ?? undefined} data-trackable={item.label}>
|
|
183
|
-
{item.label}
|
|
184
|
-
</a>
|
|
185
|
-
</li>
|
|
186
|
-
))}
|
|
187
|
-
</ul>
|
|
188
|
-
</div>
|
|
189
|
-
)
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export { NavDesktop, NavListLeft, NavListRight, UserActionsNav, MobileNav }
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
|
|
3
|
-
const Search = ({ instance }) => {
|
|
4
|
-
return (
|
|
5
|
-
<div
|
|
6
|
-
id={`o-header-search-${instance}`}
|
|
7
|
-
className={`o-header__row o-header__search o-header__search--${instance}`}
|
|
8
|
-
data-trackable="header-search"
|
|
9
|
-
data-o-header-search>
|
|
10
|
-
<div className="o-header__container">
|
|
11
|
-
<form
|
|
12
|
-
className="o-header__search-form"
|
|
13
|
-
action="/search"
|
|
14
|
-
role="search"
|
|
15
|
-
aria-label="Site search"
|
|
16
|
-
data-n-topic-search
|
|
17
|
-
data-n-topic-search-categories="concepts,equities"
|
|
18
|
-
data-n-topic-search-view-all>
|
|
19
|
-
<label className="o-header__visually-hidden" htmlFor={`o-header-search-term-${instance}`}>
|
|
20
|
-
Search the <abbr title="Financial Times">FT</abbr>
|
|
21
|
-
</label>
|
|
22
|
-
<input
|
|
23
|
-
className="o-header__search-term"
|
|
24
|
-
id={`o-header-search-term-${instance}`}
|
|
25
|
-
name="q"
|
|
26
|
-
type="text"
|
|
27
|
-
autoComplete="off"
|
|
28
|
-
autoCorrect="off"
|
|
29
|
-
autoCapitalize="off"
|
|
30
|
-
spellCheck={false}
|
|
31
|
-
data-trackable="search-term"
|
|
32
|
-
placeholder="Search the FT"
|
|
33
|
-
data-n-topic-search-input
|
|
34
|
-
/>
|
|
35
|
-
<button className="o-header__search-submit" type="submit" data-trackable="search-submit">
|
|
36
|
-
Search
|
|
37
|
-
</button>
|
|
38
|
-
<button
|
|
39
|
-
className="o-header__search-close o--if-js"
|
|
40
|
-
type="button"
|
|
41
|
-
aria-controls={`o-header-search-${instance}`}
|
|
42
|
-
title="Close search bar"
|
|
43
|
-
data-trackable="close">
|
|
44
|
-
<span className="o-header__visually-hidden">Close search bar</span>
|
|
45
|
-
</button>
|
|
46
|
-
</form>
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export { Search }
|