Skip to content

Commit 929436a

Browse files
committed
News details
1 parent 8361cbe commit 929436a

35 files changed

+648
-295
lines changed

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"prettier:write": "prettier --write . --log-level warn",
1414
"test": "jest --watch",
1515
"test:ci": "jest",
16-
"analyze": "ANALYZE=true npm run build"
16+
"analyze": "ANALYZE=true npm run build",
17+
"typecheck": "npx tsc --noEmit --watch"
1718
},
1819
"dependencies": {
1920
"@ant-design/icons": "^5.0.1",

src/components/LandingPage/LandingPage.module.css

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
font-optical-sizing: auto;
3333
font-weight: normal;
3434
font-style: normal;
35-
text-wrap: balance;
35+
text-wrap: auto;
3636
font-size: var(--font-size-M);
3737
scroll-behavior: smooth;
3838
}
@@ -106,7 +106,7 @@
106106

107107
.landingPage p {
108108
font-size: var(--font-size-M);
109-
text-wrap: balance;
109+
text-wrap: auto;
110110
hyphens: none;
111111
/* text-align: justify;
112112
text-justify: distribute; */
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,44 @@
1+
.blueBackground {
2+
width: 100%;
3+
overflow: visible;
4+
height: 33vh;
5+
z-index: 0;
6+
}
7+
8+
.blueBackground > div {
9+
width: 100vw;
10+
height: 100vh;
11+
background-color: var(--color-primary);
12+
z-index: 0;
13+
}
14+
115
.newsPage {
16+
z-index: 1;
17+
}
18+
19+
header.header {
20+
grid-column: 1/-1;
21+
color: #fffe;
22+
}
23+
24+
header.header h1 {
25+
font-size: calc(2.0 * var(--font-size-XL));
26+
margin: 0;
27+
margin-bottom: .5em;
28+
}
29+
30+
header.header h2 {
31+
font-family: var(--font-sans-serif);
32+
}
33+
34+
.notes {
35+
color: #3bf;
36+
font-size: var(--font-size-M);
37+
margin-bottom: 3em;
38+
display: flex;
39+
flex-wrap: wrap;
40+
flex-direction: row;
41+
justify-content: space-between;
42+
align-items: center;
43+
gap: 32px;
244
}

src/components/LandingPage/components/NewsPage/NewsPage.tsx

+36-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import stylesLandingPage from '../../LandingPage.module.css';
1414
import { classNames } from '@/util/utils';
1515

1616
import styles from './NewsPage.module.css';
17+
import ProgressiveImage from '../ProgressiveImage';
18+
import SanityContentRTF from '../SanityContentRTF';
19+
import Menu from '../../layout/Menu';
1720

1821
export interface NewsPageProps {
1922
className?: string;
@@ -23,15 +26,44 @@ export interface NewsPageProps {
2326
export default function NewsPage({ className, slug }: NewsPageProps) {
2427
const news = useSanityContentForNewsItem(slug);
2528

26-
if (!news) return <LandingPage section={EnumSection.News} />;
29+
if (!news) {
30+
return <LandingPage section={EnumSection.News} />;
31+
}
2732

2833
return (
2934
<div className={classNames(className, stylesLandingPage.landingPage)}>
30-
<PaddedBlock className={classNames(className, styles.newsPage)}>
31-
<Title value={news.title} />
32-
<div className={styleBlockSmall}>{news.article && <Text value={news.article} />}</div>
35+
<div className={styles.blueBackground}>
36+
<div />
37+
</div>
38+
<Menu scrollHasStarted section={EnumSection.News} />
39+
<PaddedBlock>
40+
<header className={classNames(styles.header, styleBlockSmall)}>
41+
<h2>NEWS</h2>
42+
<h1>{news.title}</h1>
43+
<div className={styles.notes}>
44+
<div>Published {formatDate(news.date)}</div>
45+
<div>© Copyright 2024, EPFL / BBP</div>
46+
</div>
47+
</header>
48+
<ProgressiveImage
49+
className={classNames(styles.image, styleBlockSmall)}
50+
forceAspectRatio
51+
src={news.imageURL}
52+
width={news.imageWidth}
53+
height={news.imageHeight}
54+
/>
55+
<div className={styleBlockSmall}>
56+
{news.article && <SanityContentRTF value={news.article} />}
57+
</div>
3358
</PaddedBlock>
3459
<FooterPanel section={EnumSection.News} />
3560
</div>
3661
);
3762
}
63+
64+
function formatDate(d: string) {
65+
const date = new Date(d);
66+
const fmt = new Intl.DateTimeFormat('en', { dateStyle: 'long' });
67+
return fmt.format(date);
68+
}
69+

src/components/LandingPage/components/ProgressiveImage/ProgressiveImage.module.css

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.progressiveImage {
22
position: relative;
33
background: var(--custom-background, transparent);
4+
aspect-ratio: var(--custom-aspect-ratio);
45
}
56

67
.progressiveImage > img {

src/components/LandingPage/components/ProgressiveImage/ProgressiveImage.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export interface ProgressiveImageProps {
1212
height: number;
1313
alt?: string;
1414
background?: string;
15+
forceAspectRatio?: boolean;
1516
}
1617

1718
export default function ProgressiveImage({
@@ -21,13 +22,15 @@ export default function ProgressiveImage({
2122
height,
2223
alt = 'Vignette',
2324
background = 'var(--color-primary)',
25+
forceAspectRatio = false,
2426
}: ProgressiveImageProps) {
2527
const [loaded, setLoaded] = React.useState(false);
2628

2729
return (
2830
<div
2931
style={{
3032
'--custom-background': background,
33+
'--custom-aspect-ratio': forceAspectRatio ? `${width}/${height}` : 'none',
3134
}}
3235
className={classNames(className, styles.progressiveImage)}
3336
>

src/components/LandingPage/components/SanityContentRTF/SanityContentRTF.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
ContentForRichTextTitle,
1010
ContentForRichTextVerticalSpace,
1111
ContentForRichTextWidget,
12-
isContentForRichText,
1312
} from '../../content/types';
1413
import Error from '../Error';
1514
import SanityContentTitle from './SanityContentTitle';

src/components/LandingPage/components/SanityContentRTF/SanityContentWidget/SanityContentWidget.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export default function SanityContentWidget({ value }: SanityContentWidgetProps)
4646
case 'smallCard':
4747
return <WidgetFromCellToBrain />;
4848
case 'supportEmailButton':
49+
case 'infoEmailButton':
4950
return <WidgetEmail type={value.name} />;
5051
case 'itemPriceList':
5152
return <WidgetPriceList />;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
*[_type=="footer"][0]
2+
.socialMediaList[_type=="socialMediaItem"]
3+
{
4+
title,
5+
url,
6+
"imageURL": icon.asset->url,
7+
"imageWidth": icon.asset->metadata.dimensions.width,
8+
"imageHeight": icon.asset->metadata.dimensions.height
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { tryType, typeStringOrNull } from '../../content';
2+
import { typeImage } from '../../content/_common';
3+
import { useSanity } from '../../content/content';
4+
5+
import query from './hooks.groq';
6+
7+
export function useSanityContentForSocialMediaLinks() {
8+
return useSanity(query, isContentForSocialMediaLinks) ?? [];
9+
}
10+
11+
export interface ContentForSocialMediaLink {
12+
url: string;
13+
title: string;
14+
imageURL: string;
15+
imageWidth: number;
16+
imageHeight: number;
17+
}
18+
19+
function isContentForSocialMediaLinks(data: unknown): data is ContentForSocialMediaLink[] {
20+
return tryType('ContentForSocialMediaLinks', data, [
21+
'array',
22+
{
23+
url: 'string',
24+
title: typeStringOrNull,
25+
...typeImage,
26+
},
27+
]);
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "./social-media-links"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
.socialMediaLinks {
2+
display: flex;
3+
flex-wrap: nowrap;
4+
flex-direction: row;
5+
justify-content: flex-start;
6+
align-items: center;
7+
gap: 1em;
8+
}
9+
10+
.image {
11+
height: 1.5em;
12+
}
13+
14+
.socialMediaLinks > a {
15+
display: flex;
16+
flex-wrap: nowrap;
17+
flex-direction: row;
18+
justify-content: flex-start;
19+
align-items: center;
20+
gap: 0.5em;
21+
cursor: pointer;
22+
}
23+
24+
.title {
25+
display: none;
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from 'react';
2+
3+
import ProgressiveImage from '../ProgressiveImage';
4+
import { useSanityContentForSocialMediaLinks } from './hooks';
5+
import { classNames } from '@/util/utils';
6+
7+
import styles from './social-media-links.module.css';
8+
9+
export interface SocialMediaLinksProps {
10+
className?: string;
11+
}
12+
13+
export default function SocialMediaLinks({ className }: SocialMediaLinksProps) {
14+
const links = useSanityContentForSocialMediaLinks();
15+
16+
return (
17+
<div className={classNames(className, styles.socialMediaLinks)}>
18+
{links.map((link) => (
19+
<a key={link.url} href={link.url} target="_BLANK">
20+
<ProgressiveImage
21+
className={styles.image}
22+
background="transparent"
23+
forceAspectRatio
24+
src={link.imageURL}
25+
width={link.imageWidth}
26+
height={link.imageHeight}
27+
/>
28+
<div className={styles.title}>{link.title}</div>
29+
</a>
30+
))}
31+
</div>
32+
);
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "./swipeable-cards-list"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
.swipeableCardsList {
2+
display: flex;
3+
flex-wrap: nowrap;
4+
flex-direction: column;
5+
justify-content: flex-start;
6+
align-items: stretch;
7+
margin: 1em 0;
8+
gap: 48px;
9+
}
10+
11+
.scroll {
12+
display: flex;
13+
flex-direction: row;
14+
justify-content: flex-start;
15+
align-items: center;
16+
gap: var(--custom-gap, 48px);
17+
flex-wrap: nowrap;
18+
scroll-behavior: smooth;
19+
overflow-x: scroll;
20+
scroll-snap-type: x mandatory;
21+
padding-bottom: 24px;
22+
-ms-overflow-style: none;
23+
scrollbar-width: none;
24+
}
25+
26+
.swipeableCardsList > footer {
27+
display: flex;
28+
flex-wrap: nowrap;
29+
flex-direction: row;
30+
justify-content: space-between;
31+
align-items: center;
32+
gap: 0;
33+
padding: 0;
34+
padding-right: 16px;
35+
}
36+
37+
.swipeableCardsList nav {
38+
flex: 0 0 auto;
39+
display: flex;
40+
flex-direction: row;
41+
justify-content: flex-start;
42+
align-items: center;
43+
flex-wrap: nowrap;
44+
gap: 8px;
45+
}
46+
47+
.swipeableCardsList nav > button.page {
48+
content: '';
49+
width: 24px;
50+
height: 6px;
51+
border-radius: 99vmax;
52+
background-color: #0004;
53+
}
54+
55+
.swipeableCardsList nav > button.page.selected {
56+
background-color: var(--color-primary);
57+
}
58+
59+
.swipeableCardsList nav > button.arrow {
60+
width: 3em;
61+
display: grid;
62+
place-items: center;
63+
}

0 commit comments

Comments
 (0)