Skip to content

Commit

Permalink
Merge branch 'main' into blog-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
vannyle committed Feb 10, 2022
2 parents 985c17d + 8c4d65d commit a031042
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 86 deletions.
97 changes: 56 additions & 41 deletions src/components/pages/home/learn/learn.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<section className="mt-10 md:mt-20 lg:mt-28">
<Container>
<Heading tag="h2">{title}</Heading>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 mt-6 md:mt-8 lg:mt-11 lg:grid-rows-4">
{posts.map(({ frontmatter }, index) => (
<Fragment key={index}>
{index === 0 ? (
<BlogPostCard
className="lg:row-span-full"
size={isDesktop ? 'lg' : 'sm'}
isLandscapeView={!isDesktop}
{...frontmatter}
/>
) : (
<BlogPostCard size="sm" isLandscapeView {...frontmatter} />
)}
</Fragment>
))}
</div>
</Container>
</section>
);
};
const Learn = () => (
<section className="mt-10 md:mt-20 lg:mt-28">
<Container>
<Heading tag="h2">{title}</Heading>
<div className="grid grid-cols-1 mt-6 md:mt-10 lg:mt-14 lg:grid-cols-12 gap-x-8">
<List className="lg:col-span-10" {...featuredBlogs} />
</div>
</Container>
</section>
);

export default Learn;
159 changes: 114 additions & 45 deletions src/components/shared/blog-post-card/blog-post-card.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import classNames from 'classnames';
import { GatsbyImage, getImage } from 'gatsby-plugin-image';
import PropTypes from 'prop-types';
import React from 'react';
Expand All @@ -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 = (
<GatsbyImage
className={coverClassNames}
imgClassName="rounded-lg"
image={getImage(ogImage)}
objectFit="contain"
alt={title}
/>
);
} else if (coverUrl) {
content = (
<img
className={classNames('rounded-lg object-contain', coverClassNames)}
src={coverUrl}
alt={title}
/>
);
} else if (!ogImage && !coverUrl) {
content = (
<div
className={classNames(
'flex justify-center items-center bg-gray-4 rounded-lg',
coverClassNames
)}
>
<CiliumLogo />
</div>
);
}
return content;
};

const BlogPostCard = ({
path,
ogImage,
ogImageUrl,
Expand All @@ -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 (
<Link
to={url || path}
className="flex flex-col p-6 transition-all duration-200 border rounded-lg md:p-8 border-gray-3 group hover:border-transparent hover:shadow-tertiary"
className={classNames(
'flex p-6 transition-all duration-200 border rounded-lg md:p-8 border-gray-3 group hover:border-transparent hover:shadow-tertiary',
isLandscapeView
? 'flex-col space-y-7 sm:space-y-0 sm:flex-row sm:space-x-7'
: 'flex-col space-y-7',
size === 'lg' && 'lg:p-10',
className
)}
target={url ? '_blank' : ''}
rel={url ? 'noopener noreferrer' : ''}
>
{ogImage && (
<GatsbyImage
className="min-h-[168px] max-h-[168px]"
imgClassName="rounded-lg"
image={getImage(ogImage)}
objectFit="contain"
alt={title}
/>
)}
{coverUrl && (
<img
className="min-h-[168px] max-h-[168px] rounded-lg object-contain"
src={coverUrl}
alt={title}
/>
)}
{!ogImage && !coverUrl && (
<div className="h-[168px] flex justify-center items-center bg-gray-4 rounded-lg">
<CiliumLogo />
</div>
)}

<div className="flex flex-col grow mt-7">
<BlogCover
ogImage={ogImage}
title={title}
coverUrl={coverUrl}
coverClassNames={coverClassNames}
/>
<article className="flex flex-col grow">
<span className="text-sm font-medium leading-none text-gray-1">{date}</span>
<h3 className="mt-3 font-bold leading-normal transition-colors duration-200 line-clamp-3 group-hover:text-primary-1 md:text-lg">
<h3
className={classNames(
'mt-3 leading-normal transition-colors duration-200 md:leading-normal lg:leading-normal line-clamp-3 group-hover:text-primary-1',
titleStyles[size]
)}
>
{title}
</h3>
<p className="mt-2 mb-4 line-clamp-5">{summary}</p>
<div className="flex flex-wrap mt-auto gap-x-2 gap-y-2">
{categories?.map((category) => (
<span
className="inline-flex items-center h-8 text-primary-1 font-bold bg-additional-4 bg-opacity-70 rounded p-2.5 tracking-wider uppercase text-xs leading-none"
key={category}
{!isLandscapeView && (
<>
<p
className={classNames(
'mt-2 mb-4 line-clamp-5 leading-relaxed',
size === 'lg' && 'md:text-lg'
)}
>
{category}
</span>
))}
{url && (
<div className="inline-flex items-center h-8 text-primary-1 font-bold bg-additional-4 bg-opacity-70 rounded p-2.5 tracking-wider uppercase text-xs leading-none">
<span>External</span>
<ExternalLinkIcon className="ml-1" />
{summary}
</p>
<div className="flex flex-wrap mt-auto gap-x-2 gap-y-2">
{categories?.map((category) => (
<span
className="inline-flex items-center h-8 text-primary-1 font-bold bg-additional-4 bg-opacity-70 rounded p-2.5 tracking-wider uppercase text-xs leading-none"
key={category}
>
{category}
</span>
))}
{url && (
<div className="inline-flex items-center h-8 text-primary-1 font-bold bg-additional-4 bg-opacity-70 rounded p-2.5 tracking-wider uppercase text-xs leading-none">
<span>External</span>
<ExternalLinkIcon className="ml-1" />
</div>
)}
</div>
)}
</div>
</div>
</>
)}
</article>
</Link>
);
}
};

BlogPostCard.propTypes = {
path: PropTypes.string,
Expand All @@ -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 = {
Expand All @@ -98,6 +164,9 @@ BlogPostCard.defaultProps = {
externalUrl: null,
ogSummary: null,
categories: null,
size: Object.keys(titleStyles)[1],
className: null,
isLandscapeView: false,
};

export default BlogPostCard;
29 changes: 29 additions & 0 deletions src/hooks/use-window-size.js
Original file line number Diff line number Diff line change
@@ -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;
1 change: 1 addition & 0 deletions src/styles/global.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@layer base {
body {
@apply text-base text-black antialiased;
-webkit-tap-highlight-color: transparent;
}

.highlight-words {
Expand Down

0 comments on commit a031042

Please sign in to comment.