diff --git a/src/components/pages/home/learn/learn.jsx b/src/components/pages/home/learn/learn.jsx
index 3992c2e6f..d333857cf 100644
--- a/src/components/pages/home/learn/learn.jsx
+++ b/src/components/pages/home/learn/learn.jsx
@@ -1,49 +1,64 @@
-import React from 'react';
+import { useStaticQuery, graphql } from 'gatsby';
+import React, { Fragment } from 'react';
+import BlogPostCard from 'components/shared/blog-post-card';
import Container from 'components/shared/container';
import Heading from 'components/shared/heading';
-import List from 'components/shared/list';
+import useWindowSize from 'hooks/use-window-size';
-const title = 'Latest News & Blogs';
+const TABLET_WIDTH = 1024;
+const title = 'Learn about Cilium & eBPF';
-const featuredBlogs = {
- title: 'Featured Blogs',
- items: [
- {
- linkUrl: 'https://isovalent.com/blog/post/2021-09-aws-eks-anywhere-chooses-cilium',
- linkTarget: '_blank',
- linkText: 'AWS picks Cilium for Networking & Security on EKS Anywhere',
- },
- {
- linkUrl: 'https://cilium.io/blog/2021/08/03/best-of-echo',
- linkText: 'eBPF and Cilium Office Hours - Highlights from Season 1',
- },
- {
- linkUrl: 'https://cilium.io/blog/2021/05/20/cilium-110',
- linkText:
- 'Cilium 1.10: WireGuard, BGP Support, Egress IP Gateway, New Cilium CLI, XDP Load Balancer, Alibaba Cloud Integration and more',
- },
- {
- linkUrl: 'https://cilium.io/blog/2021/05/11/cni-benchmark',
- linkText: 'CNI Benchmark: Understanding Cilium Network Performance',
- },
- {
- linkUrl: 'https://cilium.io/blog/2021/04/19/openshift-certification',
- linkText: 'Introducing the Cilium Certified OpenShift Plug-in',
- },
- ],
- buttonUrl: '/blog',
- buttonText: 'Read more',
+const Learn = () => {
+ const { width } = useWindowSize();
+ const isDesktop = width >= TABLET_WIDTH;
+ const {
+ allMdx: { posts },
+ } = useStaticQuery(graphql`
+ query blogQuery {
+ allMdx(sort: { order: DESC, fields: frontmatter___date }, limit: 5) {
+ posts: nodes {
+ frontmatter {
+ path
+ externalUrl
+ title
+ date(locale: "en", formatString: "MMM DD, yyyy")
+ ogImageUrl
+ ogImage {
+ childImageSharp {
+ gatsbyImageData(width: 512)
+ }
+ }
+ ogSummary
+ }
+ }
+ }
+ }
+ `);
+
+ return (
+
+
+ {title}
+
+ {posts.map(({ frontmatter }, index) => (
+
+ {index === 0 ? (
+
+ ) : (
+
+ )}
+
+ ))}
+
+
+
+ );
};
-const Learn = () => (
-
-);
export default Learn;
diff --git a/src/components/shared/blog-post-card/blog-post-card.jsx b/src/components/shared/blog-post-card/blog-post-card.jsx
index ce6fee161..55fe472a8 100644
--- a/src/components/shared/blog-post-card/blog-post-card.jsx
+++ b/src/components/shared/blog-post-card/blog-post-card.jsx
@@ -1,3 +1,4 @@
+import classNames from 'classnames';
import { GatsbyImage, getImage } from 'gatsby-plugin-image';
import PropTypes from 'prop-types';
import React from 'react';
@@ -7,7 +8,55 @@ import ExternalLinkIcon from 'icons/external-link.inline.svg';
import CiliumLogo from './images/cilium-logo.inline.svg';
-function BlogPostCard({
+const coverStyles = {
+ base: 'shrink-0',
+ lg: 'sm:max-w-[512px]',
+ md: 'min-h-[168px] sm:max-h-[168px] sm:max-w-[320px]',
+ sm: 'min-h-[107px] sm:max-h-[107px] sm:max-w-[198px]',
+};
+
+const titleStyles = {
+ lg: 'text-2xl lg:text-3xl font-semibold',
+ md: 'md:text-lg font-bold',
+ sm: 'md:text-lg font-bold',
+};
+
+const BlogCover = ({ ogImage, title, coverUrl, coverClassNames }) => {
+ let content = null;
+ if (ogImage) {
+ content = (
+
+ );
+ } else if (coverUrl) {
+ content = (
+
+ );
+ } else if (!ogImage && !coverUrl) {
+ content = (
+
+
+
+ );
+ }
+ return content;
+};
+
+const BlogPostCard = ({
path,
ogImage,
ogImageUrl,
@@ -16,65 +65,79 @@ function BlogPostCard({
ogSummary: summary,
categories,
externalUrl,
-}) {
+ size,
+ className,
+ isLandscapeView,
+}) => {
const url = externalUrl !== '' ? externalUrl : null;
const coverUrl = ogImageUrl !== '' ? ogImageUrl : null;
-
+ const coverClassNames = classNames(
+ coverStyles.base,
+ coverStyles[size],
+ isLandscapeView && 'self-center'
+ );
return (
- {ogImage && (
-
- )}
- {coverUrl && (
-
- )}
- {!ogImage && !coverUrl && (
-
-
-
- )}
-
-
+
+
{date}
-
+
{title}
-
{summary}
-
- {categories?.map((category) => (
-
+
- {category}
-
- ))}
- {url && (
-
-
External
-
+ {summary}
+
+
+ {categories?.map((category) => (
+
+ {category}
+
+ ))}
+ {url && (
+
+ External
+
+
+ )}
- )}
-
-
+ >
+ )}
+
);
-}
+};
BlogPostCard.propTypes = {
path: PropTypes.string,
@@ -89,6 +152,9 @@ BlogPostCard.propTypes = {
title: PropTypes.string.isRequired,
ogSummary: PropTypes.string,
categories: PropTypes.arrayOf(PropTypes.string),
+ size: PropTypes.oneOf(Object.keys(titleStyles)),
+ className: PropTypes.string,
+ isLandscapeView: PropTypes.bool,
};
BlogPostCard.defaultProps = {
@@ -98,6 +164,9 @@ BlogPostCard.defaultProps = {
externalUrl: null,
ogSummary: null,
categories: null,
+ size: Object.keys(titleStyles)[1],
+ className: null,
+ isLandscapeView: false,
};
export default BlogPostCard;
diff --git a/src/hooks/use-window-size.js b/src/hooks/use-window-size.js
new file mode 100644
index 000000000..6c3af3034
--- /dev/null
+++ b/src/hooks/use-window-size.js
@@ -0,0 +1,29 @@
+import { useState, useEffect } from 'react';
+// Hook
+function useWindowSize() {
+ // Initialize state with undefined width/height so server and client renders match
+ // Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/
+ const [windowSize, setWindowSize] = useState({
+ width: undefined,
+ height: undefined,
+ });
+ useEffect(() => {
+ // Handler to call on window resize
+ function handleResize() {
+ // Set window width/height to state
+ setWindowSize({
+ width: window.innerWidth,
+ height: window.innerHeight,
+ });
+ }
+ // Add event listener
+ window.addEventListener('resize', handleResize);
+ // Call handler right away so state gets updated with initial window size
+ handleResize();
+ // Remove event listener on cleanup
+ return () => window.removeEventListener('resize', handleResize);
+ }, []); // Empty array ensures that effect is only run on mount
+ return windowSize;
+}
+
+export default useWindowSize;
diff --git a/src/styles/global.css b/src/styles/global.css
index e66ebcd54..c3c5543d2 100644
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -1,6 +1,7 @@
@layer base {
body {
@apply text-base text-black antialiased;
+ -webkit-tap-highlight-color: transparent;
}
.highlight-words {