diff --git a/components/Blog/BlogCard/__tests__/__snapshots__/index.test.tsx.snap b/components/Blog/BlogCard/__tests__/__snapshots__/index.test.tsx.snap new file mode 100644 index 0000000000000..430876477be63 --- /dev/null +++ b/components/Blog/BlogCard/__tests__/__snapshots__/index.test.tsx.snap @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`BlogCard component renders correctly 1`] = ` +
+
+ +
+

+ April 21, 2023 +

+

+ components.blog.blogCard.author.by + + + Bat Man + +

+
+
+
+`; diff --git a/components/Blog/BlogCard/__tests__/index.test.tsx b/components/Blog/BlogCard/__tests__/index.test.tsx new file mode 100644 index 0000000000000..3a2b31ef998eb --- /dev/null +++ b/components/Blog/BlogCard/__tests__/index.test.tsx @@ -0,0 +1,32 @@ +import { render } from '@testing-library/react'; +import { IntlProvider } from 'react-intl'; + +import BlogCard from '..'; + +jest.mock('next/router', () => ({ + useRouter: jest.fn().mockReturnValue({}), +})); + +jest.mock('../../../../hooks/useLocale', () => ({ + useLocale: jest.fn().mockReturnValue({ + currentLocale: {}, + }), +})); + +describe('BlogCard component', () => { + it('renders correctly', () => { + const { container } = render( + {}}> + + + ); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/components/Blog/BlogCard/index.module.scss b/components/Blog/BlogCard/index.module.scss new file mode 100644 index 0000000000000..c16ec8aeabb9f --- /dev/null +++ b/components/Blog/BlogCard/index.module.scss @@ -0,0 +1,72 @@ +.blogCard { + display: flex; + flex-direction: column; + padding: var(--space-32) var(--space-24) var(--space-32) 0; + + @media (max-width: 900px) { + padding: var(--space-12) var(--space-24); + } + + .title { + background-color: var(--color-blog-card-background); + border-radius: 5px; + display: flex; + flex: 1 1 0px; + flex-direction: column; + padding: 1rem 1.5rem; + + a { + color: var(--color-text-accent); + font-size: 2em; + margin-bottom: 10px; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + } + + .metadata { + align-self: flex-start; + background-color: var(--color-dropdown-hover); + border-radius: 1rem; + display: flex; + margin-top: auto; + padding: 0.25rem; + + span, + a { + color: var(--color-text-high-contrast); + font-size: var(--font-size-body3); + padding: 0.125rem 0.5rem; + + &.category { + background-color: var(--color-dropdown-background); + border-radius: 1rem; + margin: 0; + } + } + } + + .content { + justify-self: flex-end; + + h4 { + margin: 0; + margin-top: 7px; + opacity: 0.7; + } + + p { + margin: 7px 0; + opacity: 0.8; + + li { + display: inline; + list-style: none; + margin: 0 3px; + } + } + } +} diff --git a/components/Blog/BlogCard/index.stories.tsx b/components/Blog/BlogCard/index.stories.tsx new file mode 100644 index 0000000000000..5a7f848ab6eee --- /dev/null +++ b/components/Blog/BlogCard/index.stories.tsx @@ -0,0 +1,18 @@ +import BlockQuote from './index'; +import type { Meta as MetaObj, StoryObj } from '@storybook/react'; + +type Story = StoryObj; +type Meta = MetaObj; + +export const Default: Story = { + args: { + author: 'Bat Man', + category: 'category-mock', + date: '2023-04-21 23:40:56.77', + slug: '/blog/category-mock/sample-blog', + title: 'Sample Test Blog', + readingTime: '1 min read', + }, +}; + +export default { component: BlockQuote } as Meta; diff --git a/components/Blog/BlogCard/index.tsx b/components/Blog/BlogCard/index.tsx new file mode 100644 index 0000000000000..147ac59b1340e --- /dev/null +++ b/components/Blog/BlogCard/index.tsx @@ -0,0 +1,50 @@ +import { FormattedDate, FormattedMessage } from 'react-intl'; +import styles from './index.module.scss'; +import LocalizedLink from '../../LocalizedLink'; +import navigation from '../../../navigation.json'; +import type { BlogPost } from '../../../types'; +import type { FC } from 'react'; + +const getBlogCategoryUrl = (category: string): string => + `${navigation.blog.link}/${category}/`; + +type BlogCardProps = Omit; + +const BlogCard: FC = ({ + title, + author, + date, + category, + readingTime, + slug, +}) => ( +
+
+ {title} +
+ {category && ( + + {category} + + )} + {readingTime} +
+
+
+

+ +

+ {author && ( +

+ {' '} + {author} +

+ )} +
+
+); + +export default BlogCard; diff --git a/i18n/locales/en.json b/i18n/locales/en.json index 2a39e924cbead..a9988128d6567 100644 --- a/i18n/locales/en.json +++ b/i18n/locales/en.json @@ -42,6 +42,7 @@ "components.article.editLink.title.edit": "Edit this page on GitHub", "components.article.editLink.title.translate": "Interested to help with translations?", "components.common.languageSelector.button.title": "Switch Language", + "components.blog.blogCard.author.by": "by", "components.footer.links.trademark": "Trademark Policy", "components.footer.links.privacy": "Privacy Policy", "components.footer.links.codeOfConduct": "Code of Conduct", diff --git a/types/blog.ts b/types/blog.ts index 0836fea2f2dde..7ab79b7b49482 100644 --- a/types/blog.ts +++ b/types/blog.ts @@ -4,6 +4,7 @@ export interface BlogPost { date: string; category: string; slug: string; + readingTime?: string; // TODO: verify this works when implementing blog file: string; }