Skip to content
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b447d45
add services to config
pvaliani Apr 7, 2026
5eb49f5
add logic for ukchina article page support
pvaliani Apr 7, 2026
fbcac40
new navigation styles for button
pvaliani Apr 7, 2026
92e5b98
add header styling css for new nav and script link specs
pvaliani Apr 7, 2026
3933214
styling updates for script switch link
pvaliani Apr 7, 2026
e120108
adds tests for ukchina articles (legacy)
pvaliani Apr 7, 2026
04dfec8
fix underline header issue on brandsvg
pvaliani Apr 7, 2026
02e1186
Merge branch 'latest' into WS-2323-add-script-switching-new-navigation
pvaliani Apr 7, 2026
f06ed52
cleanup
pvaliani Apr 7, 2026
c65f2c5
update script switch typography font size
pvaliani Apr 8, 2026
f19d41f
update test and snapshots
pvaliani Apr 8, 2026
c4a6f25
tighten script switch button position to more closely match design at…
pvaliani Apr 8, 2026
e15c7b6
Merge remote-tracking branch 'origin/latest' into WS-2323-add-script-…
pvaliani Apr 8, 2026
22155fd
Merge branch 'latest' into WS-2323-add-script-switching-new-navigation
pvaliani Apr 8, 2026
c6fd858
remove article specific check on ukchina not needed
pvaliani Apr 8, 2026
25b666e
update tests
pvaliani Apr 8, 2026
206e4cc
remove isNewNavigation prop to use service list directly
pvaliani Apr 8, 2026
66825e2
update tests with isNewNavigation removed
pvaliani Apr 8, 2026
fc0f0df
update snapshots
pvaliani Apr 8, 2026
b5434ee
updates to styling to separate out classes for easier deletion
pvaliani Apr 8, 2026
989800b
add class selector to psammead brand for new nav script link style
pvaliani Apr 8, 2026
3dea0d1
adjust headerBrand to use min height for script link
pvaliani Apr 8, 2026
3d73268
update snapshots
pvaliani Apr 8, 2026
ca84a24
Merge branch 'latest' into WS-2323-add-script-switching-new-navigation
pvaliani Apr 8, 2026
e9b8e9e
update snapshots
pvaliani Apr 8, 2026
5930dfe
remove hasScriptLink prop
pvaliani Apr 9, 2026
ae80e77
remove hasScriptLink prop style
pvaliani Apr 9, 2026
2170a7c
update snapshots
pvaliani Apr 9, 2026
2533f26
Merge branch 'latest' into WS-2323-add-script-switching-new-navigation
pvaliani Apr 9, 2026
336d893
snapshot update
pvaliani Apr 9, 2026
4ce75a1
Merge branch 'latest' into WS-2323-add-script-switching-new-navigation
pvaliani Apr 9, 2026
317ee75
fix spacing issue w/ script switch relative to hamburger icon at lowe…
pvaliani Apr 9, 2026
d312f31
Merge branch 'latest' into WS-2323-add-script-switching-new-navigation
pvaliani Apr 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 114 additions & 37 deletions src/app/components/Header/ScriptLink/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,149 @@

exports[`Script Link should render correctly 1`] = `
.emotion-0 {
font-size: 0.9375rem;
line-height: 1.25rem;
font-family: Helmet,Freesans,Helvetica,Arial,sans-serif;
font-style: normal;
font-weight: 400;
display: inline-block;
font-size: 0.9375rem;
line-height: 1;
position: relative;
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
-webkit-align-items: stretch;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
box-sizing: border-box;
color: #FFFFFF;
-webkit-text-decoration: none;
text-decoration: none;
height: 2.75rem;
height: 2.25rem;
min-width: 2.125rem;
border: 0.0625rem solid #FFFFFF;
margin: 0.5rem 0 0.5rem 0.5rem;
min-width: 2.75rem;
text-align: center;
white-space: nowrap;
}

@media (min-width: 20rem) and (max-width: 37.4375rem) {
.emotion-0 {
font-size: 1rem;
line-height: 1.25rem;
}
.emotion-0:focus::after,
.emotion-0:hover::after {
content: "";
position: absolute;
inset: 0;
box-sizing: border-box;
border: 0.25rem solid #FFFFFF;
pointer-events: none;
}

@media (min-width: 37.5rem) {
.emotion-0 {
font-size: 1rem;
line-height: 1.25rem;
}
.emotion-1 {
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
box-sizing: border-box;
height: 100%;
padding-inline: 0.375rem;
line-height: 1;
}

.emotion-0:focus span,
.emotion-0:hover span {
margin: 0;
border: 0.1875rem solid #FFFFFF;
}
<div>
<a
class="focusIndicatorRemove emotion-0"
data-variant="cyr"
href="/serbian/cyr"
>
<span
class="emotion-1"
>
Ћир
</span>
</a>
</div>
`;

@media (min-width: 25rem) {
.emotion-0 {
line-height: calc(2.25rem - 0.5rem);
}
exports[`Script Link should render correctly for new navigation 1`] = `
.emotion-0 {
font-family: Helvetica,Arial,STHeiti,华文黑体,"Microsoft YaHei",微软雅黑,SimSun,宋体;
font-style: normal;
font-weight: 400;
font-size: 0.9375rem;
line-height: 1;
position: relative;
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
-webkit-align-items: stretch;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
box-sizing: border-box;
color: #FFFFFF;
-webkit-text-decoration: none;
text-decoration: none;
height: 2.25rem;
min-width: 2.125rem;
border: 0.0625rem solid #FFFFFF;
text-align: center;
white-space: nowrap;
}

@media (max-width: 24.9375rem) {
.emotion-0 {
margin: 0.5rem 0 0.5rem 0;
}
.emotion-0:focus::after,
.emotion-0:hover::after {
content: "";
position: absolute;
inset: 0;
box-sizing: border-box;
border: 0.25rem solid #FFFFFF;
pointer-events: none;
}

.emotion-1 {
margin-top: 0.1875rem;
width: 100%;
display: inline-block;
height: calc(100%);
line-height: calc(2.75rem - 0.5rem);
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
box-sizing: border-box;
height: 100%;
padding-inline: 0.375rem;
line-height: 1;
}

<div>
<a
class="focusIndicatorRemove emotion-0"
data-variant="cyr"
href="/serbian/cyr"
data-variant="simp"
href="/ukchina/simp/articles/c0e8weny66ko"
>
<span
class="emotion-1"
>
Ћир
</span>
</a>
</div>
Expand Down
37 changes: 37 additions & 0 deletions src/app/components/Header/ScriptLink/index.styles.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import pixelsToRem from '#app/utilities/pixelsToRem';
import { css, Theme } from '@emotion/react';

const styles = {
Expand Down Expand Up @@ -26,6 +27,32 @@ const styles = {
margin: `${spacings.FULL}rem 0 ${spacings.FULL}rem 0`,
},
}),
newNavLink: ({ fontVariants, palette }: Theme) =>
css({
...fontVariants.sansRegular,
fontSize: `${pixelsToRem(15)}rem`,
lineHeight: 1,
position: 'relative',
display: 'inline-flex',
alignItems: 'stretch',
justifyContent: 'center',
boxSizing: 'border-box',
color: palette.WHITE,
textDecoration: 'none',
height: `${pixelsToRem(36)}rem`,
minWidth: `${pixelsToRem(34)}rem`,
border: `${pixelsToRem(1)}rem solid ${palette.WHITE}`,
textAlign: 'center',
whiteSpace: 'nowrap',
'&:focus::after, &:hover::after': {
content: '""',
position: 'absolute',
inset: 0,
boxSizing: 'border-box',
border: `${pixelsToRem(4)}rem solid ${palette.WHITE}`,
pointerEvents: 'none',
},
}),
container: ({ spacings }: Theme) =>
css({
marginTop: '0.1875rem',
Expand All @@ -34,5 +61,15 @@ const styles = {
height: 'calc(100%)',
lineHeight: `calc(2.75rem - ${spacings.FULL}rem)`,
}),
newNavContainer: () =>
css({
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
boxSizing: 'border-box',
height: '100%',
paddingInline: `${pixelsToRem(6)}rem`,
lineHeight: 1,
}),
};
export default styles;
10 changes: 10 additions & 0 deletions src/app/components/Header/ScriptLink/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ describe(`Script Link`, () => {
expect(container).toMatchSnapshot();
});

it('should render correctly for new navigation', () => {
const { container } = render(<ScriptLink />, {
toggles: enabledToggleState,
service: 'ukchina',
variant: 'trad',
pathname: '/ukchina/trad/articles/c0e8weny66ko',
});
expect(container).toMatchSnapshot();
});

describe('assertions', () => {
describe.each(['canonical', 'amp', 'lite'])('%s', platform => {
it.each`
Expand Down
12 changes: 9 additions & 3 deletions src/app/components/Header/ScriptLink/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { use } from 'react';
import useToggle from '#hooks/useToggle';
import { RequestContext } from '#app/contexts/RequestContext';
import SERVICES_WITH_NEW_NAV from '#app/components/Navigation/config';
import { ServiceContext } from '../../../contexts/ServiceContext';
import styles from './index.styles';

const ScriptLink = () => {
const { scriptLink } = use(ServiceContext);
const { scriptLink, service } = use(ServiceContext);
const { pathname, variant: currentVariant } = use(RequestContext);
const { enabled: scriptLinkEnabled } = useToggle('scriptLink');

Expand All @@ -26,15 +27,20 @@ const ScriptLink = () => {

pathPartsWithoutExtension[currentVariantIndex] = alternateVariant;
Comment on lines 24 to 28
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currentVariant can be null in RequestContext, and indexOf will return -1 if the variant segment isn’t present in the URL. In that case pathPartsWithoutExtension[currentVariantIndex] = alternateVariant writes to index -1 and the joined path won’t change, producing an incorrect href (no variant switch). Add a guard for currentVariantIndex < 0 (e.g. return null or derive the replacement segment more defensively).

Copilot uses AI. Check for mistakes.
const pathToVariant = pathPartsWithoutExtension.join('/');
const useNewNavigationStyles = SERVICES_WITH_NEW_NAV.includes(service);
const linkStyles = useNewNavigationStyles ? styles.newNavLink : styles.link;
const containerStyles = useNewNavigationStyles
? styles.newNavContainer
: styles.container;

return (
<a
css={styles.link}
css={linkStyles}
href={pathToVariant}
data-variant={alternateVariant}
className="focusIndicatorRemove"
>
<span css={styles.container}>{text}</span>
<span css={containerStyles}>{text}</span>
</a>
);
};
Expand Down
4 changes: 4 additions & 0 deletions src/app/components/Navigation/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ const SERVICES_WITH_NEW_NAV: Services[] = [
'marathi',
'pidgin',
'punjabi',
'serbian',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to remove these services before merging so that we don't release the new nav to them early.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(just as a reminder to remove, i'll fix the conflicts once it's gone to preview and been swarmed)

'somali',
'swahili',
'tamil',
'telugu',
'tigrinya',
'ukchina',
'urdu',
Comment on lines +16 to 23
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SERVICES_WITH_NEW_NAV now includes ukchina, but HeaderContainer explicitly disables the new nav for ukchina non-article pages. This means the constant no longer reliably represents “services that use the new nav”, yet it’s also used elsewhere (e.g. to set useNewNav=true when fetching navigation config). Consider refactoring to a shared predicate (e.g. shouldUseNewNav({ service, pageType, pagePath })) or splitting into separate lists so ukchina can remain “articles only” without affecting other consumers.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change is only for articles on ukchina.

'uzbek',
'yoruba',
'zhongwen',
] as const;

export default SERVICES_WITH_NEW_NAV;
12 changes: 8 additions & 4 deletions src/app/legacy/containers/Header/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ const HeaderContainer = ({ navItems, propsForTopBarOJComponent }) => {
</SkipLink>
);

const shouldUseNewNav = SERVICES_WITH_NEW_NAV.includes(service);

let shouldRenderScriptSwitch = false;

if (scriptLink) {
Expand All @@ -102,8 +104,10 @@ const HeaderContainer = ({ navItems, propsForTopBarOJComponent }) => {
}

if (isApp) return null;

const shouldUseNewNav = SERVICES_WITH_NEW_NAV.includes(service);
const headerBrandCss = shouldUseNewNav
? theme =>
styles.headerBrand(theme, { hasScriptLink: shouldRenderScriptSwitch })
: null;

const NavigationComponent = shouldUseNewNav
? NewNavigationContainer
Expand All @@ -117,7 +121,7 @@ const HeaderContainer = ({ navItems, propsForTopBarOJComponent }) => {
linkId="brandLink"
skipLink={skipLink}
scriptLink={shouldRenderScriptSwitch && <ScriptLink />}
css={shouldUseNewNav ? styles.headerBrand : null}
css={headerBrandCss}
>
<AccountHeader />
</Header>
Expand All @@ -126,7 +130,7 @@ const HeaderContainer = ({ navItems, propsForTopBarOJComponent }) => {
brandRef={brandRef}
skipLink={skipLink}
scriptLink={shouldRenderScriptSwitch && <ScriptLink />}
css={shouldUseNewNav ? styles.headerBrand : null}
css={headerBrandCss}
>
<AccountHeader />
</Header>
Expand Down
Loading
Loading