@financial-times/dotcom-ui-header 8.2.1 → 9.0.0-beta.10
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/browser.js +12 -3
- package/dist/node/components/sticky/partials.js +8 -4
- package/dist/node/components/top/partials.d.ts +3 -1
- package/dist/node/components/top/partials.js +14 -8
- package/dist/node/index.js +4 -2
- package/dist/tsconfig.tsbuildinfo +5 -4
- package/package.json +4 -4
- package/src/__test__/components/__snapshots__/MainHeader.spec.tsx.snap +3 -3
- package/src/components/sticky/partials.tsx +16 -16
- package/src/components/top/partials.tsx +21 -17
- package/src/enhanced-search/customList.js +170 -0
- package/src/enhanced-search/enhancedSearch.js +61 -0
- package/src/enhanced-search/styles.scss +150 -0
- package/src/index.tsx +14 -2
- package/styles.scss +8 -4
package/browser.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import Header from '@financial-times/o-header'
|
|
2
2
|
import TopicSearch from 'n-topic-search'
|
|
3
|
-
|
|
3
|
+
import EnhancedSearch from './src/enhanced-search/enhancedSearch'
|
|
4
4
|
/**
|
|
5
5
|
* @typedef HeaderOptions
|
|
6
6
|
* @property { HTMLElement } [rootElement] - the root element passed to o-header
|
|
7
7
|
* @property { string } [hostName]
|
|
8
|
+
* @property { 'open' | 'close' } [searchState]
|
|
9
|
+
* @property { string } [enhancedSearchUrl]
|
|
8
10
|
*/
|
|
9
11
|
|
|
10
12
|
/**
|
|
@@ -16,10 +18,17 @@ export const init = (headerOptions = {}) => {
|
|
|
16
18
|
'.o-header [data-n-topic-search], .o-header__drawer [data-n-topic-search]'
|
|
17
19
|
)
|
|
18
20
|
topicSearchElements.forEach((element) => {
|
|
19
|
-
|
|
21
|
+
headerOptions.enhancedSearchUrl
|
|
22
|
+
? new EnhancedSearch(element, headerOptions)
|
|
23
|
+
: new TopicSearch(element, headerOptions)
|
|
20
24
|
})
|
|
21
25
|
|
|
22
|
-
Header.init(headerOptions.rootElement)
|
|
26
|
+
Header.init(headerOptions.rootElement, { searchState: headerOptions.searchState })
|
|
27
|
+
|
|
28
|
+
if (headerOptions.searchState === 'open') {
|
|
29
|
+
// Hide the sticky heder
|
|
30
|
+
document.querySelector('#o-header-search-sticky')?.setAttribute('aria-hidden', 'true')
|
|
31
|
+
}
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
export { Header as OrigamiHeader }
|
|
@@ -31,8 +31,12 @@ const NavListRightAnonSticky = (props) => {
|
|
|
31
31
|
subscribeAction && (react_1.default.createElement(partials_1.SubscribeButton, { item: subscribeAction, variant: "sticky", className: "o-header__top-button--hide-m" })),
|
|
32
32
|
signInAction && react_1.default.createElement(partials_1.SignInLink, { item: signInAction, variant: "sticky", className: "" }))));
|
|
33
33
|
};
|
|
34
|
-
const MyFtSticky = ({ className }) =>
|
|
35
|
-
|
|
34
|
+
const MyFtSticky = ({ className, items }) => {
|
|
35
|
+
var _a;
|
|
36
|
+
const ftUrl = (_a = items === null || items === void 0 ? void 0 : items.find((el) => el.label === 'myFT')) === null || _a === void 0 ? void 0 : _a.url;
|
|
37
|
+
return (react_1.default.createElement("a", { className: `o-header__top-icon-link o-header__top-icon-link--myft ${className}`, href: ftUrl !== null && ftUrl !== void 0 ? ftUrl : '/myft', "data-trackable": "my-ft", tabIndex: -1 },
|
|
38
|
+
react_1.default.createElement("span", { className: "o-header__visually-hidden" }, "myFT")));
|
|
39
|
+
};
|
|
36
40
|
const TopWrapperSticky = (props) => (react_1.default.createElement("div", { className: "o-header__row o-header__top", "data-trackable": "header-sticky" },
|
|
37
41
|
react_1.default.createElement("div", { className: "o-header__container" },
|
|
38
42
|
react_1.default.createElement("div", { className: "o-header__top-wrapper" }, props.children))));
|
|
@@ -50,11 +54,11 @@ const TopColumnCenterSticky = (props) => {
|
|
|
50
54
|
};
|
|
51
55
|
exports.TopColumnCenterSticky = TopColumnCenterSticky;
|
|
52
56
|
const NavListRightLoggedInSticky = (props) => {
|
|
53
|
-
var _a;
|
|
57
|
+
var _a, _b;
|
|
54
58
|
const subscribeAction = (_a = props.data['navbar-right-anon'].items) === null || _a === void 0 ? void 0 : _a[1];
|
|
55
59
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
56
60
|
!props.userIsSubscribed && subscribeAction && (react_1.default.createElement(partials_1.SubscribeButton, { item: subscribeAction, variant: "sticky", className: "o-header__top-button--hide-m" })),
|
|
57
|
-
react_1.default.createElement(MyFtSticky, { className: "" })));
|
|
61
|
+
react_1.default.createElement(MyFtSticky, { className: "", items: (_b = props.data.account) === null || _b === void 0 ? void 0 : _b.items })));
|
|
58
62
|
};
|
|
59
63
|
// This behaviour is similar to `NavListRight` in '../navigation/partials' but:
|
|
60
64
|
// - The sticky header renders either the `navbar-right-anon` data or the myFT component
|
|
@@ -4,7 +4,9 @@ import { TNavMenuItem } from '@financial-times/dotcom-types-navigation';
|
|
|
4
4
|
declare const HeaderWrapper: (props: any) => JSX.Element;
|
|
5
5
|
declare const TopWrapper: (props: any) => JSX.Element;
|
|
6
6
|
declare const TopColumnLeft: () => JSX.Element;
|
|
7
|
-
declare const TopColumnCenter: (
|
|
7
|
+
declare const TopColumnCenter: ({ url }: {
|
|
8
|
+
url?: string | undefined;
|
|
9
|
+
}) => JSX.Element;
|
|
8
10
|
declare const TopColumnCenterNoLink: () => JSX.Element;
|
|
9
11
|
declare const SignInLink: ({ item, variant, className }: {
|
|
10
12
|
item: TNavMenuItem;
|
|
@@ -12,8 +12,12 @@ const DrawerIcon = () => (react_1.default.createElement("a", { href: "#o-header-
|
|
|
12
12
|
react_1.default.createElement("span", { className: "o-header__top-link-label" }, "Open side navigation menu")));
|
|
13
13
|
const SearchIcon = () => (react_1.default.createElement("a", { href: `#o-header-search-primary`, className: "o-header__top-icon-link o-header__top-icon-link--search", "aria-controls": `o-header-search-primary`, title: "Open search bar", "data-trackable": "search-toggle" },
|
|
14
14
|
react_1.default.createElement("span", { className: "o-header__top-link-label" }, "Open search bar")));
|
|
15
|
-
const MyFt = ({ className }) =>
|
|
16
|
-
|
|
15
|
+
const MyFt = ({ className, items }) => {
|
|
16
|
+
var _a;
|
|
17
|
+
const ftUrl = (_a = items === null || items === void 0 ? void 0 : items.find((el) => el.label === 'myFT')) === null || _a === void 0 ? void 0 : _a.url;
|
|
18
|
+
return (react_1.default.createElement("a", { className: `o-header__top-icon-link o-header__top-icon-link--myft ${className}`, id: "o-header-top-link-myft", href: ftUrl !== null && ftUrl !== void 0 ? ftUrl : '/myft', "data-trackable": "my-ft", "data-tour-stage": "myFt", "aria-label": "My F T" },
|
|
19
|
+
react_1.default.createElement("span", { className: "o-header__visually-hidden" }, "myFT")));
|
|
20
|
+
};
|
|
17
21
|
const TopWrapper = (props) => (react_1.default.createElement("div", { className: "o-header__row o-header__top", "data-trackable": "header-top" },
|
|
18
22
|
react_1.default.createElement("div", { className: "o-header__container" },
|
|
19
23
|
react_1.default.createElement("div", { className: "o-header__top-wrapper" }, props.children))));
|
|
@@ -22,8 +26,8 @@ const TopColumnLeft = () => (react_1.default.createElement("div", { className: "
|
|
|
22
26
|
react_1.default.createElement(DrawerIcon, null),
|
|
23
27
|
react_1.default.createElement(SearchIcon, null)));
|
|
24
28
|
exports.TopColumnLeft = TopColumnLeft;
|
|
25
|
-
const TopColumnCenter = () => (react_1.default.createElement("div", { className: "o-header__top-column o-header__top-column--center" },
|
|
26
|
-
react_1.default.createElement("a", { className: "o-header__top-logo", style: { backgroundImage: 'none' }, "data-trackable": "logo", href:
|
|
29
|
+
const TopColumnCenter = ({ url }) => (react_1.default.createElement("div", { className: "o-header__top-column o-header__top-column--center" },
|
|
30
|
+
react_1.default.createElement("a", { className: "o-header__top-logo", style: { backgroundImage: 'none' }, "data-trackable": "logo", href: url !== null && url !== void 0 ? url : '/', title: "Go to Financial Times homepage" },
|
|
27
31
|
react_1.default.createElement(BrandFtMasthead_1.default, { title: "Financial Times" }))));
|
|
28
32
|
exports.TopColumnCenter = TopColumnCenter;
|
|
29
33
|
const TopColumnCenterNoLink = () => (react_1.default.createElement("div", { className: "o-header__top-column o-header__top-column--center" },
|
|
@@ -31,11 +35,11 @@ const TopColumnCenterNoLink = () => (react_1.default.createElement("div", { clas
|
|
|
31
35
|
react_1.default.createElement(BrandFtMasthead_1.default, { title: "Financial Times" }))));
|
|
32
36
|
exports.TopColumnCenterNoLink = TopColumnCenterNoLink;
|
|
33
37
|
const TopColumnRightLoggedIn = (props) => {
|
|
34
|
-
var _a, _b;
|
|
38
|
+
var _a, _b, _c, _d;
|
|
35
39
|
const subscribeAction = (_b = (_a = props.data['navbar-right-anon']) === null || _a === void 0 ? void 0 : _a.items) === null || _b === void 0 ? void 0 : _b[1];
|
|
36
40
|
return (react_1.default.createElement("div", { className: "o-header__top-column o-header__top-column--right" },
|
|
37
41
|
!props.userIsSubscribed && subscribeAction && (react_1.default.createElement(SubscribeButton, { item: subscribeAction, variant: props.variant, className: "o-header__top-button--hide-m" })),
|
|
38
|
-
react_1.default.createElement(MyFt, { className: "" })));
|
|
42
|
+
react_1.default.createElement(MyFt, { className: "", items: (_d = (_c = props.data) === null || _c === void 0 ? void 0 : _c.account) === null || _d === void 0 ? void 0 : _d.items })));
|
|
39
43
|
};
|
|
40
44
|
const SignInLink = ({ item, variant, className }) => {
|
|
41
45
|
var _a;
|
|
@@ -58,16 +62,18 @@ const TopColumnRightAnon = ({ items, variant }) => {
|
|
|
58
62
|
return (react_1.default.createElement("div", { className: "o-header__top-column o-header__top-column--right" },
|
|
59
63
|
subscribeAction && (react_1.default.createElement(SubscribeButton, { item: subscribeAction, variant: variant, className: "o-header__top-button--hide-m" })),
|
|
60
64
|
signInAction && (react_1.default.createElement(SignInLink, { item: signInAction, variant: variant, className: "o-header__top-link--hide-m" })),
|
|
61
|
-
react_1.default.createElement(MyFt, { className: "o-header__top-icon-link--show-m" })));
|
|
65
|
+
react_1.default.createElement(MyFt, { className: "o-header__top-icon-link--show-m", items: items })));
|
|
62
66
|
};
|
|
63
67
|
exports.TopColumnRightAnon = TopColumnRightAnon;
|
|
64
68
|
const TopColumnRight = (props) => {
|
|
69
|
+
var _a, _b;
|
|
65
70
|
if (props.userIsLoggedIn) {
|
|
66
71
|
return react_1.default.createElement(TopColumnRightLoggedIn, Object.assign({}, props));
|
|
67
72
|
}
|
|
68
73
|
else {
|
|
69
74
|
const userNavAnonItems = props.data['navbar-right-anon'].items;
|
|
70
|
-
|
|
75
|
+
const userNavAccountItems = (_b = (_a = props.data.account) === null || _a === void 0 ? void 0 : _a.items) !== null && _b !== void 0 ? _b : [];
|
|
76
|
+
return react_1.default.createElement(TopColumnRightAnon, { items: userNavAnonItems.concat(userNavAccountItems), variant: props.variant });
|
|
71
77
|
}
|
|
72
78
|
};
|
|
73
79
|
exports.TopColumnRight = TopColumnRight;
|
package/dist/node/index.js
CHANGED
|
@@ -20,13 +20,14 @@ const defaultProps = {
|
|
|
20
20
|
showMegaNav: true
|
|
21
21
|
};
|
|
22
22
|
function MainHeader(props) {
|
|
23
|
+
var _a, _b;
|
|
23
24
|
const includeUserActionsNav = props.showUserNavigation && !props.userIsLoggedIn;
|
|
24
25
|
const includeSubNavigation = props.showSubNavigation && (props.data.breadcrumb || props.data.subsections);
|
|
25
26
|
return (react_1.default.createElement(partials_1.HeaderWrapper, Object.assign({}, props),
|
|
26
27
|
includeUserActionsNav ? react_1.default.createElement(partials_2.UserActionsNav, Object.assign({}, props)) : null,
|
|
27
28
|
react_1.default.createElement(partials_1.TopWrapper, null,
|
|
28
29
|
react_1.default.createElement(partials_1.TopColumnLeft, null),
|
|
29
|
-
props.showLogoLink ? react_1.default.createElement(partials_1.TopColumnCenter, null) : react_1.default.createElement(partials_1.TopColumnCenterNoLink, null),
|
|
30
|
+
props.showLogoLink ? (react_1.default.createElement(partials_1.TopColumnCenter, { url: (_b = (_a = props.data.editions) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.url })) : (react_1.default.createElement(partials_1.TopColumnCenterNoLink, null)),
|
|
30
31
|
react_1.default.createElement(partials_1.TopColumnRight, Object.assign({}, props))),
|
|
31
32
|
react_1.default.createElement(partials_5.Search, { instance: "primary" }),
|
|
32
33
|
react_1.default.createElement(partials_2.MobileNav, Object.assign({}, props)),
|
|
@@ -66,11 +67,12 @@ function Drawer(props) {
|
|
|
66
67
|
exports.Drawer = Drawer;
|
|
67
68
|
Drawer.defaultProps = defaultProps;
|
|
68
69
|
function NoOutboundLinksHeader(props) {
|
|
70
|
+
var _a, _b;
|
|
69
71
|
const includeUserActionsNav = props.showUserNavigation && !props.userIsLoggedIn;
|
|
70
72
|
const includeSubNavigation = props.showSubNavigation && (props.data.breadcrumb || props.data.subsections);
|
|
71
73
|
return (react_1.default.createElement(partials_1.HeaderWrapper, Object.assign({}, props),
|
|
72
74
|
includeUserActionsNav ? react_1.default.createElement(partials_2.UserActionsNav, Object.assign({}, props)) : null,
|
|
73
|
-
react_1.default.createElement(partials_1.TopWrapper, null, props.showLogoLink ? react_1.default.createElement(partials_1.TopColumnCenter, null) : react_1.default.createElement(partials_1.TopColumnCenterNoLink, null)),
|
|
75
|
+
react_1.default.createElement(partials_1.TopWrapper, null, props.showLogoLink ? (react_1.default.createElement(partials_1.TopColumnCenter, { url: (_b = (_a = props.data.editions) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.url })) : (react_1.default.createElement(partials_1.TopColumnCenterNoLink, null))),
|
|
74
76
|
react_1.default.createElement(partials_2.NavDesktop, null, props.showUserNavigation ? react_1.default.createElement(partials_2.NavListRight, Object.assign({}, props)) : null),
|
|
75
77
|
includeSubNavigation ? react_1.default.createElement(partials_4.SubNavigation, Object.assign({}, props)) : null));
|
|
76
78
|
}
|
|
@@ -182,8 +182,8 @@
|
|
|
182
182
|
"affectsGlobalScope": false
|
|
183
183
|
},
|
|
184
184
|
"../src/components/top/partials.tsx": {
|
|
185
|
-
"version": "
|
|
186
|
-
"signature": "
|
|
185
|
+
"version": "87cbe39a584f2dc0fcf77dbccd2d72880ae938a0692243b2b3b4c2639eed747e",
|
|
186
|
+
"signature": "77e2a1005d3885487e05d8fbb99862703ec1e3230b16b31970b731a124f19414",
|
|
187
187
|
"affectsGlobalScope": false
|
|
188
188
|
},
|
|
189
189
|
"../src/utils.ts": {
|
|
@@ -197,7 +197,7 @@
|
|
|
197
197
|
"affectsGlobalScope": false
|
|
198
198
|
},
|
|
199
199
|
"../src/components/sticky/partials.tsx": {
|
|
200
|
-
"version": "
|
|
200
|
+
"version": "f8dd9197528a0ccdacf58885773f78a59e1243c3189eb73e810fdfbfc66b28fb",
|
|
201
201
|
"signature": "502016ae45d32bca27cbd9d67cf6f390647cb4b8db18384814c9539213d40fba",
|
|
202
202
|
"affectsGlobalScope": false
|
|
203
203
|
},
|
|
@@ -222,7 +222,7 @@
|
|
|
222
222
|
"affectsGlobalScope": false
|
|
223
223
|
},
|
|
224
224
|
"../src/index.tsx": {
|
|
225
|
-
"version": "
|
|
225
|
+
"version": "5e57493c4c31180ed6b73ef9da15c8b041a49351db43162cc5f96f0e3b78980e",
|
|
226
226
|
"signature": "193a1c1b82fe624c251dd16b488b6b90a155e072da0ace6b843ec85f99df0c6e",
|
|
227
227
|
"affectsGlobalScope": false
|
|
228
228
|
},
|
|
@@ -1385,6 +1385,7 @@
|
|
|
1385
1385
|
],
|
|
1386
1386
|
"../src/components/sticky/partials.tsx": [
|
|
1387
1387
|
"../../../node_modules/@types/react/index.d.ts",
|
|
1388
|
+
"../../dotcom-types-navigation/index.d.ts",
|
|
1388
1389
|
"../src/components/top/partials.tsx",
|
|
1389
1390
|
"../src/interfaces.d.ts"
|
|
1390
1391
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@financial-times/dotcom-ui-header",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0-beta.10",
|
|
4
4
|
"description": "",
|
|
5
5
|
"browser": "browser.js",
|
|
6
6
|
"main": "component.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"author": "",
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@financial-times/dotcom-types-navigation": "^
|
|
25
|
+
"@financial-times/dotcom-types-navigation": "^9.0.0-beta.10",
|
|
26
26
|
"n-topic-search": "^4.0.0",
|
|
27
27
|
"n-ui-foundations": "^9.0.0"
|
|
28
28
|
},
|
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
"@svgr/core": "^5.0.0",
|
|
32
32
|
"camelcase": "^6.0.0",
|
|
33
33
|
"check-engine": "^1.10.1",
|
|
34
|
-
"@financial-times/o-header": "^11.0
|
|
34
|
+
"@financial-times/o-header": "^11.1.0",
|
|
35
35
|
"react": "^16.8.6"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@financial-times/o-header": "^11.0
|
|
38
|
+
"@financial-times/o-header": "^11.1.0",
|
|
39
39
|
"@financial-times/logo-images": "^1.10.1",
|
|
40
40
|
"react": "16.x || 17.x"
|
|
41
41
|
},
|
|
@@ -54,7 +54,7 @@ exports[`dotcom-ui-header/src/components/MainHeader renders a right aligned subn
|
|
|
54
54
|
<a
|
|
55
55
|
className="o-header__top-logo"
|
|
56
56
|
data-trackable="logo"
|
|
57
|
-
href="
|
|
57
|
+
href="#"
|
|
58
58
|
style={
|
|
59
59
|
Object {
|
|
60
60
|
"backgroundImage": "none",
|
|
@@ -1897,7 +1897,7 @@ exports[`dotcom-ui-header/src/components/MainHeader renders as a logged in user
|
|
|
1897
1897
|
<a
|
|
1898
1898
|
className="o-header__top-logo"
|
|
1899
1899
|
data-trackable="logo"
|
|
1900
|
-
href="
|
|
1900
|
+
href="#"
|
|
1901
1901
|
style={
|
|
1902
1902
|
Object {
|
|
1903
1903
|
"backgroundImage": "none",
|
|
@@ -3745,7 +3745,7 @@ exports[`dotcom-ui-header/src/components/MainHeader renders as an anonymous user
|
|
|
3745
3745
|
<a
|
|
3746
3746
|
className="o-header__top-logo"
|
|
3747
3747
|
data-trackable="logo"
|
|
3748
|
-
href="
|
|
3748
|
+
href="#"
|
|
3749
3749
|
style={
|
|
3750
3750
|
Object {
|
|
3751
3751
|
"backgroundImage": "none",
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import React from 'react'
|
|
5
5
|
import { SubscribeButton, SignInLink } from '../top/partials'
|
|
6
6
|
import { THeaderProps } from '../../interfaces'
|
|
7
|
+
import { TNavMenuItem } from '@financial-times/dotcom-types-navigation'
|
|
7
8
|
|
|
8
9
|
const StickyHeaderWrapper = (props: THeaderProps & { children: React.ReactNode }) => (
|
|
9
10
|
<header
|
|
@@ -88,16 +89,19 @@ const NavListRightAnonSticky = (props: THeaderProps) => {
|
|
|
88
89
|
)
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
const MyFtSticky = ({ className }: { className?: string }) =>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
92
|
+
const MyFtSticky = ({ className, items }: { className?: string; items?: TNavMenuItem[] }) => {
|
|
93
|
+
const ftUrl = items?.find((el) => el.label === 'myFT')?.url
|
|
94
|
+
return (
|
|
95
|
+
<a
|
|
96
|
+
className={`o-header__top-icon-link o-header__top-icon-link--myft ${className}`}
|
|
97
|
+
href={ftUrl ?? '/myft'}
|
|
98
|
+
data-trackable="my-ft"
|
|
99
|
+
tabIndex={-1}
|
|
100
|
+
>
|
|
101
|
+
<span className="o-header__visually-hidden">myFT</span>
|
|
102
|
+
</a>
|
|
103
|
+
)
|
|
104
|
+
}
|
|
101
105
|
|
|
102
106
|
const TopWrapperSticky = (props) => (
|
|
103
107
|
<div className="o-header__row o-header__top" data-trackable="header-sticky">
|
|
@@ -129,13 +133,9 @@ const NavListRightLoggedInSticky = (props: THeaderProps) => {
|
|
|
129
133
|
return (
|
|
130
134
|
<React.Fragment>
|
|
131
135
|
{!props.userIsSubscribed && subscribeAction && (
|
|
132
|
-
<SubscribeButton
|
|
133
|
-
item={subscribeAction}
|
|
134
|
-
variant="sticky"
|
|
135
|
-
className="o-header__top-button--hide-m"
|
|
136
|
-
/>
|
|
136
|
+
<SubscribeButton item={subscribeAction} variant="sticky" className="o-header__top-button--hide-m" />
|
|
137
137
|
)}
|
|
138
|
-
<MyFtSticky className="" />
|
|
138
|
+
<MyFtSticky className="" items={props.data.account?.items} />
|
|
139
139
|
</React.Fragment>
|
|
140
140
|
)
|
|
141
141
|
}
|
|
@@ -39,18 +39,21 @@ const SearchIcon = () => (
|
|
|
39
39
|
</a>
|
|
40
40
|
)
|
|
41
41
|
|
|
42
|
-
const MyFt = ({ className }: { className?: string }) =>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
42
|
+
const MyFt = ({ className, items }: { className?: string; items?: TNavMenuItem[] }) => {
|
|
43
|
+
const ftUrl = items?.find((el) => el.label === 'myFT')?.url
|
|
44
|
+
return (
|
|
45
|
+
<a
|
|
46
|
+
className={`o-header__top-icon-link o-header__top-icon-link--myft ${className}`}
|
|
47
|
+
id="o-header-top-link-myft"
|
|
48
|
+
href={ftUrl ?? '/myft'}
|
|
49
|
+
data-trackable="my-ft"
|
|
50
|
+
data-tour-stage="myFt"
|
|
51
|
+
aria-label="My F T"
|
|
52
|
+
>
|
|
53
|
+
<span className="o-header__visually-hidden">myFT</span>
|
|
54
|
+
</a>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
54
57
|
|
|
55
58
|
const TopWrapper = (props) => (
|
|
56
59
|
<div className="o-header__row o-header__top" data-trackable="header-top">
|
|
@@ -67,13 +70,13 @@ const TopColumnLeft = () => (
|
|
|
67
70
|
</div>
|
|
68
71
|
)
|
|
69
72
|
|
|
70
|
-
const TopColumnCenter = () => (
|
|
73
|
+
const TopColumnCenter = ({ url }: { url?: string }) => (
|
|
71
74
|
<div className="o-header__top-column o-header__top-column--center">
|
|
72
75
|
<a
|
|
73
76
|
className="o-header__top-logo"
|
|
74
77
|
style={{ backgroundImage: 'none' }}
|
|
75
78
|
data-trackable="logo"
|
|
76
|
-
href=
|
|
79
|
+
href={url ?? '/'}
|
|
77
80
|
title="Go to Financial Times homepage"
|
|
78
81
|
>
|
|
79
82
|
<BrandFtMastheadSvg title="Financial Times" />
|
|
@@ -100,7 +103,7 @@ const TopColumnRightLoggedIn = (props: THeaderProps) => {
|
|
|
100
103
|
className="o-header__top-button--hide-m"
|
|
101
104
|
/>
|
|
102
105
|
)}
|
|
103
|
-
<MyFt className="" />
|
|
106
|
+
<MyFt className="" items={props.data?.account?.items} />
|
|
104
107
|
</div>
|
|
105
108
|
)
|
|
106
109
|
}
|
|
@@ -162,7 +165,7 @@ const TopColumnRightAnon = ({ items, variant }: { items: TNavMenuItem[]; variant
|
|
|
162
165
|
{signInAction && (
|
|
163
166
|
<SignInLink item={signInAction} variant={variant} className="o-header__top-link--hide-m" />
|
|
164
167
|
)}
|
|
165
|
-
<MyFt className="o-header__top-icon-link--show-m" />
|
|
168
|
+
<MyFt className="o-header__top-icon-link--show-m" items={items} />
|
|
166
169
|
</div>
|
|
167
170
|
)
|
|
168
171
|
}
|
|
@@ -172,7 +175,8 @@ const TopColumnRight = (props: THeaderProps) => {
|
|
|
172
175
|
return <TopColumnRightLoggedIn {...props} />
|
|
173
176
|
} else {
|
|
174
177
|
const userNavAnonItems = props.data['navbar-right-anon'].items
|
|
175
|
-
|
|
178
|
+
const userNavAccountItems = props.data.account?.items ?? []
|
|
179
|
+
return <TopColumnRightAnon items={userNavAnonItems.concat(userNavAccountItems)} variant={props.variant} />
|
|
176
180
|
}
|
|
177
181
|
}
|
|
178
182
|
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import BaseRenderer from 'n-topic-search/src/renderers/base-renderer'
|
|
2
|
+
|
|
3
|
+
const DISPLAY_ITEMS = 5
|
|
4
|
+
|
|
5
|
+
const headingMapping = {
|
|
6
|
+
concepts: 'Related topics',
|
|
7
|
+
equities: 'Securities'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
class CustomSuggestionList extends BaseRenderer {
|
|
11
|
+
constructor(container, options, enhancedSearchUrl) {
|
|
12
|
+
super(container, options)
|
|
13
|
+
this.renderSuggestionGroup = this.renderSuggestionGroup.bind(this)
|
|
14
|
+
this.enhancedSearchUrl = enhancedSearchUrl
|
|
15
|
+
this.createHtml()
|
|
16
|
+
this.render()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
renderSuggestionChip = (term) => {
|
|
20
|
+
return `<a
|
|
21
|
+
tabindex="0"
|
|
22
|
+
data-trackable="link"
|
|
23
|
+
data-suggestion-id="${term}"
|
|
24
|
+
href="${this.enhancedSearchUrl}${term}"
|
|
25
|
+
class="n-topic-search__target enhanced-search__chip">
|
|
26
|
+
<span class="enhanced-search__chip-text">${term}</span>
|
|
27
|
+
</a>`
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
renderDefaultSuggestionsChips() {
|
|
31
|
+
return `
|
|
32
|
+
<div class="enhanced-search__default-results">
|
|
33
|
+
${['Will Trump win the next election?', 'Investing in AI', 'Ukraine counteroffensive']
|
|
34
|
+
.map(this.renderSuggestionChip)
|
|
35
|
+
.join('')}
|
|
36
|
+
</div>`
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
renderSuggestionLink(suggestion, group) {
|
|
40
|
+
return `<li class="n-topic-search__item">
|
|
41
|
+
<a class="n-topic-search__target enhanced-search__target ${group.linkClassName}"
|
|
42
|
+
href="${suggestion.url}"
|
|
43
|
+
tabindex="0"
|
|
44
|
+
data-trackable="link"
|
|
45
|
+
data-suggestion-id="${suggestion.id}"
|
|
46
|
+
data-suggestion-type="${suggestion.type}"
|
|
47
|
+
>${suggestion.html}</a>
|
|
48
|
+
</li>`
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
renderSuggestionGroup(group) {
|
|
52
|
+
if (group.suggestions?.length || group.emptyHtml) {
|
|
53
|
+
return `
|
|
54
|
+
<div class="enhanced-search__group ${group.linkClassName}" data-trackable="${group.trackable}">
|
|
55
|
+
<h3 class="enhanced-search__title">${group.heading}</h3>
|
|
56
|
+
<ul class="n-topic-search__item-list">
|
|
57
|
+
${group.suggestions.map((suggestion) => this.renderSuggestionLink(suggestion, group)).join('')}
|
|
58
|
+
</ul>
|
|
59
|
+
</div>`
|
|
60
|
+
}
|
|
61
|
+
return ''
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
renderError() {
|
|
65
|
+
return `
|
|
66
|
+
<div
|
|
67
|
+
class="o-message o-message--alert o-message--error enhanced-search__margin-top"
|
|
68
|
+
data-o-component="o-message">
|
|
69
|
+
<div class="o-message__container">
|
|
70
|
+
<div class="o-message__content">
|
|
71
|
+
<p class="o-message__content-main">Failed to load topics and securities results</p>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
`
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
createHtml() {
|
|
79
|
+
const term = this.state?.searchTerm
|
|
80
|
+
const loading = this.state?.loading
|
|
81
|
+
const error = this.state?.error !== undefined
|
|
82
|
+
const hasConcepts = this.state?.suggestions?.concepts && this.state.suggestions.concepts.length
|
|
83
|
+
const hasEquities = this.state?.suggestions?.equities && this.state.suggestions.equities.length
|
|
84
|
+
const hasSuggestions = hasConcepts || hasEquities
|
|
85
|
+
const suggestions = []
|
|
86
|
+
this.items = []
|
|
87
|
+
if (this.options.categories.includes('concepts')) {
|
|
88
|
+
suggestions.push({
|
|
89
|
+
heading: headingMapping['concepts'],
|
|
90
|
+
linkClassName: 'enhanced-search__target--news',
|
|
91
|
+
trackable: 'enhanced-search-news',
|
|
92
|
+
suggestions: this.state.suggestions.concepts?.slice(0, DISPLAY_ITEMS).map((suggestion) => ({
|
|
93
|
+
html: this.highlight(suggestion.prefLabel),
|
|
94
|
+
url: suggestion.url,
|
|
95
|
+
id: suggestion.id,
|
|
96
|
+
type: 'enhanced-search-tag'
|
|
97
|
+
}))
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (this.options.categories.includes('equities')) {
|
|
102
|
+
suggestions.push({
|
|
103
|
+
heading: headingMapping['equities'],
|
|
104
|
+
trackable: 'enhanced-search-equities',
|
|
105
|
+
linkClassName: 'enhanced-search__target--equities',
|
|
106
|
+
emptyHtml: '<div className="enhanced-search__no-results-message">No equities found</div>',
|
|
107
|
+
suggestions: this.state.suggestions.equities?.slice(0, DISPLAY_ITEMS).map((suggestion) => ({
|
|
108
|
+
html: `<span class="enhanced-search__target__equity-name">${this.highlight(
|
|
109
|
+
suggestion.name
|
|
110
|
+
)}</span><abbr>${this.highlight(suggestion.symbol)}</abbr>`,
|
|
111
|
+
url: suggestion.url,
|
|
112
|
+
id: suggestion.symbol,
|
|
113
|
+
type: 'enhanced-search-equity'
|
|
114
|
+
}))
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
this.newHtml = `
|
|
119
|
+
<div aria-live="assertive">
|
|
120
|
+
${
|
|
121
|
+
hasSuggestions
|
|
122
|
+
? `
|
|
123
|
+
<div
|
|
124
|
+
class="o-normalise-visually-hidden n-topic-search__suggestions_explanation"
|
|
125
|
+
>
|
|
126
|
+
Search results have been displayed. To jump to the list of suggestions press
|
|
127
|
+
the down arrow key.
|
|
128
|
+
</div>
|
|
129
|
+
`
|
|
130
|
+
: ''
|
|
131
|
+
}
|
|
132
|
+
<div
|
|
133
|
+
class="n-topic-search n-topic-search__suggestions enhanced-search enhanced-search__suggestions"
|
|
134
|
+
data-trackable="typeahead"
|
|
135
|
+
>
|
|
136
|
+
<div class="enhanced-search__wrapper">
|
|
137
|
+
<h3 class="enhanced-search__title">${
|
|
138
|
+
term
|
|
139
|
+
? 'Get top results for...'
|
|
140
|
+
: 'Search tip: <span class="enhanced-search__title-no-bold">Try using questions or phrases like...</span>'
|
|
141
|
+
}</h3>
|
|
142
|
+
${term ? this.renderSuggestionChip(term) : this.renderDefaultSuggestionsChips()}
|
|
143
|
+
<div class="o-normalise-visually-hidden">Suggestions include</div>
|
|
144
|
+
${error ? this.renderError() : ''}
|
|
145
|
+
${
|
|
146
|
+
loading && !error
|
|
147
|
+
? `<div class="o-loading o-loading--dark o-loading--small enhanced-search__margin-top"></div>`
|
|
148
|
+
: ''
|
|
149
|
+
}
|
|
150
|
+
${
|
|
151
|
+
hasSuggestions && term && !loading && !error
|
|
152
|
+
? `<div class="enhanced-search__suggestions-items">${suggestions
|
|
153
|
+
.map(this.renderSuggestionGroup)
|
|
154
|
+
.join('')}</div>
|
|
155
|
+
`
|
|
156
|
+
: ''
|
|
157
|
+
}
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
</div>`
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
handleSelection(el, ev) {
|
|
164
|
+
ev.stopPropagation()
|
|
165
|
+
// we don't prevent default as the link's url is a link to the relevant stream page
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export default CustomSuggestionList
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import TopicSearch from 'n-topic-search'
|
|
2
|
+
import CustomSuggestionList from './customList'
|
|
3
|
+
|
|
4
|
+
class EnhancedSearch extends TopicSearch {
|
|
5
|
+
constructor(containerEl, options) {
|
|
6
|
+
super(containerEl, {
|
|
7
|
+
...options,
|
|
8
|
+
listComponent: (...args) => new CustomSuggestionList(...args.concat(options?.enhancedSearchUrl)),
|
|
9
|
+
errorCallback: (error) => {
|
|
10
|
+
this.suggestionsView.setState({
|
|
11
|
+
error,
|
|
12
|
+
searchTerm: this.searchEl.value,
|
|
13
|
+
suggestions: {}
|
|
14
|
+
})
|
|
15
|
+
// const detail = { category: 'search', action: `Error: ${error.message}` }
|
|
16
|
+
// document.body.dispatchEvent(new CustomEvent('flyout-load-topics-error', { detail, bubbles: true }))
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
this.updateEnhancedSearchAttributes(options)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
updateEnhancedSearchAttributes(options) {
|
|
24
|
+
const inputs = [
|
|
25
|
+
document.querySelector('#o-header-search-term-primary'),
|
|
26
|
+
document.querySelector('#o-header-search-term-sticky'),
|
|
27
|
+
document.querySelector('#o-header-drawer-search-term')
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
inputs.forEach((input, index) => {
|
|
31
|
+
input.setAttribute('placeholder', 'Search for stories, topics or securities')
|
|
32
|
+
input.parentElement.setAttribute('action', options?.enhancedSearchUrl ?? '/search')
|
|
33
|
+
|
|
34
|
+
if (index === 0) input.parentElement.setAttribute('data-attribute-enhanced-search', 'true')
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
this.hide()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
onFocus(ev) {
|
|
41
|
+
super.onFocus(ev)
|
|
42
|
+
this.show()
|
|
43
|
+
this.suggestionTargets = Array.from(
|
|
44
|
+
this.suggestionListContainer.querySelectorAll('.n-topic-search__target')
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
onType(ev) {
|
|
49
|
+
// This is to update the suggestion chip on keyup
|
|
50
|
+
this.suggestionsView.setState({
|
|
51
|
+
searchTerm: this.searchEl.value,
|
|
52
|
+
loading: this.searchEl.value && this.searchEl.value.length >= this.minLength,
|
|
53
|
+
suggestions: {}
|
|
54
|
+
})
|
|
55
|
+
super.onType(ev)
|
|
56
|
+
// this is show the flyout for less than minimum length
|
|
57
|
+
this.show()
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default EnhancedSearch
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
@use '@financial-times/o-colors/main' as colors;
|
|
2
|
+
@use '@financial-times/o-spacing/main' as spacing;
|
|
3
|
+
@use '@financial-times/o-typography/main' as typography;
|
|
4
|
+
|
|
5
|
+
@mixin enhancedSearch {
|
|
6
|
+
// Hide search-bar on small screens
|
|
7
|
+
.o-header__search[aria-hidden='false'] {
|
|
8
|
+
display: none;
|
|
9
|
+
@include oGridRespondTo('L') {
|
|
10
|
+
display: block;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.enhanced-search {
|
|
15
|
+
&__suggestions {
|
|
16
|
+
@include oGridRespondTo('L') {
|
|
17
|
+
max-width: 540px;
|
|
18
|
+
left: calc(-1 * spacing.oSpacingByName('s3'));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&__title {
|
|
23
|
+
color: colors.oColorsByName('black');
|
|
24
|
+
@include typography.oTypographySans($scale: 0, $style: 'normal', $weight: 'semibold');
|
|
25
|
+
margin: 0 0 spacing.oSpacingByName('s3') 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&__title-no-bold {
|
|
29
|
+
@include typography.oTypographySans($scale: 0, $style: 'normal', $weight: 'regular');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&__margin-top {
|
|
33
|
+
margin-top: spacing.oSpacingByName('s4');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
&__wrapper {
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-direction: column;
|
|
39
|
+
width: 100%;
|
|
40
|
+
padding: spacing.oSpacingByName('s6');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
&__title {
|
|
44
|
+
color: colors.oColorsByName('black');
|
|
45
|
+
@include typography.oTypographySans($scale: 0, $style: 'normal', $weight: 'semibold');
|
|
46
|
+
margin: 0 0 spacing.oSpacingByName('s3') 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&__suggestions-items {
|
|
50
|
+
display: flex;
|
|
51
|
+
gap: spacing.oSpacingByName('m16');
|
|
52
|
+
padding-top: spacing.oSpacingByName('s6');
|
|
53
|
+
flex-direction: column;
|
|
54
|
+
|
|
55
|
+
@include oGridRespondTo('L') {
|
|
56
|
+
flex-direction: row;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
&__target {
|
|
61
|
+
padding: 0;
|
|
62
|
+
padding-block: spacing.oSpacingByName('s2');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
&__target::before,
|
|
66
|
+
&__chip::before {
|
|
67
|
+
border-bottom: unset !important;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
&__target:hover,
|
|
71
|
+
&__target:focus {
|
|
72
|
+
background-color: transparent;
|
|
73
|
+
color: oColorsByName('teal');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
&__target:hover:before,
|
|
77
|
+
&__target:focus:before {
|
|
78
|
+
opacity: 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
&__target--news {
|
|
82
|
+
min-width: spacing.oSpacingByIncrement(25);
|
|
83
|
+
color: colors.oColorsByName('claret-70');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
&__target--news:hover,
|
|
87
|
+
&__target--news:focus {
|
|
88
|
+
color: colors.oColorsByName('claret-30');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
&__target--equities {
|
|
92
|
+
color: colors.oColorsByName('black');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
a.enhanced-search__target--equities{
|
|
96
|
+
display: flex;
|
|
97
|
+
align-items: flex-start;
|
|
98
|
+
gap: spacing.oSpacingByName('s3');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
&__target--equities:hover,
|
|
102
|
+
&__target--equities:focus {
|
|
103
|
+
color: colors.oColorsByName('slate');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
&__chip {
|
|
107
|
+
border-radius: spacing.oSpacingByName('s1');
|
|
108
|
+
background: colors.oColorsMix('ft-grey', 'white', 10);
|
|
109
|
+
padding: spacing.oSpacingByName('s2') spacing.oSpacingByName('s3');
|
|
110
|
+
width: fit-content;
|
|
111
|
+
cursor: pointer;
|
|
112
|
+
text-decoration: none;
|
|
113
|
+
display: block;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
&__chip:hover,
|
|
117
|
+
&__chip:focus {
|
|
118
|
+
background: colors.oColorsMix('ft-grey', 'white', 20);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
&__chip:focus-visible {
|
|
122
|
+
box-shadow: 0 0 0 spacing.oSpacingByIncrement(0.5) colors.oColorsByName('white'),
|
|
123
|
+
0 0 0 spacing.oSpacingByName('s1') colors.oColorsByName('black-70');
|
|
124
|
+
color: colors.oColorsByName('white');
|
|
125
|
+
border-color: transparent;
|
|
126
|
+
border-radius: 0;
|
|
127
|
+
outline: none;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
&__chip-text {
|
|
131
|
+
margin: 0;
|
|
132
|
+
color: colors.oColorsByName('black');
|
|
133
|
+
@include typography.oTypographySans($scale: -1, $style: 'normal', $weight: 'regular');
|
|
134
|
+
outline: none;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
&__default-results {
|
|
138
|
+
display: flex;
|
|
139
|
+
justify-content: flex-start;
|
|
140
|
+
align-items: flex-start;
|
|
141
|
+
gap: spacing.oSpacingByName('s2');
|
|
142
|
+
flex-direction: column;
|
|
143
|
+
|
|
144
|
+
@include oGridRespondTo('L') {
|
|
145
|
+
flex-direction: row;
|
|
146
|
+
align-items: center;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -45,10 +45,16 @@ function MainHeader(props: THeaderProps) {
|
|
|
45
45
|
{includeUserActionsNav ? <UserActionsNav {...props} /> : null}
|
|
46
46
|
<TopWrapper>
|
|
47
47
|
<TopColumnLeft />
|
|
48
|
-
{props.showLogoLink ?
|
|
48
|
+
{props.showLogoLink ? (
|
|
49
|
+
<TopColumnCenter url={props.data.editions?.current?.url} />
|
|
50
|
+
) : (
|
|
51
|
+
<TopColumnCenterNoLink />
|
|
52
|
+
)}
|
|
49
53
|
<TopColumnRight {...props} />
|
|
50
54
|
</TopWrapper>
|
|
55
|
+
|
|
51
56
|
<Search instance="primary" />
|
|
57
|
+
|
|
52
58
|
<MobileNav {...props} />
|
|
53
59
|
<NavDesktop>
|
|
54
60
|
<NavListLeft {...props} />
|
|
@@ -110,7 +116,13 @@ function NoOutboundLinksHeader(props: THeaderProps) {
|
|
|
110
116
|
return (
|
|
111
117
|
<HeaderWrapper {...props}>
|
|
112
118
|
{includeUserActionsNav ? <UserActionsNav {...props} /> : null}
|
|
113
|
-
<TopWrapper>
|
|
119
|
+
<TopWrapper>
|
|
120
|
+
{props.showLogoLink ? (
|
|
121
|
+
<TopColumnCenter url={props.data.editions?.current?.url} />
|
|
122
|
+
) : (
|
|
123
|
+
<TopColumnCenterNoLink />
|
|
124
|
+
)}
|
|
125
|
+
</TopWrapper>
|
|
114
126
|
<NavDesktop>{props.showUserNavigation ? <NavListRight {...props} /> : null}</NavDesktop>
|
|
115
127
|
{includeSubNavigation ? <SubNavigation {...props} /> : null}
|
|
116
128
|
</HeaderWrapper>
|
package/styles.scss
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
// This will be overridden by dotcom-ui-layout, it's necessary here for storybook builds
|
|
2
2
|
$system-code: 'page-kit-header' !default;
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
@import 'n-ui-foundations/mixins';
|
|
5
6
|
|
|
6
7
|
// We don't need the sub-brand or transparent header styles so disable them.
|
|
7
8
|
// TODO: move drawer styles into a separate stylesheet which can be lazy loaded?
|
|
8
|
-
@import
|
|
9
|
+
@import '@financial-times/o-header/main';
|
|
9
10
|
@include oHeader(('top', 'nav', 'subnav', 'search', 'megamenu', 'drawer', 'anon', 'sticky', 'simple'));
|
|
10
11
|
|
|
11
|
-
@import
|
|
12
|
+
@import 'src/header';
|
|
12
13
|
|
|
13
|
-
@import
|
|
14
|
+
@import 'n-topic-search/main';
|
|
14
15
|
@include nTopicSearch;
|
|
16
|
+
|
|
17
|
+
@import './src/enhanced-search/styles';
|
|
18
|
+
@include enhancedSearch;
|